From d0d13e7b2da7b39ba930eaee2e8cfe63f05dfe63 Mon Sep 17 00:00:00 2001 From: Davoud Eshtehari Date: Tue, 14 Dec 2021 14:28:27 -0800 Subject: [PATCH 1/7] Add MSS project in netfx --- build.proj | 22 ++- src/Directory.Build.props | 1 + src/Microsoft.Data.SqlClient.sln | 21 ++- .../netfx/src/Microsoft.Data.SqlClient.csproj | 19 +-- .../Microsoft/Data/SqlClient/Server/sqlser.cs | 1 + .../Microsoft/Data/SqlClient/SqlConnection.cs | 4 +- .../src/Microsoft/Data/SqlClient/TdsParser.cs | 3 +- .../src/Microsoft/Data/Common/AdapterUtil.cs | 4 + .../src/Microsoft/Data/SqlClient/SqlEnums.cs | 5 +- .../Microsoft/Data/SqlClient/SqlUdtInfo.cs | 5 +- .../FunctionalTests/SqlDataRecordTest.cs | 4 + .../FunctionalTests/SqlFacetAttributeTest.cs | 4 + ....Data.SqlClient.ManualTesting.Tests.csproj | 3 +- .../SQL/UdtTest/SqlServerTypesTest.cs | 119 ++++++++++++++- .../SQL/UdtTest/UDTs/Address/Address.cs | 4 + .../SQL/UdtTest/UDTs/Circle/Circle.cs | 4 + .../SQL/UdtTest/UDTs/Circle/Point1.cs | 4 + .../SQL/UdtTest/UDTs/Shapes/Line.cs | 4 + .../SQL/UdtTest/UDTs/Shapes/Point.cs | 4 + .../SQL/UdtTest/UDTs/Utf8String/Utf8String.cs | 4 + .../tests/ManualTests/SQL/UdtTest/UdtTest2.cs | 4 + .../IBinarySerialize.cs | 21 +++ .../Microsoft.SqlServer.Server.csproj | 47 ++++++ .../SqlFacetAttribute.cs | 51 +++++++ .../SqlFunctionAttribute.cs | 104 +++++++++++++ .../SqlMethodAttribute.cs | 47 ++++++ .../SqlUserDefinedAggregateAttribute.cs | 134 +++++++++++++++++ .../SqlUserDefinedTypeAttribute.cs | 140 ++++++++++++++++++ .../Strings.Designer.cs | 90 +++++++++++ src/Microsoft.SqlServer.Server/Strings.resx | 129 ++++++++++++++++ .../StringsHelper.cs | 127 ++++++++++++++++ .../TypeForwards.cs | 11 ++ tools/props/Versions.props | 11 +- tools/specs/Microsoft.SqlServer.Server.nuspec | 49 ++++++ tools/targets/GenerateNugetPackage.targets | 9 ++ 35 files changed, 1180 insertions(+), 33 deletions(-) create mode 100644 src/Microsoft.SqlServer.Server/IBinarySerialize.cs create mode 100644 src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj create mode 100644 src/Microsoft.SqlServer.Server/SqlFacetAttribute.cs create mode 100644 src/Microsoft.SqlServer.Server/SqlFunctionAttribute.cs create mode 100644 src/Microsoft.SqlServer.Server/SqlMethodAttribute.cs create mode 100644 src/Microsoft.SqlServer.Server/SqlUserDefinedAggregateAttribute.cs create mode 100644 src/Microsoft.SqlServer.Server/SqlUserDefinedTypeAttribute.cs create mode 100644 src/Microsoft.SqlServer.Server/Strings.Designer.cs create mode 100644 src/Microsoft.SqlServer.Server/Strings.resx create mode 100644 src/Microsoft.SqlServer.Server/StringsHelper.cs create mode 100644 src/Microsoft.SqlServer.Server/TypeForwards.cs create mode 100644 tools/specs/Microsoft.SqlServer.Server.nuspec diff --git a/build.proj b/build.proj index 2aa4ee019b..6ff0fd5c84 100644 --- a/build.proj +++ b/build.proj @@ -37,6 +37,7 @@ + @@ -65,13 +66,18 @@ - - - + + + + - + + + + + @@ -101,6 +107,14 @@ + + + + + + + + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 4f15f38412..0cca6a4cb5 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -41,6 +41,7 @@ $(RepoRoot)artifacts\$(ReferenceType)\ $(Artifacts)tools\ $(ProjectDir)Microsoft.Data.SqlClient\ + $(ProjectDir)Microsoft.SqlServer.Server\ $(ManagedSourceCode)netcore\ $(ManagedSourceCode)netfx\ $(ManagedSourceCode)netfx\src\Resources\ diff --git a/src/Microsoft.Data.SqlClient.sln b/src/Microsoft.Data.SqlClient.sln index e3a765ce11..18cc04fbc8 100644 --- a/src/Microsoft.Data.SqlClient.sln +++ b/src/Microsoft.Data.SqlClient.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29521.150 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31912.275 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.SqlClient", "Microsoft.Data.SqlClient\netfx\src\Microsoft.Data.SqlClient.csproj", "{407890AC-9876-4FEF-A6F1-F36A876BAADE}" EndProject @@ -200,6 +200,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.Do EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.SqlClient.PerformanceTests", "Microsoft.Data.SqlClient\tests\PerformanceTests\Microsoft.Data.SqlClient.PerformanceTests.csproj", "{599A336B-2A5F-473D-8442-1223ED37C93E}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4F3CD363-B1E6-4D6D-9466-97D78A56BE45}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlServer.Server", "Microsoft.SqlServer.Server\Microsoft.SqlServer.Server.csproj", "{A314812A-7820-4565-A2A8-ABBE391C11E4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -472,6 +476,18 @@ Global {599A336B-2A5F-473D-8442-1223ED37C93E}.Release|x64.Build.0 = Release|x64 {599A336B-2A5F-473D-8442-1223ED37C93E}.Release|x86.ActiveCfg = Release|x86 {599A336B-2A5F-473D-8442-1223ED37C93E}.Release|x86.Build.0 = Release|x86 + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Debug|x64.ActiveCfg = Debug|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Debug|x64.Build.0 = Debug|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Debug|x86.ActiveCfg = Debug|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Debug|x86.Build.0 = Debug|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|Any CPU.Build.0 = Release|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x64.ActiveCfg = Release|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x64.Build.0 = Release|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x86.ActiveCfg = Release|Any CPU + {A314812A-7820-4565-A2A8-ABBE391C11E4}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -507,6 +523,7 @@ Global {B499E477-C9B1-4087-A5CF-5C762D90E433} = {0CC4817A-12F3-4357-912C-09315FAAD008} {B93A3149-67E8-491E-A1E5-19D65F9D9E98} = {0CC4817A-12F3-4357-912C-09315FAAD008} {599A336B-2A5F-473D-8442-1223ED37C93E} = {0CC4817A-12F3-4357-912C-09315FAAD008} + {A314812A-7820-4565-A2A8-ABBE391C11E4} = {4F3CD363-B1E6-4D6D-9466-97D78A56BE45} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {01D48116-37A2-4D33-B9EC-94793C702431} 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 df8e73b2d3..3448abf5c3 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -177,9 +177,6 @@ Microsoft\Data\SqlClient\Server\ExtendedClrTypeCode.cs - - Microsoft\Data\SqlClient\Server\IBinarySerialize.cs - Microsoft\Data\SqlClient\Server\ITypedGetters.cs @@ -207,24 +204,9 @@ Microsoft\Data\SqlClient\Server\SmiXetterAccess.Common.cs - - Microsoft\Data\SqlClient\Server\SqlFacetAttribute.cs - - - Microsoft\Data\SqlClient\Server\SqlFunctionAttribute.cs - Microsoft\Data\SqlClient\Server\SqlMetaData.cs - - Microsoft\Data\SqlClient\Server\SqlMethodAttribute.cs - - - Microsoft\Data\SqlClient\Server\SqlUserDefinedTypeAttribute.cs - - - Microsoft\Data\SqlClient\Server\SqlUserDefinedAggregateAttribute.cs - Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs @@ -338,6 +320,7 @@ Microsoft\Data\SqlClient\SqlCommandBuilder.cs + Component Microsoft\Data\SqlClient\SqlCommandSet.cs diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs index 2967aaaa55..ae97fcae9e 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using Microsoft.Data.Common; +using Microsoft.SqlServer.Server; namespace Microsoft.Data.SqlClient.Server { diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs index b6c2b5d930..c9c6cd3c40 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -2959,12 +2959,12 @@ internal object GetUdtValue(object value, SqlMetaDataPriv metaData, bool returnD internal byte[] GetBytes(object o) { - Format format = Format.Native; + Microsoft.SqlServer.Server.Format format = Microsoft.SqlServer.Server.Format.Native; int maxSize = 0; return GetBytes(o, out format, out maxSize); } - internal byte[] GetBytes(object o, out Format format, out int maxSize) + internal byte[] GetBytes(object o, out Microsoft.SqlServer.Server.Format format, out int maxSize) { SqlUdtInfo attr = AssemblyCache.GetInfoFromType(o.GetType()); maxSize = attr.MaxByteSize; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs index 56ff3c94c6..410369e3f1 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -23,6 +23,7 @@ using Microsoft.Data.SqlClient.DataClassification; using Microsoft.Data.SqlClient.Server; using Microsoft.Data.SqlTypes; +using Microsoft.SqlServer.Server; namespace Microsoft.Data.SqlClient { @@ -10690,7 +10691,7 @@ private void WriteParameterName(string parameterName, TdsParserStateObject state } } - private static readonly IEnumerable __tvpEmptyValue = new List().AsReadOnly(); + private static readonly IEnumerable __tvpEmptyValue = new List().AsReadOnly(); private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefault, TdsParserStateObject stateObj, bool isAnonymous, bool advancedTraceIsOn) { // diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs index f7e3715ccc..8f82c1eaff 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs @@ -25,6 +25,10 @@ using Microsoft.Win32; using IsolationLevel = System.Data.IsolationLevel; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#endif + namespace Microsoft.Data.Common { /// diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs index 6cc1bcaf35..08d8f5af6f 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs @@ -16,6 +16,9 @@ using System.Xml; using Microsoft.Data.Common; using Microsoft.Data.SqlClient.Server; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#endif namespace Microsoft.Data.SqlClient { @@ -929,7 +932,7 @@ internal static string GetStringFromXml(XmlReader xmlreader) private static readonly MetaType s_metaTable = new(255, 255, -1, false, false, false, TdsEnums.SQLTABLE, TdsEnums.SQLTABLE, MetaTypeName.TABLE, typeof(IEnumerable), typeof(IEnumerable), SqlDbType.Structured, DbType.Object, 0); - private static readonly MetaType s_metaSUDT = new(255, 255, -1, false, false, false, TdsEnums.SQLVOID, TdsEnums.SQLVOID, "", typeof(SqlDataRecord), typeof(SqlDataRecord), SqlDbType.Structured, DbType.Object, 0); + private static readonly MetaType s_metaSUDT = new(255, 255, -1, false, false, false, TdsEnums.SQLVOID, TdsEnums.SQLVOID, "", typeof(Server.SqlDataRecord), typeof(Server.SqlDataRecord), SqlDbType.Structured, DbType.Object, 0); private static readonly MetaType s_metaDate = new(255, 255, 3, true, false, false, TdsEnums.SQLDATE, TdsEnums.SQLDATE, MetaTypeName.DATE, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.Date, DbType.Date, 0); diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUdtInfo.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUdtInfo.cs index c87051dd8a..ef2bdc4a5e 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUdtInfo.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUdtInfo.cs @@ -5,6 +5,9 @@ using System; using System.Collections.Generic; using Microsoft.Data.SqlClient.Server; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#endif namespace Microsoft.Data.SqlClient { @@ -32,7 +35,7 @@ internal static SqlUdtInfo GetFromType(Type target) SqlUdtInfo udtAttr = TryGetFromType(target); if (udtAttr == null) { - throw InvalidUdtException.Create(target, Strings.SqlUdtReason_NoUdtAttribute); + throw Server.InvalidUdtException.Create(target, Strings.SqlUdtReason_NoUdtAttribute); } return udtAttr; } diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs index 56f95b9962..0da219f653 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs @@ -7,7 +7,11 @@ using System.Collections.Generic; using System.Data; using System.Data.SqlTypes; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#else using Microsoft.Data.SqlClient.Server; +#endif using Xunit; namespace Microsoft.Data.SqlClient.Tests diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlFacetAttributeTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlFacetAttributeTest.cs index 7e74fba8f5..d37e20667d 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlFacetAttributeTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlFacetAttributeTest.cs @@ -2,7 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#else using Microsoft.Data.SqlClient.Server; +#endif using Xunit; namespace Microsoft.Data.SqlClient.Tests diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj index 3364313106..ab9ad736bf 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj @@ -317,7 +317,8 @@ - + + diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs index 3015d11c70..0e64b091b6 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs @@ -2,10 +2,16 @@ // 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.Collections.Generic; +#if NETFRAMEWORK +using System; +using System.Globalization; +using Microsoft.SqlServer.Types; +#else using System.Collections.ObjectModel; -using System.Data; using System.Data.Common; +#endif +using System.Collections.Generic; +using System.Data; using System.Data.SqlTypes; using System.IO; using System.Linq; @@ -404,5 +410,114 @@ private static string ToHexString(byte[] bytes) return hex.ToString(); } + +#if NETFRAMEWORK + private static string GetUdtName(Type udtClrType) + { + if (typeof(SqlHierarchyId) == udtClrType) + { + return "hierarchyid"; + } + if (typeof(SqlGeography) == udtClrType) + { + return "geography"; + } + if (typeof(SqlGeometry) == udtClrType) + { + return "geometry"; + } + + throw new ArgumentException("Unknwon UDT CLR Type " + udtClrType.FullName); + } + + // Synapse: Parse error at line: 1, column: 8: Incorrect syntax near 'geometry'. + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] + public static void TestSqlServerTypesInsertAndRead() + { + string tableName = DataTestUtility.GetUniqueNameForSqlServer("Type"); + string allTypesSQL = @$" + if not exists (select * from sysobjects where name='{tableName}' and xtype='U') + Begin + create table {tableName} + ( + id int identity not null, + c1 hierarchyid not null, + c2 uniqueidentifier not null, + c3 geography not null, + c4 geometry not null, + ); + End + "; + + Dictionary rowValues = new(); + rowValues["c1"] = SqlHierarchyId.Parse(new SqlString("/1/1/3/")); + rowValues["c2"] = Guid.NewGuid(); + rowValues["c3"] = SqlGeography.Point(1.1, 2.2, 4120); + rowValues["c4"] = SqlGeometry.Point(5.2, 1.1, 4120); + + using SqlConnection conn = new(DataTestUtility.TCPConnectionString); + conn.Open(); + try + { + using SqlCommand cmd1 = conn.CreateCommand(); + + // Create db and table + cmd1.CommandText = allTypesSQL.ToString(); + cmd1.ExecuteNonQuery(); + + using SqlCommand cmd2 = conn.CreateCommand(); + + StringBuilder columnsSql = new(); + StringBuilder valuesSql = new(); + + foreach (KeyValuePair pair in rowValues) + { + string paramName = "@" + pair.Key; + object paramValue = pair.Value; + columnsSql.Append(pair.Key); + valuesSql.Append(paramName); + + columnsSql.Append(","); + valuesSql.Append(","); + + SqlParameter param = new(paramName, paramValue); + cmd2.Parameters.Add(param); + + if (paramValue.GetType().Assembly == typeof(SqlHierarchyId).Assembly) + { + param.UdtTypeName = GetUdtName(paramValue.GetType()); + } + } + + columnsSql.Length--; + valuesSql.Length--; + + string insertSql = string.Format(CultureInfo.InvariantCulture, $"insert {tableName}" + @" ({0}) values({1})", + columnsSql.ToString(), valuesSql.ToString()); + + cmd2.CommandText = insertSql; + cmd2.ExecuteNonQuery(); + + cmd1.CommandText = @$"select * from dbo.{tableName}"; + using SqlDataReader r = cmd1.ExecuteReader(); + while (r.Read()) + { + Assert.Equal(rowValues["c1"].GetType(), r.GetValue(1).GetType()); + Assert.Equal(rowValues["c2"].GetType(), r.GetValue(2).GetType()); + Assert.Equal(rowValues["c3"].GetType(), r.GetValue(3).GetType()); + Assert.Equal(rowValues["c4"].GetType(), r.GetValue(4).GetType()); + + Assert.Equal(rowValues["c1"].ToString(), r.GetValue(1).ToString()); + Assert.Equal(rowValues["c2"].ToString(), r.GetValue(2).ToString()); + Assert.Equal(rowValues["c3"].ToString(), r.GetValue(3).ToString()); + Assert.Equal(rowValues["c4"].ToString(), r.GetValue(4).ToString()); + } + } + finally + { + DataTestUtility.DropTable(conn, tableName); + } + } +#endif } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Address/Address.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Address/Address.cs index 8d66060684..01057ebb2e 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Address/Address.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Address/Address.cs @@ -5,7 +5,11 @@ using System; using System.Data.SqlTypes; using System.IO; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#else using Microsoft.Data.SqlClient.Server; +#endif [Serializable] [SqlUserDefinedType(Format.UserDefined, IsByteOrdered = false, MaxByteSize = 500)] diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Circle/Circle.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Circle/Circle.cs index 5d82e6896d..0964e14847 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Circle/Circle.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Circle/Circle.cs @@ -6,7 +6,11 @@ using System.Data.SqlTypes; using System.IO; using System.Text; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#else using Microsoft.Data.SqlClient.Server; +#endif [Serializable] [SqlUserDefinedType(Format.UserDefined, IsByteOrdered = false, MaxByteSize = 30)] diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Circle/Point1.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Circle/Point1.cs index db88aa35e4..5392e57818 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Circle/Point1.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Circle/Point1.cs @@ -6,7 +6,11 @@ using System.Data.SqlTypes; using System.IO; using System.Text; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#else using Microsoft.Data.SqlClient.Server; +#endif [Serializable] [SqlUserDefinedType(Format.UserDefined, IsByteOrdered = true, MaxByteSize = 9)] diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Shapes/Line.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Shapes/Line.cs index 777455fdfd..addc6e266f 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Shapes/Line.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Shapes/Line.cs @@ -6,7 +6,11 @@ using System.Data.SqlTypes; using System.IO; using System.Text; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#else using Microsoft.Data.SqlClient.Server; +#endif [Serializable] [SqlUserDefinedType(Format.UserDefined, IsByteOrdered = false, MaxByteSize = 20)] diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Shapes/Point.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Shapes/Point.cs index 1f122fecd7..b1b7a4ea7f 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Shapes/Point.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Shapes/Point.cs @@ -6,7 +6,11 @@ using System.Data.SqlTypes; using System.IO; using System.Text; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#else using Microsoft.Data.SqlClient.Server; +#endif [Serializable] [SqlUserDefinedType(Format.UserDefined, IsByteOrdered = true, MaxByteSize = 9)] diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Utf8String/Utf8String.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Utf8String/Utf8String.cs index e49876dda5..4bba8c88ba 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Utf8String/Utf8String.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UDTs/Utf8String/Utf8String.cs @@ -5,7 +5,11 @@ using System; using System.Data.SqlTypes; using System.Globalization; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#else using Microsoft.Data.SqlClient.Server; +#endif namespace Microsoft.Samples.SqlServer { diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest2.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest2.cs index 3437736adf..e0e30dd2e5 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest2.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/UdtTest2.cs @@ -6,7 +6,11 @@ using System.Data; using System.Data.SqlTypes; using System.Text; +#if NETFRAMEWORK +using Microsoft.SqlServer.Server; +#else using Microsoft.Data.SqlClient.Server; +#endif using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests diff --git a/src/Microsoft.SqlServer.Server/IBinarySerialize.cs b/src/Microsoft.SqlServer.Server/IBinarySerialize.cs new file mode 100644 index 0000000000..1e844f0300 --- /dev/null +++ b/src/Microsoft.SqlServer.Server/IBinarySerialize.cs @@ -0,0 +1,21 @@ +// 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.IO; + +namespace Microsoft.SqlServer.Server +{ + /// + // This interface is used by types that want full control over the + // binary serialization format. + public interface IBinarySerialize + { + /// + // Read from the specified binary reader. + void Read(BinaryReader r); + /// + // Write to the specified binary writer. + void Write(BinaryWriter w); + } +} diff --git a/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj b/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj new file mode 100644 index 0000000000..7b2ec38d66 --- /dev/null +++ b/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj @@ -0,0 +1,47 @@ + + + Microsoft.SqlServer.Server + This is the helper library for Microsoft.Data.SqlClient for cross framework compatibility support of UDT types. + Microsoft SqlServer Server + net46;netstandard2.0 + $(ObjFolder)$(Configuration).$(Platform)\$(AssemblyName)\ + $(BinFolder)$(Configuration).$(Platform)\$(AssemblyName)\ + $(OutputPath)$(TargetFramework)\Microsoft.SqlServer.Server.xml + portable + false + true + + + + + + + + + + + + + + + + + + + + + True + True + Strings.resx + + + ResXFileCodeGenerator + Strings.Designer.cs + + + + + + + + diff --git a/src/Microsoft.SqlServer.Server/SqlFacetAttribute.cs b/src/Microsoft.SqlServer.Server/SqlFacetAttribute.cs new file mode 100644 index 0000000000..fd20dbf95a --- /dev/null +++ b/src/Microsoft.SqlServer.Server/SqlFacetAttribute.cs @@ -0,0 +1,51 @@ +// 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; + +namespace Microsoft.SqlServer.Server +{ + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.ReturnValue | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + public class SqlFacetAttribute : Attribute + { + /// + public SqlFacetAttribute() { } + + /// + public bool IsFixedLength + { + get; + set; + } + + /// + public int MaxSize + { + get; + set; + } + + /// + public int Precision + { + get; + set; + } + + /// + public int Scale + { + get; + set; + } + + /// + public bool IsNullable + { + get; + set; + } + } +} diff --git a/src/Microsoft.SqlServer.Server/SqlFunctionAttribute.cs b/src/Microsoft.SqlServer.Server/SqlFunctionAttribute.cs new file mode 100644 index 0000000000..53bdf15d02 --- /dev/null +++ b/src/Microsoft.SqlServer.Server/SqlFunctionAttribute.cs @@ -0,0 +1,104 @@ +// 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; + +namespace Microsoft.SqlServer.Server +{ + /// + [Serializable] + public enum DataAccessKind + { + /// + None = 0, + /// + Read = 1, + } + + /// + [Serializable] + public enum SystemDataAccessKind + { + /// + None = 0, + /// + Read = 1, + } + + /// + // sql specific attribute + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false), Serializable] + public class SqlFunctionAttribute : Attribute + { + private bool _isDeterministic; + private DataAccessKind _dataAccess; + private SystemDataAccessKind _systemDataAccess; + private bool _isPrecise; + private string _name; + private string _tableDefinition; + private string _fillRowMethodName; + + /// + public SqlFunctionAttribute() + { + // default values + _isDeterministic = false; + _dataAccess = DataAccessKind.None; + _systemDataAccess = SystemDataAccessKind.None; + _isPrecise = false; + _name = null; + _tableDefinition = null; + _fillRowMethodName = null; + } + + /// + public bool IsDeterministic + { + get => _isDeterministic; + set => _isDeterministic = value; + } + + /// + public DataAccessKind DataAccess + { + get => _dataAccess; + set => _dataAccess = value; + } + + /// + public SystemDataAccessKind SystemDataAccess + { + get => _systemDataAccess; + set => _systemDataAccess = value; + } + + /// + public bool IsPrecise + { + get => _isPrecise; + set => _isPrecise = value; + } + + /// + public string Name + { + get => _name; + set => _name = value; + } + + /// + public string TableDefinition + { + get => _tableDefinition; + set => _tableDefinition = value; + } + + /// + public string FillRowMethodName + { + get => _fillRowMethodName; + set => _fillRowMethodName = value; + } + } +} diff --git a/src/Microsoft.SqlServer.Server/SqlMethodAttribute.cs b/src/Microsoft.SqlServer.Server/SqlMethodAttribute.cs new file mode 100644 index 0000000000..cd94a4f28b --- /dev/null +++ b/src/Microsoft.SqlServer.Server/SqlMethodAttribute.cs @@ -0,0 +1,47 @@ +// 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; + +namespace Microsoft.SqlServer.Server +{ + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false), Serializable] + public sealed class SqlMethodAttribute : SqlFunctionAttribute + { + private bool _isCalledOnNullInputs; + private bool _isMutator; + private bool _shouldInvokeIfReceiverIsNull; + + /// + public SqlMethodAttribute() + { + // default values + _isCalledOnNullInputs = true; + _isMutator = false; + _shouldInvokeIfReceiverIsNull = false; + } + + /// + public bool OnNullCall + { + get => _isCalledOnNullInputs; + set => _isCalledOnNullInputs = value; + } + + /// + public bool IsMutator + { + get => _isMutator; + set => _isMutator = value; + } + + /// + public bool InvokeIfReceiverIsNull + { + get => _shouldInvokeIfReceiverIsNull; + set => _shouldInvokeIfReceiverIsNull = value; + } + } +} diff --git a/src/Microsoft.SqlServer.Server/SqlUserDefinedAggregateAttribute.cs b/src/Microsoft.SqlServer.Server/SqlUserDefinedAggregateAttribute.cs new file mode 100644 index 0000000000..8058795d17 --- /dev/null +++ b/src/Microsoft.SqlServer.Server/SqlUserDefinedAggregateAttribute.cs @@ -0,0 +1,134 @@ +// 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.Globalization; + +namespace Microsoft.SqlServer.Server +{ + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] + public sealed class SqlUserDefinedAggregateAttribute : Attribute + { + private int _maxByteSize; + private bool _isInvariantToDup; + private bool _isInvariantToNulls; + private bool _isInvariantToOrder = true; + private bool _isNullIfEmpty; + private Format _format; + private string _name; + + /// + // The maximum value for the maxbytesize field, in bytes. + public const int MaxByteSizeValue = 8000; + + /// + // A required attribute on all UD Aggs, used to indicate that the + // given type is a UD Agg, and its storage format. + public SqlUserDefinedAggregateAttribute(Format format) + { + switch (format) + { + case Format.Unknown: + throw new ArgumentOutOfRangeException(typeof(Format).Name, string.Format(Strings.ADP_NotSupportedEnumerationValue, typeof(Format).Name, ((int)format).ToString(), nameof(format))); + case Format.Native: + case Format.UserDefined: + _format = format; + break; + default: + throw new ArgumentOutOfRangeException(typeof(Format).Name, string.Format(Strings.ADP_InvalidEnumerationValue, typeof(Format).Name, ((int)format).ToString(CultureInfo.InvariantCulture))); + } + } + + /// + // The maximum size of this instance, in bytes. Does not have to be + // specified for Native format serialization. The maximum value + // for this property is specified by MaxByteSizeValue. + public int MaxByteSize + { + get + { + return _maxByteSize; + } + set + { + // MaxByteSize of -1 means 2GB and is valid, as well as 0 to MaxByteSizeValue + if (value < -1 || value > MaxByteSizeValue) + { + throw new ArgumentOutOfRangeException(nameof(MaxByteSize), value.ToString(), StringsHelper.GetString(Strings.SQLUDT_MaxByteSizeValue)); + } + _maxByteSize = value; + } + } + + /// + public bool IsInvariantToDuplicates + { + get + { + return _isInvariantToDup; + } + set + { + _isInvariantToDup = value; + } + } + + /// + public bool IsInvariantToNulls + { + get + { + return _isInvariantToNulls; + } + set + { + _isInvariantToNulls = value; + } + } + + /// + public bool IsInvariantToOrder + { + get + { + return _isInvariantToOrder; + } + set + { + _isInvariantToOrder = value; + } + } + + /// + public bool IsNullIfEmpty + { + get + { + return _isNullIfEmpty; + } + set + { + _isNullIfEmpty = value; + } + } + + /// + // The on-disk format for this type. + public Format Format => _format; + + /// + public string Name + { + get + { + return _name; + } + set + { + _name = value; + } + } + } +} diff --git a/src/Microsoft.SqlServer.Server/SqlUserDefinedTypeAttribute.cs b/src/Microsoft.SqlServer.Server/SqlUserDefinedTypeAttribute.cs new file mode 100644 index 0000000000..4e55366394 --- /dev/null +++ b/src/Microsoft.SqlServer.Server/SqlUserDefinedTypeAttribute.cs @@ -0,0 +1,140 @@ +// 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.Globalization; + +namespace Microsoft.SqlServer.Server +{ + /// + public enum Format + { + /// + Unknown = 0, + /// + Native = 1, + /// + UserDefined = 2, + } + + /// + // This custom attribute indicates that the given type is + // a SqlServer udt. The properties on the attribute reflect the + // physical attributes that will be used when the type is registered + // with SqlServer. + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)] + public sealed class SqlUserDefinedTypeAttribute : Attribute + { + private int _maxByteSize; + private bool _isFixedLength; + private bool _isByteOrdered; + private Format _format; + private string _name; + + // The maximum value for the maxbytesize field, in bytes. + internal const int YukonMaxByteSizeValue = 8000; + private string _validationMethodName = null; + + /// + // A required attribute on all udts, used to indicate that the + // given type is a udt, and its storage format. + public SqlUserDefinedTypeAttribute(Format format) + { + switch (format) + { + case Format.Unknown: + throw new ArgumentOutOfRangeException(typeof(Format).Name, string.Format(Strings.ADP_NotSupportedEnumerationValue, typeof(Format).Name, ((int)format).ToString(), nameof(format))); + case Format.Native: + case Format.UserDefined: + _format = format; + break; + default: + throw new ArgumentOutOfRangeException(typeof(Format).Name, string.Format(Strings.ADP_InvalidEnumerationValue, typeof(Format).Name, ((int)format).ToString(CultureInfo.InvariantCulture))); + } + } + + /// + // The maximum size of this instance, in bytes. Does not have to be + // specified for Native serialization. The maximum value + // for this property is specified by MaxByteSizeValue. + public int MaxByteSize + { + get + { + return _maxByteSize; + } + set + { + if (value < -1) + { + throw new ArgumentOutOfRangeException(value.ToString(), StringsHelper.GetString(Strings.SQLUDT_MaxByteSizeValue), nameof(MaxByteSize)); + } + _maxByteSize = value; + } + } + + /// + // Are all instances of this udt the same size on disk? + public bool IsFixedLength + { + get + { + return _isFixedLength; + } + set + { + _isFixedLength = value; + } + } + + /// + // Is this type byte ordered, i.e. is the on disk representation + // consistent with the ordering semantics for this type? + // If true, the binary representation of the type will be used + // in comparison by SqlServer. This property enables indexing on the + // udt and faster comparisons. + public bool IsByteOrdered + { + get + { + return _isByteOrdered; + } + set + { + _isByteOrdered = value; + } + } + + /// + // The on-disk format for this type. + public Format Format => _format; + + /// + // An Optional method used to validate this UDT + public string ValidationMethodName + { + get + { + return _validationMethodName; + } + set + { + _validationMethodName = value; + } + } + + /// + public string Name + { + get + { + return _name; + } + set + { + _name = value; + } + } + } +} diff --git a/src/Microsoft.SqlServer.Server/Strings.Designer.cs b/src/Microsoft.SqlServer.Server/Strings.Designer.cs new file mode 100644 index 0000000000..67e310e065 --- /dev/null +++ b/src/Microsoft.SqlServer.Server/Strings.Designer.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.SqlServer.Server { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.SqlServer.Server.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to The {0} enumeration value, {1}, is invalid.. + /// + internal static string ADP_InvalidEnumerationValue { + get { + return ResourceManager.GetString("ADP_InvalidEnumerationValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The {0} enumeration value, {1}, is not supported by the {2} method.. + /// + internal static string ADP_NotSupportedEnumerationValue { + get { + return ResourceManager.GetString("ADP_NotSupportedEnumerationValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to range: 0-8000. + /// + internal static string SQLUDT_MaxByteSizeValue { + get { + return ResourceManager.GetString("SQLUDT_MaxByteSizeValue", resourceCulture); + } + } + } +} diff --git a/src/Microsoft.SqlServer.Server/Strings.resx b/src/Microsoft.SqlServer.Server/Strings.resx new file mode 100644 index 0000000000..20c25de4ea --- /dev/null +++ b/src/Microsoft.SqlServer.Server/Strings.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The {0} enumeration value, {1}, is invalid. + + + The {0} enumeration value, {1}, is not supported by the {2} method. + + + range: 0-8000 + + diff --git a/src/Microsoft.SqlServer.Server/StringsHelper.cs b/src/Microsoft.SqlServer.Server/StringsHelper.cs new file mode 100644 index 0000000000..610839adbf --- /dev/null +++ b/src/Microsoft.SqlServer.Server/StringsHelper.cs @@ -0,0 +1,127 @@ +// 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.Globalization; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Microsoft.SqlServer.Server +{ + internal class StringsHelper : Strings + { + static StringsHelper s_loader = null; + ResourceManager _resources; + + internal StringsHelper() + { + _resources = new ResourceManager("Microsoft.SqlServer.Server.Strings", GetType().Assembly); + } + + private static StringsHelper GetLoader() + { + if (s_loader == null) + { + StringsHelper sr = new(); + Interlocked.CompareExchange(ref s_loader, sr, null); + } + return s_loader; + } + + public static ResourceManager Resources => GetLoader()._resources; + + + // This method is used to decide if we need to append the exception message parameters to the message when calling Strings.Format. + // by default it returns false. + // Native code generators can replace the value this returns based on user input at the time of native code generation. + // Marked as NoInlining because if this is used in an AoT compiled app that is not compiled into a single file, the user + // could compile each module with a different setting for this. We want to make sure there's a consistent behavior + // that doesn't depend on which native module this method got inlined into. + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool UsingResourceKeys() + { + return false; + } + + public static string GetResourceString(string res) + { + StringsHelper sys = GetLoader(); + if (sys == null) + return null; + + // If "res" is a resource id, temp will not be null, "res" will contain the retrieved resource string. + // If "res" is not a resource id, temp will be null. + string temp = sys._resources.GetString(res, Culture); + if (temp != null) + res = temp; + + return res; + } + public static string GetString(string res, params object[] args) + { + res = GetResourceString(res); + if (args != null && args.Length > 0) + { + for (int i = 0; i < args.Length; i++) + { + string value = args[i] as string; + if (value != null && value.Length > 1024) + { + args[i] = value.Substring(0, 1024 - 3) + "..."; + } + } + return string.Format(CultureInfo.CurrentCulture, res, args); + } + else + { + return res; + } + } + + public static string Format(string resourceFormat, params object[] args) + { + if (args != null) + { + if (UsingResourceKeys()) + { + return resourceFormat + string.Join(", ", args); + } + + return string.Format(resourceFormat, args); + } + + return resourceFormat; + } + + public static string Format(string resourceFormat, object p1) + { + if (UsingResourceKeys()) + { + return string.Join(", ", resourceFormat, p1); + } + + return string.Format(resourceFormat, p1); + } + + public static string Format(string resourceFormat, object p1, object p2) + { + if (UsingResourceKeys()) + { + return string.Join(", ", resourceFormat, p1, p2); + } + + return string.Format(resourceFormat, p1, p2); + } + + public static string Format(string resourceFormat, object p1, object p2, object p3) + { + if (UsingResourceKeys()) + { + return string.Join(", ", resourceFormat, p1, p2, p3); + } + + return string.Format(resourceFormat, p1, p2, p3); + } + } +} diff --git a/src/Microsoft.SqlServer.Server/TypeForwards.cs b/src/Microsoft.SqlServer.Server/TypeForwards.cs new file mode 100644 index 0000000000..efd2f9d4a3 --- /dev/null +++ b/src/Microsoft.SqlServer.Server/TypeForwards.cs @@ -0,0 +1,11 @@ + +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.IBinarySerialize))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.Format))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.SqlFacetAttribute))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.SqlFunctionAttribute))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.SqlMethodAttribute))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.SqlUserDefinedAggregateAttribute))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.DataAccessKind))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.SystemDataAccessKind))] +namespace Microsoft.SqlServer.Server { } diff --git a/tools/props/Versions.props b/tools/props/Versions.props index f13965c102..ba018dc65a 100644 --- a/tools/props/Versions.props +++ b/tools/props/Versions.props @@ -2,13 +2,22 @@ 1.0.0.0 - + 4.0.0.0 5.0.0-dev $(NugetPackageVersion) + + + + + 1.0.0.0 + 1.0.0.0 + 1.0.0-dev + $(SqlServerPackageVersion) + 4.0.0 diff --git a/tools/specs/Microsoft.SqlServer.Server.nuspec b/tools/specs/Microsoft.SqlServer.Server.nuspec new file mode 100644 index 0000000000..91597ca438 --- /dev/null +++ b/tools/specs/Microsoft.SqlServer.Server.nuspec @@ -0,0 +1,49 @@ + + + + Microsoft.SqlServer.Server + 1.0.0 + Microsoft.SqlServer.Server + Microsoft + true + MIT + https://aka.ms/sqlclientproject + dotnet.png + + This is the helper library for Microsoft.Data.SqlClient for cross framework compatibility support of UDT types. + +Available Types: +Microsoft.SqlServer.Server.IBinarySerializer +Microsoft.SqlServer.Server.SqlFacetAttribute +Microsoft.SqlServer.Server.SqlFunctionAttribute +Microsoft.SqlServer.Server.SqlMethodAttribute +Microsoft.SqlServer.Server.SqlUserDefinedAggregateAttribute +Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute +Microsoft.SqlServer.Server.DataAccessKind +Microsoft.SqlServer.Server.SystemDataAccessKind +Microsoft.SqlServer.Server.Format + + + https://go.microsoft.com/fwlink/?linkid=2090501 + © Microsoft Corporation. All rights reserved. + sqlserver microsoft.sqlserver.server + + + + + + + + + + + + + + + + + + + + diff --git a/tools/targets/GenerateNugetPackage.targets b/tools/targets/GenerateNugetPackage.targets index 7ffecfc6b3..5ec95be2dc 100644 --- a/tools/targets/GenerateNugetPackage.targets +++ b/tools/targets/GenerateNugetPackage.targets @@ -9,4 +9,13 @@ -command "&$(ToolsDir)scripts\downloadLatestNuget.ps1 -nugetDestPath '$(NuGetRoot)'"" /> + + + $(SqlServerPackageVersion)-debug + + + + + From aef40d0321361142ca11c401cbef4b1c3e28e677 Mon Sep 17 00:00:00 2001 From: Davoud Eshtehari Date: Fri, 17 Dec 2021 21:07:35 -0800 Subject: [PATCH 2/7] Add InvalidUdtException --- .../Microsoft/Data/SqlClient/Server/SqlSer.cs | 2 +- .../netfx/src/Microsoft.Data.SqlClient.csproj | 3 - .../src/Microsoft/Data/Common/AdapterUtil.cs | 104 +++++++++++------- .../Microsoft/Data/SqlClient/SqlUdtInfo.cs | 6 +- .../InvalidUdtException.cs | 50 +++++++++ .../Microsoft.SqlServer.Server.csproj | 1 + .../Strings.Designer.cs | 28 ++++- src/Microsoft.SqlServer.Server/Strings.resx | 6 + .../TypeForwards.cs | 1 + tools/specs/Microsoft.SqlServer.Server.nuspec | 1 + 10 files changed, 152 insertions(+), 50 deletions(-) create mode 100644 src/Microsoft.SqlServer.Server/InvalidUdtException.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs index c9f1536f50..3a0ccf847c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs @@ -146,7 +146,7 @@ internal static SqlUserDefinedTypeAttribute GetUdtAttribute(Type t) } else { - throw InvalidUdtException.Create(t, Strings.SqlUdtReason_NoUdtAttribute); + throw ADP.CreateInvalidUdtException(t, nameof(Strings.SqlUdtReason_NoUdtAttribute)); } return udtAttr; } 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 3448abf5c3..f888874ec4 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -430,9 +430,6 @@ Microsoft\Data\DataException.cs - - Microsoft\Data\SqlClient\Server\InvalidUdtException.cs - Microsoft\Data\SqlClient\Server\SmiTypedGetterSetter.cs diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs index 8f82c1eaff..7d86c2d7ff 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs @@ -21,12 +21,14 @@ using System.Threading.Tasks; using System.Transactions; using Microsoft.Data.SqlClient; -using Microsoft.Data.SqlClient.Server; using Microsoft.Win32; using IsolationLevel = System.Data.IsolationLevel; #if NETFRAMEWORK using Microsoft.SqlServer.Server; +using System.Reflection; +#else +using Microsoft.Data.SqlClient.Server; #endif namespace Microsoft.Data.Common @@ -61,6 +63,26 @@ internal static class ADP /// internal const int MaxBufferAccessTokenExpiry = 600; + #region UDT +#if NETFRAMEWORK + private static readonly MethodInfo s_method = typeof(InvalidUdtException).GetMethod("Create", BindingFlags.NonPublic | BindingFlags.Static); +#endif + /// + /// Calls "InvalidUdtException.Create" method when an invalid UDT occurs. + /// + internal static InvalidUdtException CreateInvalidUdtException(Type udtType, string resourceReasonName) + { + InvalidUdtException e = +#if NETFRAMEWORK + (InvalidUdtException)s_method.Invoke(null, new object[] { udtType, resourceReasonName }); + ADP.TraceExceptionAsReturnValue(e); +#else + InvalidUdtException.Create(udtType, resourceReasonName); +#endif + return e; + } + #endregion + static private void TraceException(string trace, Exception e) { Debug.Assert(null != e, "TraceException: null Exception"); @@ -105,7 +127,7 @@ internal static Exception ExceptionWithStackTrace(Exception e) } } - #region COM+ exceptions +#region COM+ exceptions internal static ArgumentException Argument(string error) { ArgumentException e = new(error); @@ -304,9 +326,9 @@ internal static ArgumentOutOfRangeException ArgumentOutOfRange(string message, s TraceExceptionAsReturnValue(e); return e; } - #endregion +#endregion - #region Helper Functions +#region Helper Functions internal static ArgumentOutOfRangeException NotSupportedEnumerationValue(Type type, string value, string method) => ArgumentOutOfRange(StringsHelper.GetString(Strings.ADP_NotSupportedEnumerationValue, type.Name, value, method), type.Name); @@ -394,9 +416,9 @@ internal static ArgumentException InvalidArgumentLength(string argumentName, int => Argument(StringsHelper.GetString(Strings.ADP_InvalidArgumentLength, argumentName, limit)); internal static ArgumentException MustBeReadOnly(string argumentName) => Argument(StringsHelper.GetString(Strings.ADP_MustBeReadOnly, argumentName)); - #endregion +#endregion - #region CommandBuilder, Command, BulkCopy +#region CommandBuilder, Command, BulkCopy /// /// This allows the caller to determine if it is an error or not for the quotedString to not be quoted /// @@ -729,9 +751,9 @@ internal static ArgumentException InvalidPrefixSuffix() TraceExceptionAsReturnValue(e); return e; } - #endregion +#endregion - #region DbConnectionOptions, DataAccess +#region DbConnectionOptions, DataAccess internal static ArgumentException ConnectionStringSyntax(int index) => Argument(StringsHelper.GetString(Strings.ADP_ConnectionStringSyntax, index)); internal static ArgumentException KeywordNotSupported(string keyword) => Argument(StringsHelper.GetString(Strings.ADP_KeywordNotSupported, keyword)); @@ -769,9 +791,9 @@ internal static ArgumentException ConvertFailed(Type fromType, Type toType, Exce internal static ArgumentException InvalidMinMaxPoolSizeValues() => ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidMinMaxPoolSizeValues)); - #endregion +#endregion - #region DbConnection +#region DbConnection private static string ConnectionStateMsg(ConnectionState state) { // MDAC 82165, if the ConnectionState enum to msg the localization looks weird return state switch @@ -794,25 +816,25 @@ internal static NotImplementedException MethodNotImplemented([CallerMemberName] TraceExceptionAsReturnValue(e); return e; } - #endregion +#endregion - #region Stream +#region Stream internal static Exception StreamClosed([CallerMemberName] string method = "") => InvalidOperation(StringsHelper.GetString(Strings.ADP_StreamClosed, method)); static internal Exception InvalidSeekOrigin(string parameterName) => ArgumentOutOfRange(StringsHelper.GetString(Strings.ADP_InvalidSeekOrigin), parameterName); internal static IOException ErrorReadingFromStream(Exception internalException) => IO(StringsHelper.GetString(Strings.SqlMisc_StreamErrorMessage), internalException); - #endregion +#endregion - #region Generic Data Provider Collection +#region Generic Data Provider Collection internal static ArgumentException ParametersIsNotParent(Type parameterType, ICollection collection) => Argument(StringsHelper.GetString(Strings.ADP_CollectionIsNotParent, parameterType.Name, collection.GetType().Name)); internal static ArgumentException ParametersIsParent(Type parameterType, ICollection collection) => Argument(StringsHelper.GetString(Strings.ADP_CollectionIsNotParent, parameterType.Name, collection.GetType().Name)); - #endregion +#endregion - #region ConnectionUtil +#region ConnectionUtil internal enum InternalErrorCode { UnpooledObjectHasOwner = 0, @@ -883,9 +905,9 @@ internal static Exception InternalConnectionError(ConnectionError internalError) internal static Exception InvalidConnectRetryCountValue() => Argument(StringsHelper.GetString(Strings.SQLCR_InvalidConnectRetryCountValue)); internal static Exception InvalidConnectRetryIntervalValue() => Argument(StringsHelper.GetString(Strings.SQLCR_InvalidConnectRetryIntervalValue)); - #endregion +#endregion - #region DbDataReader +#region DbDataReader internal static Exception DataReaderClosed([CallerMemberName] string method = "") => InvalidOperation(StringsHelper.GetString(Strings.ADP_DataReaderClosed, method)); @@ -927,9 +949,9 @@ internal static Exception InvalidXmlMissingColumn(string collectionName, string => Argument(StringsHelper.GetString(Strings.MDF_InvalidXmlMissingColumn, collectionName, columnName)); internal static InvalidOperationException AsyncOperationPending() => InvalidOperation(StringsHelper.GetString(Strings.ADP_PendingAsyncOperation)); - #endregion +#endregion - #region IDbCommand +#region IDbCommand // IDbCommand.CommandType static internal ArgumentOutOfRangeException InvalidCommandType(CommandType value) { @@ -998,9 +1020,9 @@ internal static Exception DeriveParametersNotSupported(IDbCommand value) => DataAdapter(StringsHelper.GetString(Strings.ADP_DeriveParametersNotSupported, value.GetType().Name, value.CommandType.ToString())); internal static Exception NoStoredProcedureExists(string sproc) => InvalidOperation(StringsHelper.GetString(Strings.ADP_NoStoredProcedureExists, sproc)); - #endregion +#endregion - #region DbMetaDataFactory +#region DbMetaDataFactory internal static Exception DataTableDoesNotExist(string collectionName) => Argument(StringsHelper.GetString(Strings.MDF_DataTableDoesNotExist, collectionName)); @@ -1071,17 +1093,17 @@ internal static Exception UndefinedPopulationMechanism(string populationMechanis #else => throw new NotImplementedException(); #endif - #endregion +#endregion - #region DbConnectionPool and related +#region DbConnectionPool and related internal static Exception PooledOpenTimeout() => ADP.InvalidOperation(StringsHelper.GetString(Strings.ADP_PooledOpenTimeout)); internal static Exception NonPooledOpenTimeout() => ADP.TimeoutException(StringsHelper.GetString(Strings.ADP_NonPooledOpenTimeout)); - #endregion +#endregion - #region DbProviderException +#region DbProviderException internal static InvalidOperationException TransactionConnectionMismatch() => Provider(StringsHelper.GetString(Strings.ADP_TransactionConnectionMismatch)); @@ -1090,18 +1112,18 @@ internal static InvalidOperationException TransactionRequired(string method) internal static InvalidOperationException TransactionCompletedButNotDisposed() => Provider(StringsHelper.GetString(Strings.ADP_TransactionCompletedButNotDisposed)); - #endregion +#endregion - #region SqlMetaData, SqlTypes +#region SqlMetaData, SqlTypes internal static Exception InvalidMetaDataValue() => ADP.Argument(StringsHelper.GetString(Strings.ADP_InvalidMetaDataValue)); internal static InvalidOperationException NonSequentialColumnAccess(int badCol, int currCol) => InvalidOperation(StringsHelper.GetString(Strings.ADP_NonSequentialColumnAccess, badCol.ToString(CultureInfo.InvariantCulture), currCol.ToString(CultureInfo.InvariantCulture))); - #endregion +#endregion - #region IDataParameter +#region IDataParameter internal static ArgumentException InvalidDataType(TypeCode typecode) => Argument(StringsHelper.GetString(Strings.ADP_InvalidDataType, typecode.ToString())); internal static ArgumentException UnknownDataType(Type dataType) => Argument(StringsHelper.GetString(Strings.ADP_UnknownDataType, dataType.FullName)); @@ -1157,9 +1179,9 @@ internal static Exception ParameterConversionFailed(object value, Type destType, TraceExceptionAsReturnValue(e); return e; } - #endregion +#endregion - #region IDataParameterCollection +#region IDataParameterCollection internal static Exception ParametersMappingIndex(int index, DbParameterCollection collection) => CollectionIndexInt32(index, collection.GetType(), collection.Count); internal static Exception ParametersSourceIndex(string parameterName, DbParameterCollection collection, Type parameterType) @@ -1170,16 +1192,16 @@ internal static Exception ParameterNull(string parameter, DbParameterCollection internal static Exception InvalidParameterType(DbParameterCollection collection, Type parameterType, object invalidValue) => CollectionInvalidType(collection.GetType(), parameterType, invalidValue); - #endregion +#endregion - #region IDbTransaction +#region IDbTransaction internal static Exception ParallelTransactionsNotSupported(DbConnection obj) => InvalidOperation(StringsHelper.GetString(Strings.ADP_ParallelTransactionsNotSupported, obj.GetType().Name)); internal static Exception TransactionZombied(DbTransaction obj) => InvalidOperation(StringsHelper.GetString(Strings.ADP_TransactionZombied, obj.GetType().Name)); - #endregion +#endregion - #region DbProviderConfigurationHandler +#region DbProviderConfigurationHandler internal static InvalidOperationException InvalidMixedUsageOfSecureAndClearCredential() => InvalidOperation(StringsHelper.GetString(Strings.ADP_InvalidMixedUsageOfSecureAndClearCredential)); @@ -1203,10 +1225,10 @@ static internal InvalidOperationException InvalidMixedUsageOfAccessTokenAndAuthe static internal Exception InvalidMixedUsageOfCredentialAndAccessToken() => InvalidOperation(StringsHelper.GetString(Strings.ADP_InvalidMixedUsageOfCredentialAndAccessToken)); - #endregion +#endregion #if NETFRAMEWORK - #region netfx project only +#region netfx project only internal static Task CreatedTaskWithException(Exception ex) { TaskCompletionSource completion = new(); @@ -1451,9 +1473,9 @@ internal static IntPtr IntPtrOffset(IntPtr pbase, int offset) } internal static bool IsEmpty(string str) => string.IsNullOrEmpty(str); - #endregion +#endregion #else - #region netcore project only +#region netcore project only internal static Timer UnsafeCreateTimer(TimerCallback callback, object state, int dueTime, int period) { // Don't capture the current ExecutionContext and its AsyncLocals onto @@ -1524,7 +1546,7 @@ internal static ArgumentOutOfRangeException InvalidParameterDirection(ParameterD // internal static Exception InvalidCommandTimeout(int value, [CallerMemberName] string property = "") => Argument(StringsHelper.GetString(Strings.ADP_InvalidCommandTimeout, value.ToString(CultureInfo.InvariantCulture)), property); - #endregion +#endregion #endif } } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUdtInfo.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUdtInfo.cs index ef2bdc4a5e..c15808bc8a 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUdtInfo.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUdtInfo.cs @@ -4,9 +4,11 @@ using System; using System.Collections.Generic; -using Microsoft.Data.SqlClient.Server; +using Microsoft.Data.Common; #if NETFRAMEWORK using Microsoft.SqlServer.Server; +#else +using Microsoft.Data.SqlClient.Server; #endif namespace Microsoft.Data.SqlClient @@ -35,7 +37,7 @@ internal static SqlUdtInfo GetFromType(Type target) SqlUdtInfo udtAttr = TryGetFromType(target); if (udtAttr == null) { - throw Server.InvalidUdtException.Create(target, Strings.SqlUdtReason_NoUdtAttribute); + throw ADP.CreateInvalidUdtException(target, nameof(Strings.SqlUdtReason_NoUdtAttribute)); } return udtAttr; } diff --git a/src/Microsoft.SqlServer.Server/InvalidUdtException.cs b/src/Microsoft.SqlServer.Server/InvalidUdtException.cs new file mode 100644 index 0000000000..7dcecd626a --- /dev/null +++ b/src/Microsoft.SqlServer.Server/InvalidUdtException.cs @@ -0,0 +1,50 @@ +// 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.Runtime.Serialization; + +namespace Microsoft.SqlServer.Server +{ + /// + [Serializable] + public sealed class InvalidUdtException : SystemException + { + private const int InvalidUdtHResult = unchecked((int)0x80131937); + + internal InvalidUdtException() : base() + { + HResult = InvalidUdtHResult; + } + + internal InvalidUdtException(string message) : base(message) + { + HResult = InvalidUdtHResult; + } + + internal InvalidUdtException(string message, Exception innerException) : base(message, innerException) + { + HResult = InvalidUdtHResult; + } + + private InvalidUdtException(SerializationInfo si, StreamingContext sc) : base(si, sc) + { + } + + /// + [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)] + public override void GetObjectData(SerializationInfo si, StreamingContext context) + { + base.GetObjectData(si, context); + } + + internal static InvalidUdtException Create(Type udtType, string resourceReason) + { + string reason = StringsHelper.GetString(resourceReason); + string message = StringsHelper.GetString(Strings.SqlUdt_InvalidUdtMessage, udtType.FullName, reason); + InvalidUdtException e = new InvalidUdtException(message); + return e; + } + } +} diff --git a/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj b/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj index 7b2ec38d66..dafc9a4dbe 100644 --- a/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj +++ b/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Microsoft.SqlServer.Server/Strings.Designer.cs b/src/Microsoft.SqlServer.Server/Strings.Designer.cs index 67e310e065..ebe75538ee 100644 --- a/src/Microsoft.SqlServer.Server/Strings.Designer.cs +++ b/src/Microsoft.SqlServer.Server/Strings.Designer.cs @@ -77,14 +77,36 @@ internal static string ADP_NotSupportedEnumerationValue { return ResourceManager.GetString("ADP_NotSupportedEnumerationValue", resourceCulture); } } - + /// - /// Looks up a localized string similar to range: 0-8000. + /// Looks up a localized string similar to '{0}' is an invalid user defined type, reason: {1}.. /// - internal static string SQLUDT_MaxByteSizeValue { + internal static string SqlUdt_InvalidUdtMessage + { get { + return ResourceManager.GetString("SqlUdt_InvalidUdtMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to range: 0-8000. + /// + internal static string SQLUDT_MaxByteSizeValue + { + get + { return ResourceManager.GetString("SQLUDT_MaxByteSizeValue", resourceCulture); } } + + /// + /// Looks up a localized string similar to no UDT attribute. + /// + internal static string SqlUdtReason_NoUdtAttribute + { + get { + return ResourceManager.GetString("SqlUdtReason_NoUdtAttribute", resourceCulture); + } + } } } diff --git a/src/Microsoft.SqlServer.Server/Strings.resx b/src/Microsoft.SqlServer.Server/Strings.resx index 20c25de4ea..deb5efff24 100644 --- a/src/Microsoft.SqlServer.Server/Strings.resx +++ b/src/Microsoft.SqlServer.Server/Strings.resx @@ -123,6 +123,12 @@ The {0} enumeration value, {1}, is not supported by the {2} method. + + no UDT attribute + + + '{0}' is an invalid user defined type, reason: {1}. + range: 0-8000 diff --git a/src/Microsoft.SqlServer.Server/TypeForwards.cs b/src/Microsoft.SqlServer.Server/TypeForwards.cs index efd2f9d4a3..9b9c27afdd 100644 --- a/src/Microsoft.SqlServer.Server/TypeForwards.cs +++ b/src/Microsoft.SqlServer.Server/TypeForwards.cs @@ -1,5 +1,6 @@  [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.IBinarySerialize))] +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.InvalidUdtException))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.Format))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.SqlFacetAttribute))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(Microsoft.SqlServer.Server.SqlFunctionAttribute))] diff --git a/tools/specs/Microsoft.SqlServer.Server.nuspec b/tools/specs/Microsoft.SqlServer.Server.nuspec index 91597ca438..3c9499ffc4 100644 --- a/tools/specs/Microsoft.SqlServer.Server.nuspec +++ b/tools/specs/Microsoft.SqlServer.Server.nuspec @@ -14,6 +14,7 @@ Available Types: Microsoft.SqlServer.Server.IBinarySerializer +Microsoft.SqlServer.Server.InvalidUdtException Microsoft.SqlServer.Server.SqlFacetAttribute Microsoft.SqlServer.Server.SqlFunctionAttribute Microsoft.SqlServer.Server.SqlMethodAttribute From 0ba0442b46d60075af97817aa40311a23207a1bf Mon Sep 17 00:00:00 2001 From: Davoud Eshtehari Date: Mon, 20 Dec 2021 20:29:36 -0800 Subject: [PATCH 3/7] Add test --- .../tests/FunctionalTests/SqlMetaDataTest.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlMetaDataTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlMetaDataTest.cs index d2306431f4..8d3c46b75a 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlMetaDataTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlMetaDataTest.cs @@ -712,6 +712,19 @@ public void UdtConstructorTest() Assert.Equal(-1, metaData.SortOrdinal); } + [Fact] + public static void InvalidUdtEcxeption_Throws() + { + var e = Assert.Throws +#if NETFRAMEWORK + +#else + +#endif + (() => new SqlMetaData("col1", SqlDbType.Udt, typeof(int), "UdtTestDb.dbo.Address")); + Assert.Equal("'System.Int32' is an invalid user defined type, reason: no UDT attribute.", e.Message); + } + [Fact] public void UdtConstructorTestWithoutServerTypeName() { From 90d3aad06dc02e20ec7dea1c04e467b64ac5df35 Mon Sep 17 00:00:00 2001 From: Davoud Eshtehari Date: Mon, 17 Jan 2022 20:05:15 -0800 Subject: [PATCH 4/7] make public InvalidUdtException.Create --- .../InvalidUdtException.xml | 17 +++++++++++++++++ .../InvalidUdtException.cs | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient.Server/InvalidUdtException.xml b/doc/snippets/Microsoft.Data.SqlClient.Server/InvalidUdtException.xml index 70bfd160f4..8c70c3ea78 100644 --- a/doc/snippets/Microsoft.Data.SqlClient.Server/InvalidUdtException.xml +++ b/doc/snippets/Microsoft.Data.SqlClient.Server/InvalidUdtException.xml @@ -18,5 +18,22 @@ ]]> + + The object. + The object that represents a string in string resources. The default value is `SqlUdtReason_NoUdtAttribute` which looks up a localized string similar to "no UDT attribute". + Create a new object. + A new object. + + [!IMPORTANT] +> This function exposes for backward compatibility, and should be used with default value for `resourceReason` parameter. + + ]]> + + diff --git a/src/Microsoft.SqlServer.Server/InvalidUdtException.cs b/src/Microsoft.SqlServer.Server/InvalidUdtException.cs index 7dcecd626a..4831eb3a1a 100644 --- a/src/Microsoft.SqlServer.Server/InvalidUdtException.cs +++ b/src/Microsoft.SqlServer.Server/InvalidUdtException.cs @@ -39,7 +39,8 @@ public override void GetObjectData(SerializationInfo si, StreamingContext contex base.GetObjectData(si, context); } - internal static InvalidUdtException Create(Type udtType, string resourceReason) + /// + internal static InvalidUdtException Create(Type udtType, string resourceReason = "SqlUdtReason_NoUdtAttribute") { string reason = StringsHelper.GetString(resourceReason); string message = StringsHelper.GetString(Strings.SqlUdt_InvalidUdtMessage, udtType.FullName, reason); From 7672269e89074787336eafede338a0e2193b2b51 Mon Sep 17 00:00:00 2001 From: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> Date: Wed, 19 Jan 2022 14:26:34 -0800 Subject: [PATCH 5/7] Apply suggestions from code review Co-authored-by: David Engel --- tools/specs/Microsoft.SqlServer.Server.nuspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/specs/Microsoft.SqlServer.Server.nuspec b/tools/specs/Microsoft.SqlServer.Server.nuspec index 3c9499ffc4..e5b23efbfe 100644 --- a/tools/specs/Microsoft.SqlServer.Server.nuspec +++ b/tools/specs/Microsoft.SqlServer.Server.nuspec @@ -10,7 +10,7 @@ https://aka.ms/sqlclientproject dotnet.png - This is the helper library for Microsoft.Data.SqlClient for cross framework compatibility support of UDT types. + This is a helper library for Microsoft.Data.SqlClient enabling cross framework support of UDT types. Available Types: Microsoft.SqlServer.Server.IBinarySerializer @@ -25,7 +25,7 @@ Microsoft.SqlServer.Server.SystemDataAccessKind Microsoft.SqlServer.Server.Format - https://go.microsoft.com/fwlink/?linkid=2090501 + https://go.microsoft.com/fwlink/?linkid=2185441 © Microsoft Corporation. All rights reserved. sqlserver microsoft.sqlserver.server From 7211f53e6c974478d95c729964fb6fcceaa8b68a Mon Sep 17 00:00:00 2001 From: Davoud Eshtehari Date: Wed, 19 Jan 2022 14:27:13 -0800 Subject: [PATCH 6/7] Address comment --- src/Microsoft.SqlServer.Server/InvalidUdtException.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.SqlServer.Server/InvalidUdtException.cs b/src/Microsoft.SqlServer.Server/InvalidUdtException.cs index 4831eb3a1a..4d58ed1f27 100644 --- a/src/Microsoft.SqlServer.Server/InvalidUdtException.cs +++ b/src/Microsoft.SqlServer.Server/InvalidUdtException.cs @@ -40,7 +40,7 @@ public override void GetObjectData(SerializationInfo si, StreamingContext contex } /// - internal static InvalidUdtException Create(Type udtType, string resourceReason = "SqlUdtReason_NoUdtAttribute") + public static InvalidUdtException Create(Type udtType, string resourceReason = "SqlUdtReason_NoUdtAttribute") { string reason = StringsHelper.GetString(resourceReason); string message = StringsHelper.GetString(Strings.SqlUdt_InvalidUdtMessage, udtType.FullName, reason); From ea19f4aa8fa869672f0b085d148463030fb625fd Mon Sep 17 00:00:00 2001 From: Davoud Eshtehari Date: Tue, 25 Jan 2022 15:31:03 -0800 Subject: [PATCH 7/7] update build --- build.proj | 1 + porting-cheat-sheet.md | 14 ++++++++++++++ tools/props/Versions.props | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/build.proj b/build.proj index 6ff0fd5c84..124837c2d2 100644 --- a/build.proj +++ b/build.proj @@ -24,6 +24,7 @@ $(TF) $(TF) true + Configuration=$(Configuration);AssemblyVersion=$(SqlServerAssemblyVersion);AssemblyFileVersion=$(SqlServerAssemblyFileVersion);Version=$(SqlServerPackageVersion); Configuration=$(Configuration);AssemblyFileVersion=$(AssemblyFileVersion);TargetsWindows=$(TargetsWindows);TargetsUnix=$(TargetsUnix); BuildProjectReferences=false;$(ProjectProperties);BuildForRelease=false;TargetNetCoreVersion=$(TargetNetCoreVersion);TargetNetFxVersion=$(TargetNetFxVersion) TestResults diff --git a/porting-cheat-sheet.md b/porting-cheat-sheet.md index 3258e97776..e27836717f 100644 --- a/porting-cheat-sheet.md +++ b/porting-cheat-sheet.md @@ -4,6 +4,20 @@ This guide is meant to cover all namespace changes needed in client applications ## Namespace Changes needed +### Microsoft.Data.SqlClient v5.0 and newer + +| Namespace Change | Applicability | +|--|--| +| `using System.Data.SqlClient;`
`using Microsoft.Data.SqlClient;` | Applicable to all classes, enums and delegates. | +| `using Microsoft.SqlServer.Server;`
`using Microsoft.Data.SqlClient.Server;` | Applicable Classes:
`SqlDataRecord`
`SqlMetaData`

1 _All remaining types continue to be referenced from Microsoft.SqlServer.Server namespace._| +| `using System.Data.SqlTypes;`
`using Microsoft.Data.SqlTypes;` | Applicable Classes:
`SqlFileStream`| +| `using System.Data.Sql;`
`using Microsoft.Data.Sql;` | Applicable Classes:
`SqlNotificationRequest`
| +| `using System.Data;`
`using Microsoft.Data;` | Applicable Classes:
`OperationAbortedException`| + +1 Breaking change for User-Defined types and Microsoft.SqlServer.Types support over _Microsoft.Data.SqlClient v3.0.0_. + +### Microsoft.Data.SqlClient v4.0 and older + | Namespace Change | Applicability | |--|--| | `using System.Data.SqlClient;`
`using Microsoft.Data.SqlClient;` | Applicable to all classes, enums and delegates. | diff --git a/tools/props/Versions.props b/tools/props/Versions.props index ba018dc65a..44002cbbae 100644 --- a/tools/props/Versions.props +++ b/tools/props/Versions.props @@ -5,7 +5,7 @@ - 4.0.0.0 + 5.0.0.0 5.0.0-dev $(NugetPackageVersion)