diff --git a/README.md b/README.md
index d03249aeab..ff01c4bf76 100644
--- a/README.md
+++ b/README.md
@@ -28,10 +28,6 @@ For the .NET Framework driver on Windows, a package reference to [Microsoft.Data
For the .NET Core driver on Windows, a package reference to [runtime.native.System.Data.SqlClient.sni](https://www.nuget.org/packages/runtime.native.System.Data.SqlClient.sni/) loads `arm64`, `x64` and `x86` native `SNI.dll` libraries into the client's build directories.
-**Note**
-When referencing the native `SNI.dll` on Windows, the Microsoft Visual C++ Redistributable is required to be installed: [The latest supported Visual C++ downloads](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads)
-
-
## Helpful Links
| Topic | Link to File |
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index b0a0b70040..481308bd83 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -44,7 +44,6 @@
-
@@ -56,7 +55,6 @@
-
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.NetCoreApp.cs
deleted file mode 100644
index e6a35caeda..0000000000
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.NetCoreApp.cs
+++ /dev/null
@@ -1,125 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Microsoft.Data.SqlClient.SNI
-{
- internal partial class SNIPacket
- {
- ///
- /// Read data from a stream asynchronously
- ///
- /// Stream to read from
- /// Completion callback
- public void ReadFromStreamAsync(Stream stream, SNIAsyncCallback callback)
- {
- // Treat local function as a static and pass all params otherwise as async will allocate
- async Task ReadFromStreamAsync(SNIPacket packet, SNIAsyncCallback cb, ValueTask valueTask)
- {
- bool error = false;
- try
- {
- packet._length = await valueTask.ConfigureAwait(false);
- if (packet._length == 0)
- {
- SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, SNICommon.ConnTerminatedError, string.Empty);
- error = true;
- }
- }
- catch (Exception ex)
- {
- SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, ex);
- error = true;
- }
-
- if (error)
- {
- packet.Release();
- }
-
- cb(packet, error ? TdsEnums.SNI_ERROR : TdsEnums.SNI_SUCCESS);
- }
-
- ValueTask vt = stream.ReadAsync(new Memory(_data, 0, _capacity), CancellationToken.None);
-
- if (vt.IsCompletedSuccessfully)
- {
- _length = vt.Result;
- // Zero length to go via async local function as is error condition
- if (_length > 0)
- {
- callback(this, TdsEnums.SNI_SUCCESS);
-
- // Completed
- return;
- }
- else
- {
- // Avoid consuming the same instance twice.
- vt = new ValueTask(_length);
- }
- }
-
- // Not complete or error call the async local function to complete
- _ = ReadFromStreamAsync(this, callback, vt);
- }
-
- ///
- /// Write data to a stream asynchronously
- ///
- /// Stream to write to
- ///
- ///
- ///
- public void WriteToStreamAsync(Stream stream, SNIAsyncCallback callback, SNIProviders provider, bool disposeAfterWriteAsync = false)
- {
- // Treat local function as a static and pass all params otherwise as async will allocate
- async Task WriteToStreamAsync(SNIPacket packet, SNIAsyncCallback cb, SNIProviders providers, bool disposeAfter, ValueTask valueTask)
- {
- uint status = TdsEnums.SNI_SUCCESS;
- try
- {
- await valueTask.ConfigureAwait(false);
- }
- catch (Exception e)
- {
- SNILoadHandle.SingletonInstance.LastError = new SNIError(providers, SNICommon.InternalExceptionError, e);
- status = TdsEnums.SNI_ERROR;
- }
-
- cb(packet, status);
-
- if (disposeAfter)
- {
- packet.Dispose();
- }
- }
-
- ValueTask vt = stream.WriteAsync(new Memory(_data, 0, _length), CancellationToken.None);
-
- if (vt.IsCompletedSuccessfully)
- {
- // Read the result to register as complete for the ValueTask
- vt.GetAwaiter().GetResult();
-
- callback(this, TdsEnums.SNI_SUCCESS);
-
- if (disposeAfterWriteAsync)
- {
- Dispose();
- }
-
- // Completed
- return;
- }
-
- // Not complete or error call the async local function to complete
- _ = WriteToStreamAsync(this, callback, provider, disposeAfterWriteAsync, vt);
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.NetStandard.cs
deleted file mode 100644
index 2a3cf12670..0000000000
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.NetStandard.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Microsoft.Data.SqlClient.SNI
-{
- internal partial class SNIPacket
- {
- ///
- /// Read data from a stream asynchronously
- ///
- /// Stream to read from
- /// Completion callback
- public void ReadFromStreamAsync(Stream stream, SNIAsyncCallback callback)
- {
- // Treat local function as a static and pass all params otherwise as async will allocate
- async Task ReadFromStreamAsync(SNIPacket packet, SNIAsyncCallback cb, Task task)
- {
- bool error = false;
- try
- {
- packet._length = await task.ConfigureAwait(false);
- if (packet._length == 0)
- {
- SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, SNICommon.ConnTerminatedError, string.Empty);
- error = true;
- }
- }
- catch (Exception ex)
- {
- SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, ex);
- error = true;
- }
-
- if (error)
- {
- packet.Release();
- }
-
- cb(packet, error ? TdsEnums.SNI_ERROR : TdsEnums.SNI_SUCCESS);
- }
-
- Task t = stream.ReadAsync(_data, 0, _capacity, CancellationToken.None);
-
- if ((t.Status & TaskStatus.RanToCompletion) != 0)
- {
- _length = t.Result;
- // Zero length to go via async local function as is error condition
- if (_length > 0)
- {
- callback(this, TdsEnums.SNI_SUCCESS);
-
- // Completed
- return;
- }
- }
-
- // Not complete or error call the async local function to complete
- _ = ReadFromStreamAsync(this, callback, t);
- }
-
- ///
- /// Write data to a stream asynchronously
- ///
- /// Stream to write to
- ///
- ///
- ///
- public void WriteToStreamAsync(Stream stream, SNIAsyncCallback callback, SNIProviders provider, bool disposeAfterWriteAsync = false)
- {
- // Treat local function as a static and pass all params otherwise as async will allocate
- async Task WriteToStreamAsync(SNIPacket packet, SNIAsyncCallback cb, SNIProviders providers, bool disposeAfter, Task task)
- {
- uint status = TdsEnums.SNI_SUCCESS;
- try
- {
- await task.ConfigureAwait(false);
- }
- catch (Exception e)
- {
- SNILoadHandle.SingletonInstance.LastError = new SNIError(providers, SNICommon.InternalExceptionError, e);
- status = TdsEnums.SNI_ERROR;
- }
-
- cb(packet, status);
-
- if (disposeAfter)
- {
- packet.Dispose();
- }
- }
-
- Task t = stream.WriteAsync(_data, 0, _length, CancellationToken.None);
-
- if ((t.Status & TaskStatus.RanToCompletion) != 0)
- {
- // Read the result to register as complete for the Task
- t.GetAwaiter().GetResult();
-
- callback(this, TdsEnums.SNI_SUCCESS);
-
- if (disposeAfterWriteAsync)
- {
- Dispose();
- }
-
- // Completed
- return;
- }
-
- // Not complete or error call the async local function to complete
- _ = WriteToStreamAsync(this, callback, provider, disposeAfterWriteAsync, t);
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs
index 17437880a2..4467f9b9d5 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs
@@ -5,13 +5,15 @@
using System;
using System.Buffers;
using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
namespace Microsoft.Data.SqlClient.SNI
{
///
/// SNI Packet
///
- internal partial class SNIPacket : IDisposable, IEquatable
+ internal class SNIPacket : IDisposable, IEquatable
{
private byte[] _data;
private int _length;
@@ -251,6 +253,46 @@ public void ReadFromStream(Stream stream)
_length = stream.Read(_data, 0, _capacity);
}
+ ///
+ /// Read data from a stream asynchronously
+ ///
+ /// Stream to read from
+ /// Completion callback
+ public void ReadFromStreamAsync(Stream stream, SNIAsyncCallback callback)
+ {
+ bool error = false;
+
+ stream.ReadAsync(_data, 0, _capacity, CancellationToken.None).ContinueWith(t =>
+ {
+ Exception e = t.Exception?.InnerException;
+ if (e != null)
+ {
+ SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, e);
+ error = true;
+ }
+ else
+ {
+ _length = t.Result;
+
+ if (_length == 0)
+ {
+ SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, SNICommon.ConnTerminatedError, string.Empty);
+ error = true;
+ }
+ }
+
+ if (error)
+ {
+ Release();
+ }
+
+ callback(this, error ? TdsEnums.SNI_ERROR : TdsEnums.SNI_SUCCESS);
+ },
+ CancellationToken.None,
+ TaskContinuationOptions.DenyChildAttach,
+ TaskScheduler.Default);
+ }
+
///
/// Write data to a stream synchronously
///
@@ -260,6 +302,33 @@ public void WriteToStream(Stream stream)
stream.Write(_data, 0, _length);
}
+ ///
+ /// Write data to a stream asynchronously
+ ///
+ /// Stream to write to
+ /// SNI Asynchronous Callback
+ /// SNI provider identifier
+ /// Bool flag to decide whether or not to dispose after Write Async operation
+ public async void WriteToStreamAsync(Stream stream, SNIAsyncCallback callback, SNIProviders provider, bool disposeAfterWriteAsync = false)
+ {
+ uint status = TdsEnums.SNI_SUCCESS;
+ try
+ {
+ await stream.WriteAsync(_data, 0, _length, CancellationToken.None).ConfigureAwait(false);
+ }
+ catch (Exception e)
+ {
+ SNILoadHandle.SingletonInstance.LastError = new SNIError(provider, SNICommon.InternalExceptionError, e);
+ status = TdsEnums.SNI_ERROR;
+ }
+ callback(this, status);
+
+ if (disposeAfterWriteAsync)
+ {
+ Dispose();
+ }
+ }
+
///
/// Get hash code
///
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index f6571605f5..d768d13a1f 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -84,7 +84,6 @@
-
@@ -340,8 +339,14 @@
+
+ 4.3.1
+
+
+ 4.3.0
+
- 1.1.0
+ [1.1.0,1.2.0)
3.0.8
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/packages.config b/src/Microsoft.Data.SqlClient/netfx/src/packages.config
deleted file mode 100644
index fe599d2346..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/packages.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec
index 7444bcbeb4..c9c12b4a5a 100644
--- a/tools/specs/Microsoft.Data.SqlClient.nuspec
+++ b/tools/specs/Microsoft.Data.SqlClient.nuspec
@@ -21,9 +21,6 @@ Microsoft.Data.SqlClient.SqlTransaction
Microsoft.Data.SqlClient.SqlParameterCollection
Microsoft.Data.SqlClient.SqlClientFactory
-When running on Windows, this library has a dependency on Microsoft.Data.SqlClient.SNI on .NET Framework and runtime.native.System.Data.SqlClient.sni on .NET Core, which requires the Microsoft Visual C++ Redistributable to be installed:
-https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads
-
When using NuGet 3.x this package requires at least version 3.4.
https://go.microsoft.com/fwlink/?linkid=2090501
© Microsoft Corporation. All rights reserved.
@@ -31,7 +28,7 @@ When using NuGet 3.x this package requires at least version 3.4.
-
+