Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Add DataTable support to SqlBulkCopy. #16884

Merged
merged 1 commit into from
Mar 23, 2017
Merged

Add DataTable support to SqlBulkCopy. #16884

merged 1 commit into from
Mar 23, 2017

Conversation

corivera
Copy link
Member

@corivera corivera commented Mar 9, 2017

@@ -471,8 +471,6 @@ internal TdsParserStateObject GetSession(object owner)
else
{
session = _physicalStateObj;
// But for CoreCLR we are now relying on the owner to ensure that cancellation owner comes from one source
session.Owner = owner;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line was causing assert failures in the bulk copy tests. Removing it doesn't cause any test failures, and it's not present in the .NET Framework version of TdsParser.

@saurabh500 Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you point me to the assert ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bulkcopy.Close();
}
}
catch (SqlException)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed these generic catches. I'll see if I can replace these with more specific asserts or message checking.

@@ -827,10 +857,24 @@ internal static Exception TransactionZombied(DbTransaction obj)
internal const float FailoverTimeoutStep = 0.08F; // fraction of timeout to use for fast failover connections

// security issue, don't rely upon public static readonly values - AS/URT 109635
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: You may want to remove these internal bug numbers

{
Debug.Assert(false, "valid CommandType " + value.ToString());
}
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: could just be a Debug.Assert with the inverted condition rather than having Assert(false, ...) and using #if DEBUG.

I'm also a little confused by the condition being checked, as it differs from the condition being checked in ValidateCommandBehavior below; I'd have expected them to be identical.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like InvalidCommandBehavior is only referenced by ValidateCommandBehavior, so I can just combine the two.

@@ -827,10 +857,24 @@ internal static Exception TransactionZombied(DbTransaction obj)
internal const float FailoverTimeoutStep = 0.08F; // fraction of timeout to use for fast failover connections

// security issue, don't rely upon public static readonly values - AS/URT 109635
internal static readonly String StrEmpty = ""; // String.Empty
internal static readonly string StrEmpty = ""; // String.Empty
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed, rather than just using string.Empty?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll replace references to this field in a separate PR

Debug.Assert(_SqlDataReaderRowSource != null, "Should not be reading row as an XmlReader if bulk copy source is not a SqlDataReader");
return new XmlDataFeed(_SqlDataReaderRowSource.GetXmlReader(sourceOrdinal));
default:
Debug.Assert(false, string.Format("Current column is marked as being a DataFeed, but no DataFeed compatible method was provided. Method: {0}", _currentRowMetadata[destRowIndex].Method));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Debug.Assert(false, ...) can instead be Debug.Fail(...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same applies to other uses like this throughout)

if (null != mcd)
{
Delegate[] d = mcd.GetInvocationList();
for (int i = 0; i < d.Length; i++)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: foreach (Delegate del in d)

}

// Unified method to read a value from the current row
// unified method to read a value from the current row
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Why lowercase?

}
resultTask = source.Task;
return resultTask; // nothing to do. user passed us an empty array. Return a completed Task.
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TaskCompletionSource<T> allocation can be avoided and the above can be simplified as:

if (rows.Length == 0)
{
    return cancellationToken.IsCancellationRequested ?
        Task.FromCanceled(cancellationToken) :
        Task.CompletedTask;
}

{
if (0 > value)
{
throw ADP.ArgumentOutOfRange("UpdateBatchSize");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: nameof(UpdateBatchSize)

}

// Unified method to read a value from the current row
// unified method to read a value from the current row
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Capitalize unified.

@@ -1440,12 +1800,57 @@ public Task WriteToServerAsync(DbDataReader reader, CancellationToken cancellati
return resultTask;
}

public Task WriteToServerAsync(DataTable table)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: => WriteToServerAsync(table, 0, CancellationToken.None);

return WriteToServerAsync(table, 0, CancellationToken.None);
}

public Task WriteToServerAsync(DataTable table, CancellationToken cancellationToken)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: => WriteToServerAsync(table, 0, cancellationToken);

return WriteToServerAsync(table, 0, cancellationToken);
}

public Task WriteToServerAsync(DataTable table, DataRowState rowState)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: => WriteToServerAsync(table, rowState, CancellationToken.None);

@@ -471,8 +471,6 @@ internal TdsParserStateObject GetSession(object owner)
else
{
session = _physicalStateObj;
// But for CoreCLR we are now relying on the owner to ensure that cancellation owner comes from one source
session.Owner = owner;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you point me to the assert ?

dstConn.Open();
if (dstConn.ServerVersion.StartsWith("07"))
{
// test skipped on 7.0 server
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which is Version 7.0 of Sql Server? Can we get rid of the condition? If its anything before 2008 R2, I think this can be removed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7.0 is the version right before SQL 2000, so I'll get rid of this check.


namespace System.Data.SqlClient
{
public sealed class SqlDataAdapter : DbDataAdapter, IDbDataAdapter, ICloneable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the SqlDataAdapter here? Is this only being used in tests?

Copy link
Member Author

@corivera corivera Mar 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's used in the tests. I only included the APIs that are relevant to these changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think that SqlAdapter surface can be brought in completely so that the customers can use all the APIs?
You don't need to address this comment as part of this PR, but I think that you might as well drive this class to completion in case any APIs are left out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

}
}

public void WriteToServer(IDataReader reader)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this in the contract. You should add this method in the ref assembly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

@saurabh500
Copy link
Contributor

Test Failures with

error CS2001: Source file '/mnt/j/workspace/dotnet_corefx/master/ubuntu14.04_release_prtest/src/System.Data.SqlClient/tests/ManualTests/SQL/SqlBulkCopyTest/CopySomeFromRowArray.cs' could not be found. [/mnt/j/workspace/dotnet_corefx/master/ubuntu14.04_release_prtest/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj]

Did you miss a file in the commit?


IDataReader rowSourceAsIDataReader = (IDataReader)_rowSource;

// Back-compat with 4.0 and 4.5 - only use IsDbNull when streaming is enabled and only for non-SqlDataReader
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this comment still make sense?

@@ -212,8 +212,17 @@ public sealed partial class SqlBulkCopy : System.IDisposable
public void Close() { }
void System.IDisposable.Dispose() { }
public void WriteToServer(System.Data.Common.DbDataReader reader) { }
public void WriteToServer(System.Data.DataTable table) { }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These new APIs will need a version update to SqlClient ref assembly.
I am not sure how that mechanism is handled now. The versions used to reside in the csproj file.

@weshaggard What is the guidance here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @stephentoub In case you can help with the information here?

@corivera
Copy link
Member Author

corivera commented Mar 9, 2017

}
resultTask = source.Task;
return resultTask; // Nothing to do. user passed us an empty array. Return a completed Task.
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like my previous comment was missed... Any reason why the above couldn't be simplified as follows?

if (rows.Length == 0)
{
    return cancellationToken.IsCancellationRequested ?
        Task.FromCanceled(cancellationToken) :
        Task.CompletedTask;
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, missed this. I'll fix it.

@corivera
Copy link
Member Author

@saurabh500 Test failures were due to some uncapitalized filenames.

/// <summary>
/// Column Encryption Setting to be used for the SqlCommand.
/// </summary>
public enum SqlCommandColumnEncryptionSetting
Copy link
Member Author

@corivera corivera Mar 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed since this wasn't actually being used anywhere. (originally introduced with an earlier commit in this PR)

@corivera
Copy link
Member Author

corivera commented Mar 15, 2017

@weshaggard @ericstj Do we need a version bump for SqlClient due to the contract changes here? We're adding in APIs already present in Framework SqlClient

@weshaggard
Copy link
Member

@weshaggard @ericstj Do we need a version bump for SqlClient due to the contract changes here? We're adding in APIs already rpesent in Framework SqlClient

Given that this package will have a version that runs on .NET Framework (although just a facade) I do think we should bump the minor version of the assembly (and the package assuming that isn't already bumped). @ericstj is that your assessment as well?

@saurabh500
Copy link
Contributor

@weshaggard @ericstj Where is the version bump made for the libraries? The information used to be with the folder of the assemblies in the csproj files. But the version information doesn't exist there any more.

@saurabh500
Copy link
Contributor

@corivera I cant reply to my comments in the review above.

Can you point me to the assert ?

Is this assert still an issue?

@corivera
Copy link
Member Author

@saurabh500 No, removing this line resolves the failing Assert. This line isn't found in Framework, either.
#16884 (diff)

@weshaggard
Copy link
Member

@weshaggard @ericstj Where is the version bump made for the libraries? The information used to be with the folder of the assemblies in the csproj files. But the version information doesn't exist there any more.

https://github.com/dotnet/corefx/blob/master/src/System.Data.SqlClient/dir.props#L5 change that to 4.2.0.0

@corivera
Copy link
Member Author

corivera commented Mar 15, 2017

@weshaggard where do we update the version for the nuget package?

@weshaggard
Copy link
Member

@weshaggard where do we update the version for the nuget package?

They were globally updated in master after the fork of our last release (https://github.com/dotnet/corefx/blob/master/Packaging.props#L23) so you don't need to update it.

@danmoseley
Copy link
Member

D:\j\workspace\AllConfigurat---c1564d53\Tools\Packaging.targets(1090,5): error : PackageIndex from D:\j\workspace\AllConfigurat---c1564d53\pkg\Microsoft.Private.PackageBaseline\packageIndex.json is missing an assembly version entry for 4.2.0.0 for package System.Data.SqlClient.  Please run /t:UpdatePackageIndex on this project to commit an update. [D:\j\workspace\AllConfigurat---c1564d53\src\System.Data.SqlClient\pkg\System.Data.SqlClient.pkgproj]
D:\j\workspace\AllConfigurat---c1564d53\Tools\Packaging.targets(1090,5): error : PackageIndex from D:\j\workspace\AllConfigurat---c1564d53\pkg\Microsoft.Private.PackageBaseline\packageIndex.json is has an assembly version entry(s) for 4.1.2.0 which are no longer in package System.Data.SqlClient.  Please run /t:UpdatePackageIndex on this project to commit an update. [D:\j\workspace\AllConfigurat---c1564d53\src\System.Data.SqlClient\pkg\System.Data.SqlClient.pkgproj]
Command execution failed with exit code 1.

@corivera
Copy link
Member Author

@danmosemsft Looking into it

@saurabh500 saurabh500 added this to the 2.0.0 milestone Mar 21, 2017
@saurabh500
Copy link
Contributor

@corivera, As discussed I am OK with the removal of the Owner = owner statement. This is a bug and should be taken care of.
Open an issue to take of assigning the cancellation owner of TdsParserStateObject based on the investigation. The Cancel method should check who started the session with TdsParserStateObject and verify the cancellation is coming from the same Owner that started the session.

LGTM otherwise.

@corivera
Copy link
Member Author

@corivera
Copy link
Member Author

Work for adding remaining SqlDataAdapter APIs: https://github.com/dotnet/corefx/issues/17459

@corivera corivera merged commit 8e3f9ac into dotnet:master Mar 23, 2017
@corivera corivera deleted the AddDataTableToBulkCopy branch March 23, 2017 23:24
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants