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 4a1e9a7742..61dcb03279 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -226,6 +226,9 @@ Microsoft\Data\SqlClient\SqlColumnEncryptionKeyStoreProvider.cs + + Microsoft\Data\SqlClient\SqlCommandBuilder.cs + Microsoft\Data\SqlClient\SqlCommandSet.cs @@ -500,7 +503,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs b/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs index 339f9a9d93..86f9a852e7 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs @@ -158,6 +158,7 @@ internal class ResourceNames internal const string TCE_DbConnectionString_AttestationProtocol = @"Specifies an attestation protocol for its corresponding enclave attestation service."; internal const string TCE_DbConnectionString_IPAddressPreference = @"Specifies an IP address preference when connecting to SQL instances."; internal const string SqlConnection_ServerProcessId = @"Server Process Id (SPID) of the active connection."; + internal const string SqlCommandBuilder_DataAdapter = @"The DataAdapter for which to automatically generate SqlCommands."; } } } 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 d1443d0754..a09a9569ab 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -297,6 +297,9 @@ Microsoft\Data\SqlClient\SqlColumnEncryptionKeyStoreProvider.cs + + Microsoft\Data\SqlClient\SqlCommandBuilder.cs + Microsoft\Data\SqlClient\SqlCommandSet.cs @@ -467,7 +470,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs deleted file mode 100644 index 11839689f5..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs +++ /dev/null @@ -1,415 +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.ComponentModel; -using System.Data; -using System.Data.Common; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using Microsoft.Data.Common; -using Microsoft.Data.Sql; - -namespace Microsoft.Data.SqlClient -{ - /// - [DesignerCategory("")] - public sealed class SqlCommandBuilder : DbCommandBuilder - { - - /// - public SqlCommandBuilder() : base() - { - GC.SuppressFinalize(this); - base.QuotePrefix = "["; // initialize base with defaults - base.QuoteSuffix = "]"; - } - - /// - public SqlCommandBuilder(SqlDataAdapter adapter) : this() - { - DataAdapter = adapter; - } - - /// SqlServer only supports CatalogLocation.Start - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override CatalogLocation CatalogLocation - { - get - { - return CatalogLocation.Start; - } - set - { - if (CatalogLocation.Start != value) - { - throw ADP.SingleValuedProperty("CatalogLocation", "Start"); - } - } - } - - /// SqlServer only supports '.' - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override string CatalogSeparator - { - get - { - return "."; - } - set - { - if ("." != value) - { - throw ADP.SingleValuedProperty("CatalogSeparator", "."); - } - } - } - - /// - [ - DefaultValue(null), - ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Update), - ResDescriptionAttribute(StringsHelper.ResourceNames.SqlCommandBuilder_DataAdapter), // MDAC 60524 - ] - new public SqlDataAdapter DataAdapter - { - get - { - return (SqlDataAdapter)base.DataAdapter; - } - set - { - base.DataAdapter = value; - } - } - - /// SqlServer only supports '.' - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override string QuotePrefix - { - get - { - return base.QuotePrefix; - } - set - { - if (("[" != value) && ("\"" != value)) - { - throw ADP.DoubleValuedProperty("QuotePrefix", "[", "\""); - } - base.QuotePrefix = value; - } - } - - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override string QuoteSuffix - { - get - { - return base.QuoteSuffix; - } - set - { - if (("]" != value) && ("\"" != value)) - { - throw ADP.DoubleValuedProperty("QuoteSuffix", "]", "\""); - } - base.QuoteSuffix = value; - } - } - - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override string SchemaSeparator - { - get - { - return "."; - } - set - { - if ("." != value) - { - throw ADP.SingleValuedProperty("SchemaSeparator", "."); - } - } - } - - private void SqlRowUpdatingHandler(object sender, SqlRowUpdatingEventArgs ruevent) - { - base.RowUpdatingHandler(ruevent); - } - - /// - new public SqlCommand GetInsertCommand() - { - return (SqlCommand)base.GetInsertCommand(); - } - /// - new public SqlCommand GetInsertCommand(bool useColumnsForParameterNames) - { - return (SqlCommand)base.GetInsertCommand(useColumnsForParameterNames); - } - - /// - new public SqlCommand GetUpdateCommand() - { - return (SqlCommand)base.GetUpdateCommand(); - } - - /// - new public SqlCommand GetUpdateCommand(bool useColumnsForParameterNames) - { - return (SqlCommand)base.GetUpdateCommand(useColumnsForParameterNames); - } - - /// - new public SqlCommand GetDeleteCommand() - { - return (SqlCommand)base.GetDeleteCommand(); - } - - /// - new public SqlCommand GetDeleteCommand(bool useColumnsForParameterNames) - { - return (SqlCommand)base.GetDeleteCommand(useColumnsForParameterNames); - } - - /// - override protected void ApplyParameterInfo(DbParameter parameter, DataRow datarow, StatementType statementType, bool whereClause) - { - SqlParameter p = (SqlParameter)parameter; - object valueType = datarow[SchemaTableColumn.ProviderType]; - p.SqlDbType = (SqlDbType)valueType; - p.Offset = 0; - - if ((p.SqlDbType == SqlDbType.Udt) && !p.SourceColumnNullMapping) - { - p.UdtTypeName = datarow["DataTypeName"] as string; - } - else - { - p.UdtTypeName = String.Empty; - } - - object bvalue = datarow[SchemaTableColumn.NumericPrecision]; - if (DBNull.Value != bvalue) - { - byte bval = (byte)(short)bvalue; - p.PrecisionInternal = ((0xff != bval) ? bval : (byte)0); - } - - bvalue = datarow[SchemaTableColumn.NumericScale]; - if (DBNull.Value != bvalue) - { - byte bval = (byte)(short)bvalue; - p.ScaleInternal = ((0xff != bval) ? bval : (byte)0); - } - } - - /// - override protected string GetParameterName(int parameterOrdinal) - { - return "@p" + parameterOrdinal.ToString(System.Globalization.CultureInfo.InvariantCulture); - } - - /// - override protected string GetParameterName(string parameterName) - { - return "@" + parameterName; - } - - /// - override protected string GetParameterPlaceholder(int parameterOrdinal) - { - return "@p" + parameterOrdinal.ToString(System.Globalization.CultureInfo.InvariantCulture); - } - - private void ConsistentQuoteDelimiters(string quotePrefix, string quoteSuffix) - { - - Debug.Assert(quotePrefix == "\"" || quotePrefix == "["); - if ((("\"" == quotePrefix) && ("\"" != quoteSuffix)) || - (("[" == quotePrefix) && ("]" != quoteSuffix))) - { - throw ADP.InvalidPrefixSuffix(); - } - - } - - /// - static public void DeriveParameters(SqlCommand command) - { // MDAC 65927\ - SqlConnection.ExecutePermission.Demand(); - - if (null == command) - { - throw ADP.ArgumentNull("command"); - } - TdsParser bestEffortCleanupTarget = null; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { -#if DEBUG - TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); - - RuntimeHelpers.PrepareConstrainedRegions(); - try { - tdsReliabilitySection.Start(); -#else - { -#endif - bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(command.Connection); - command.DeriveParameters(); - } -#if DEBUG - finally { - tdsReliabilitySection.Stop(); - } -#endif - } - catch (System.OutOfMemoryException e) - { - if (null != command && null != command.Connection) - { - command.Connection.Abort(e); - } - throw; - } - catch (System.StackOverflowException e) - { - if (null != command && null != command.Connection) - { - command.Connection.Abort(e); - } - throw; - } - catch (System.Threading.ThreadAbortException e) - { - if (null != command && null != command.Connection) - { - command.Connection.Abort(e); - } - SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); - throw; - } - } - - - /* private static void GetLiteralInfo (DataRow dataTypeRow, out string literalPrefix, out string literalSuffix) { - - Object tempValue = dataTypeRow[DbMetaDataColumnNames.LiteralPrefix]; - if (tempValue == DBNull.Value) { - literalPrefix = ""; - } - else { - literalPrefix = (string)dataTypeRow[DbMetaDataColumnNames.LiteralPrefix]; - } - tempValue = dataTypeRow[DbMetaDataColumnNames.LiteralSuffix]; - if (tempValue == DBNull.Value) { - literalSuffix = ""; - } - else { - literalSuffix = (string)dataTypeRow[DbMetaDataColumnNames.LiteralSuffix]; - } - } - */ - - /// - protected override DataTable GetSchemaTable(DbCommand srcCommand) - { - SqlCommand sqlCommand = srcCommand as SqlCommand; - SqlNotificationRequest notificationRequest = sqlCommand.Notification; - bool notificationAutoEnlist = sqlCommand.NotificationAutoEnlist; - - sqlCommand.Notification = null; - sqlCommand.NotificationAutoEnlist = false; - - try - { - using (SqlDataReader dataReader = sqlCommand.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo)) - { - return dataReader.GetSchemaTable(); - } - } - finally - { - sqlCommand.Notification = notificationRequest; - sqlCommand.NotificationAutoEnlist = notificationAutoEnlist; - } - - } - - /// - protected override DbCommand InitializeCommand(DbCommand command) - { - SqlCommand cmd = (SqlCommand)base.InitializeCommand(command); - cmd.NotificationAutoEnlist = false; - return cmd; - } - - /// - public override string QuoteIdentifier(string unquotedIdentifier) - { - ADP.CheckArgumentNull(unquotedIdentifier, "unquotedIdentifier"); - string quoteSuffixLocal = QuoteSuffix; - string quotePrefixLocal = QuotePrefix; - ConsistentQuoteDelimiters(quotePrefixLocal, quoteSuffixLocal); - return ADP.BuildQuotedString(quotePrefixLocal, quoteSuffixLocal, unquotedIdentifier); - ; - } - - /// - override protected void SetRowUpdatingHandler(DbDataAdapter adapter) - { - Debug.Assert(adapter is SqlDataAdapter, "!SqlDataAdapter"); - if (adapter == base.DataAdapter) - { // removal case - ((SqlDataAdapter)adapter).RowUpdating -= SqlRowUpdatingHandler; - } - else - { // adding case - ((SqlDataAdapter)adapter).RowUpdating += SqlRowUpdatingHandler; - } - } - - /// - public override string UnquoteIdentifier(string quotedIdentifier) - { - - ADP.CheckArgumentNull(quotedIdentifier, "quotedIdentifier"); - String unquotedIdentifier; - string quoteSuffixLocal = QuoteSuffix; - string quotePrefixLocal = QuotePrefix; - ConsistentQuoteDelimiters(quotePrefixLocal, quoteSuffixLocal); - // ignoring the return value becasue an unquoted source string is OK here - ADP.RemoveStringQuotes(quotePrefixLocal, quoteSuffixLocal, quotedIdentifier, out unquotedIdentifier); - return unquotedIdentifier; - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs similarity index 53% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs index 317ee22ebb..cfac55e028 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.ComponentModel; using System.Data; using System.Data.Common; using System.Diagnostics; @@ -14,10 +15,11 @@ namespace Microsoft.Data.SqlClient { - /// + /// + [DesignerCategory()] public sealed class SqlCommandBuilder : DbCommandBuilder { - /// + /// public SqlCommandBuilder() : base() { GC.SuppressFinalize(this); @@ -25,14 +27,19 @@ public SqlCommandBuilder() : base() base.QuoteSuffix = "]"; } - /// + /// public SqlCommandBuilder(SqlDataAdapter adapter) : this() { DataAdapter = adapter; } - /// + /// /// SqlServer only supports CatalogLocation.Start + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override CatalogLocation CatalogLocation { get @@ -48,8 +55,13 @@ public override CatalogLocation CatalogLocation } } - /// + /// /// SqlServer only supports '.' + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override string CatalogSeparator { get @@ -65,8 +77,13 @@ public override string CatalogSeparator } } - /// - new public SqlDataAdapter DataAdapter + /// + [ + DefaultValue(null), + ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Update), + ResDescriptionAttribute(StringsHelper.ResourceNames.SqlCommandBuilder_DataAdapter), + ] + public new SqlDataAdapter DataAdapter { get { @@ -78,8 +95,13 @@ public override string CatalogSeparator } } - /// + /// /// SqlServer only supports '.' + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override string QuotePrefix { get @@ -96,7 +118,12 @@ public override string QuotePrefix } } - /// + /// + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override string QuoteSuffix { get @@ -113,7 +140,12 @@ public override string QuoteSuffix } } - /// + /// + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override string SchemaSeparator { get @@ -134,31 +166,31 @@ private void SqlRowUpdatingHandler(object sender, SqlRowUpdatingEventArgs rueven base.RowUpdatingHandler(ruevent); } - /// - new public SqlCommand GetInsertCommand() + /// + public new SqlCommand GetInsertCommand() => (SqlCommand)base.GetInsertCommand(); - /// - new public SqlCommand GetInsertCommand(bool useColumnsForParameterNames) + /// + public new SqlCommand GetInsertCommand(bool useColumnsForParameterNames) => (SqlCommand)base.GetInsertCommand(useColumnsForParameterNames); - /// - new public SqlCommand GetUpdateCommand() + /// + public new SqlCommand GetUpdateCommand() => (SqlCommand)base.GetUpdateCommand(); - /// - new public SqlCommand GetUpdateCommand(bool useColumnsForParameterNames) + /// + public new SqlCommand GetUpdateCommand(bool useColumnsForParameterNames) => (SqlCommand)base.GetUpdateCommand(useColumnsForParameterNames); - /// - new public SqlCommand GetDeleteCommand() + /// + public new SqlCommand GetDeleteCommand() => (SqlCommand)base.GetDeleteCommand(); - /// - new public SqlCommand GetDeleteCommand(bool useColumnsForParameterNames) + /// + public new SqlCommand GetDeleteCommand(bool useColumnsForParameterNames) => (SqlCommand)base.GetDeleteCommand(useColumnsForParameterNames); - /// + /// protected override void ApplyParameterInfo(DbParameter parameter, DataRow datarow, StatementType statementType, bool whereClause) { SqlParameter p = (SqlParameter)parameter; @@ -190,15 +222,15 @@ protected override void ApplyParameterInfo(DbParameter parameter, DataRow dataro } } - /// + /// protected override string GetParameterName(int parameterOrdinal) => ("@p" + parameterOrdinal.ToString(CultureInfo.InvariantCulture)); - /// + /// protected override string GetParameterName(string parameterName) => ("@" + parameterName); - /// + /// protected override string GetParameterPlaceholder(int parameterOrdinal) => ("@p" + parameterOrdinal.ToString(CultureInfo.InvariantCulture)); @@ -212,18 +244,43 @@ private void ConsistentQuoteDelimiters(string quotePrefix, string quoteSuffix) } } - /// + /// public static void DeriveParameters(SqlCommand command) { +#if NETFRAMEWORK + SqlConnection.ExecutePermission.Demand(); +#endif if (null == command) { throw ADP.ArgumentNull(nameof(command)); } - +#if NETFRAMEWORK + TdsParser bestEffortCleanupTarget = null; +#endif RuntimeHelpers.PrepareConstrainedRegions(); try { - command.DeriveParameters(); +#if NETFRAMEWORK +#if DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); + + RuntimeHelpers.PrepareConstrainedRegions(); + try { + tdsReliabilitySection.Start(); +#else + { +#endif // DEBUG + bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(command.Connection); +#endif // NETFRAMEWORK + command.DeriveParameters(); +#if NETFRAMEWORK + } +#if DEBUG + finally { + tdsReliabilitySection.Stop(); + } +#endif // DEBUG +#endif // NETFRAMEWORK } catch (OutOfMemoryException e) { @@ -238,37 +295,44 @@ public static void DeriveParameters(SqlCommand command) catch (ThreadAbortException e) { command?.Connection?.Abort(e); +#if NETFRAMEWORK + SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); +#endif throw; } } - /// + /// protected override DataTable GetSchemaTable(DbCommand srcCommand) { SqlCommand sqlCommand = srcCommand as SqlCommand; SqlNotificationRequest notificationRequest = sqlCommand.Notification; - sqlCommand.Notification = null; +#if NETFRAMEWORK + bool notificationAutoEnlist = sqlCommand.NotificationAutoEnlist; + sqlCommand.NotificationAutoEnlist = false; +#endif try { - using (SqlDataReader dataReader = sqlCommand.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo)) - { - return dataReader.GetSchemaTable(); - } + using SqlDataReader dataReader = sqlCommand.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo); + return dataReader.GetSchemaTable(); } finally { sqlCommand.Notification = notificationRequest; +#if NETFRAMEWORK + sqlCommand.NotificationAutoEnlist = notificationAutoEnlist; +#endif } } - /// + /// protected override DbCommand InitializeCommand(DbCommand command) => (SqlCommand)base.InitializeCommand(command); - /// + /// public override string QuoteIdentifier(string unquotedIdentifier) { ADP.CheckArgumentNull(unquotedIdentifier, nameof(unquotedIdentifier)); @@ -278,7 +342,7 @@ public override string QuoteIdentifier(string unquotedIdentifier) return ADP.BuildQuotedString(quotePrefixLocal, quoteSuffixLocal, unquotedIdentifier); } - /// + /// protected override void SetRowUpdatingHandler(DbDataAdapter adapter) { Debug.Assert(adapter is SqlDataAdapter, "Adapter is not a SqlDataAdapter."); @@ -292,16 +356,15 @@ protected override void SetRowUpdatingHandler(DbDataAdapter adapter) } } - /// + /// public override string UnquoteIdentifier(string quotedIdentifier) { ADP.CheckArgumentNull(quotedIdentifier, nameof(quotedIdentifier)); - string unquotedIdentifier; string quoteSuffixLocal = QuoteSuffix; string quotePrefixLocal = QuotePrefix; ConsistentQuoteDelimiters(quotePrefixLocal, quoteSuffixLocal); // ignoring the return value because an unquoted source string is OK here - ADP.RemoveStringQuotes(quotePrefixLocal, quoteSuffixLocal, quotedIdentifier, out unquotedIdentifier); + ADP.RemoveStringQuotes(quotePrefixLocal, quoteSuffixLocal, quotedIdentifier, out string unquotedIdentifier); return unquotedIdentifier; } }