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. - +