From 921c48f25e77e61083e133f65a31c96b215e324b Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 25 May 2016 14:09:25 -0700 Subject: [PATCH] Use length facet for parameter size Issues: #4608 Use column/property facets for parameter types in Query Pipeline #4134 Use column/property facets for parameter types in Update Pipeline If a property length is specified, then this is used to infer the length to use for parameters relating to that property, unless the length of the data is too long, in which case unbounded length is used. Because query has code that can infer the length to use for a parameter this still means that fragmentation will not happen without always using the 4000/8000 value. --- .../TestSqlLoggerFactory.cs | 301 ++++++++-------- .../Storage/RelationalTypeMapper.cs | 16 +- .../Internal/SqlServerMaxLengthMapping.cs | 29 +- .../Storage/Internal/SqlServerTypeMapper.cs | 2 +- .../BuiltInDataTypesSqlServerFixture.cs | 1 + .../BuiltInDataTypesSqlServerTest.cs | 340 +++++++++++++++++- .../DataAnnotationSqlServerTest.cs | 24 +- .../GearsOfWarQuerySqlServerTest.cs | 2 +- .../InheritanceSqlServerTest.cs | 10 +- .../QueryBugsTest.cs | 4 +- .../QuerySqlServerTest.cs | 14 +- .../SqlServerTypeMapperTest.cs | 88 ++--- 12 files changed, 586 insertions(+), 245 deletions(-) diff --git a/src/Microsoft.EntityFrameworkCore.Relational.Specification.Tests/TestSqlLoggerFactory.cs b/src/Microsoft.EntityFrameworkCore.Relational.Specification.Tests/TestSqlLoggerFactory.cs index 60d7c109cc6..d386db64146 100644 --- a/src/Microsoft.EntityFrameworkCore.Relational.Specification.Tests/TestSqlLoggerFactory.cs +++ b/src/Microsoft.EntityFrameworkCore.Relational.Specification.Tests/TestSqlLoggerFactory.cs @@ -170,187 +170,188 @@ public void Log( } } - private static string FormatParameter(DbParameterLogData parameterData) - { - var builder = new StringBuilder(); - - var value = parameterData.Value; - var clrType = value?.GetType(); - FormatParameterValue(builder, value); + public bool IsEnabled(LogLevel logLevel) => true; - if (parameterData.IsNullable - && value != null - && !IsNullableType(clrType)) - { - builder.Append(" (Nullable = true)"); - } - else - { - if (!parameterData.IsNullable - && parameterData.HasValue - && (value == null - || IsNullableType(clrType))) - { - builder.Append(" (Nullable = false)"); - } - } + public IDisposable BeginScope(TState state) => SqlLoggerData._log.Indent(); - if (parameterData.Size != 0) - { - builder - .Append(" (Size = ") - .Append(parameterData.Size) - .Append(')'); - } + // ReSharper disable once MemberCanBeMadeStatic.Local + public void ResetLoggerData() => +#if NETSTANDARD1_3 + _loggerData.Value = null; +#else + CallContext.LogicalSetData(ContextName, null); +#endif + } - if (parameterData.Precision != 0) - { - builder - .Append(" (Precision = ") - .Append(parameterData.Precision) - .Append(')'); - } + public static string FormatParameter(DbParameterLogData parameterData) + { + var builder = new StringBuilder(); - if (parameterData.Scale != 0) - { - builder - .Append(" (Scale = ") - .Append(parameterData.Scale) - .Append(')'); - } + var value = parameterData.Value; + var clrType = value?.GetType(); - if (parameterData.Direction != ParameterDirection.Input) - { - builder - .Append(" (Direction = ") - .Append(parameterData.Direction) - .Append(')'); - } + FormatParameterValue(builder, value); - if (parameterData.HasValue - && !IsNormalDbType(parameterData.DbType, clrType)) + if (parameterData.IsNullable + && value != null + && !IsNullableType(clrType)) + { + builder.Append(" (Nullable = true)"); + } + else + { + if (!parameterData.IsNullable + && parameterData.HasValue + && (value == null + || IsNullableType(clrType))) { - builder - .Append(" (DbType = ") - .Append(parameterData.DbType) - .Append(')'); + builder.Append(" (Nullable = false)"); } - - return builder.ToString(); } - private static void FormatParameterValue(StringBuilder builder, object parameterValue) + if (parameterData.Size != 0) { - if (parameterValue.GetType() != typeof(byte[])) - { - builder.Append(Convert.ToString(parameterValue, CultureInfo.InvariantCulture)); - return; - } + builder + .Append(" (Size = ") + .Append(parameterData.Size) + .Append(')'); + } - var buffer = (byte[])parameterValue; - builder.Append("0x"); + if (parameterData.Precision != 0) + { + builder + .Append(" (Precision = ") + .Append(parameterData.Precision) + .Append(')'); + } - for (var i = 0; i < buffer.Length; i++) - { - if (i > 31) - { - builder.Append("..."); - break; - } - builder.Append(buffer[i].ToString("X2", CultureInfo.InvariantCulture)); - } + if (parameterData.Scale != 0) + { + builder + .Append(" (Scale = ") + .Append(parameterData.Scale) + .Append(')'); } - private static bool IsNullableType(Type type) + if (parameterData.Direction != ParameterDirection.Input) { - var typeInfo = type.GetTypeInfo(); + builder + .Append(" (Direction = ") + .Append(parameterData.Direction) + .Append(')'); + } - return !typeInfo.IsValueType - || (typeInfo.IsGenericType - && (typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>))); + if (parameterData.HasValue + && !IsNormalDbType(parameterData.DbType, clrType)) + { + builder + .Append(" (DbType = ") + .Append(parameterData.DbType) + .Append(')'); } - private static bool IsNormalDbType(DbType dbType, Type clrType) + return builder.ToString(); + } + + private static void FormatParameterValue(StringBuilder builder, object parameterValue) + { + if (parameterValue.GetType() != typeof(byte[])) { - if (clrType == null) - { - return false; - } + builder.Append(Convert.ToString(parameterValue, CultureInfo.InvariantCulture)); + return; + } - clrType = UnwrapEnumType(UnwrapNullableType(clrType)); + var buffer = (byte[])parameterValue; + builder.Append("0x"); - switch (dbType) + for (var i = 0; i < buffer.Length; i++) + { + if (i > 31) { - case DbType.AnsiString: // Zero - return clrType != typeof(string); - case DbType.Binary: - return clrType == typeof(byte[]); - case DbType.Byte: - return clrType == typeof(byte); - case DbType.Boolean: - return clrType == typeof(bool); - case DbType.Decimal: - return clrType == typeof(decimal); - case DbType.Double: - return clrType == typeof(double); - case DbType.Guid: - return clrType == typeof(Guid); - case DbType.Int16: - return clrType == typeof(short); - case DbType.Int32: - return clrType == typeof(int); - case DbType.Int64: - return clrType == typeof(long); - case DbType.Object: - return clrType == typeof(object); - case DbType.SByte: - return clrType == typeof(sbyte); - case DbType.Single: - return clrType == typeof(float); - case DbType.String: - return clrType == typeof(string); - case DbType.Time: - return clrType == typeof(TimeSpan); - case DbType.UInt16: - return clrType == typeof(ushort); - case DbType.UInt32: - return clrType == typeof(uint); - case DbType.UInt64: - return clrType == typeof(ulong); - case DbType.DateTime2: - return clrType == typeof(DateTime); - case DbType.DateTimeOffset: - return clrType == typeof(DateTimeOffset); - //case DbType.VarNumeric: - //case DbType.AnsiStringFixedLength: - //case DbType.StringFixedLength: - //case DbType.Xml: - //case DbType.Currency: - //case DbType.Date: - //case DbType.DateTime: - default: - return false; + builder.Append("..."); + break; } + builder.Append(buffer[i].ToString("X2", CultureInfo.InvariantCulture)); } + } - private static Type UnwrapNullableType(Type type) - => Nullable.GetUnderlyingType(type) ?? type; + private static bool IsNullableType(Type type) + { + var typeInfo = type.GetTypeInfo(); - private static Type UnwrapEnumType(Type type) - => !type.GetTypeInfo().IsEnum ? type : Enum.GetUnderlyingType(type); + return !typeInfo.IsValueType + || (typeInfo.IsGenericType + && (typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>))); + } - public bool IsEnabled(LogLevel logLevel) => true; + private static bool IsNormalDbType(DbType dbType, Type clrType) + { + if (clrType == null) + { + return false; + } - public IDisposable BeginScope(TState state) => SqlLoggerData._log.Indent(); + clrType = UnwrapEnumType(UnwrapNullableType(clrType)); - // ReSharper disable once MemberCanBeMadeStatic.Local - public void ResetLoggerData() => -#if NETSTANDARD1_3 - _loggerData.Value = null; -#else - CallContext.LogicalSetData(ContextName, null); -#endif + switch (dbType) + { + case DbType.AnsiString: // Zero + return clrType != typeof(string); + case DbType.Binary: + return clrType == typeof(byte[]); + case DbType.Byte: + return clrType == typeof(byte); + case DbType.Boolean: + return clrType == typeof(bool); + case DbType.Decimal: + return clrType == typeof(decimal); + case DbType.Double: + return clrType == typeof(double); + case DbType.Guid: + return clrType == typeof(Guid); + case DbType.Int16: + return clrType == typeof(short); + case DbType.Int32: + return clrType == typeof(int); + case DbType.Int64: + return clrType == typeof(long); + case DbType.Object: + return clrType == typeof(object); + case DbType.SByte: + return clrType == typeof(sbyte); + case DbType.Single: + return clrType == typeof(float); + case DbType.String: + return clrType == typeof(string); + case DbType.Time: + return clrType == typeof(TimeSpan); + case DbType.UInt16: + return clrType == typeof(ushort); + case DbType.UInt32: + return clrType == typeof(uint); + case DbType.UInt64: + return clrType == typeof(ulong); + case DbType.DateTime2: + return clrType == typeof(DateTime); + case DbType.DateTimeOffset: + return clrType == typeof(DateTimeOffset); + //case DbType.VarNumeric: + //case DbType.AnsiStringFixedLength: + //case DbType.StringFixedLength: + //case DbType.Xml: + //case DbType.Currency: + //case DbType.Date: + //case DbType.DateTime: + default: + return false; + } } + + private static Type UnwrapNullableType(Type type) + => Nullable.GetUnderlyingType(type) ?? type; + + private static Type UnwrapEnumType(Type type) + => !type.GetTypeInfo().IsEnum ? type : Enum.GetUnderlyingType(type); } } diff --git a/src/Microsoft.EntityFrameworkCore.Relational/Storage/RelationalTypeMapper.cs b/src/Microsoft.EntityFrameworkCore.Relational/Storage/RelationalTypeMapper.cs index e499ac085fe..3d2f776646d 100644 --- a/src/Microsoft.EntityFrameworkCore.Relational/Storage/RelationalTypeMapper.cs +++ b/src/Microsoft.EntityFrameworkCore.Relational/Storage/RelationalTypeMapper.cs @@ -73,13 +73,17 @@ protected virtual RelationalTypeMapping CreateMappingFromStoreType([NotNull] str return null; } - var closeParen = storeType.IndexOf(")", openParen + 1, StringComparison.Ordinal); - int size; - if (closeParen > openParen - && int.TryParse(storeType.Substring(openParen + 1, closeParen - openParen - 1), out size) - && mapping.Size != size) + if (mapping.ClrType == typeof(string) + || mapping.ClrType == typeof(byte[])) { - return mapping.CreateCopy(storeType, size); + var closeParen = storeType.IndexOf(")", openParen + 1, StringComparison.Ordinal); + int size; + if (closeParen > openParen + && int.TryParse(storeType.Substring(openParen + 1, closeParen - openParen - 1), out size) + && mapping.Size != size) + { + return mapping.CreateCopy(storeType, size); + } } } diff --git a/src/Microsoft.EntityFrameworkCore.SqlServer/Storage/Internal/SqlServerMaxLengthMapping.cs b/src/Microsoft.EntityFrameworkCore.SqlServer/Storage/Internal/SqlServerMaxLengthMapping.cs index 37e2acd6b89..3ac67142322 100644 --- a/src/Microsoft.EntityFrameworkCore.SqlServer/Storage/Internal/SqlServerMaxLengthMapping.cs +++ b/src/Microsoft.EntityFrameworkCore.SqlServer/Storage/Internal/SqlServerMaxLengthMapping.cs @@ -10,8 +10,6 @@ namespace Microsoft.EntityFrameworkCore.Storage.Internal { public class SqlServerMaxLengthMapping : RelationalTypeMapping { - private readonly int _maxSpecificSize; - public SqlServerMaxLengthMapping( [NotNull] string storeType, [NotNull] Type clrType, @@ -28,16 +26,15 @@ public SqlServerMaxLengthMapping( int? size, bool hasNonDefaultUnicode = false, bool hasNonDefaultSize = false) - : base(storeType, clrType, dbType, unicode, size, hasNonDefaultUnicode, hasNonDefaultSize) + : base(storeType, clrType, dbType, unicode, CalculateSize(unicode, size), hasNonDefaultUnicode, hasNonDefaultSize) { - _maxSpecificSize = - (dbType == System.Data.DbType.AnsiString) - || (dbType == System.Data.DbType.AnsiStringFixedLength) - || (dbType == System.Data.DbType.Binary) - ? 8000 - : 4000; } + private static int CalculateSize(bool unicode, int? size) + => unicode + ? size.HasValue && size < 4000 ? size.Value : 4000 + : size.HasValue && size < 8000 ? size.Value : 8000; + public override RelationalTypeMapping CreateCopy(string storeType, int? size) => new SqlServerMaxLengthMapping( storeType, @@ -50,14 +47,16 @@ public override RelationalTypeMapping CreateCopy(string storeType, int? size) protected override void ConfigureParameter(DbParameter parameter) { - // For strings and byte arrays, set the max length to 8000 bytes if the data will - // fit so as to avoid query cache fragmentation by setting lots of differet Size - // values otherwise always set to -1 (unbounded) to avoid SQL client size inference. + // For strings and byte arrays, set the max length to the size facet if specififed, or + // 8000 bytes if no size facet specified, if the data will fit so as to avoid query cache + // fragmentation by setting lots of differet Size values otherwise always set to + // -1 (unbounded) to avoid SQL client size inference. - var length = (parameter.Value as string)?.Length ?? (parameter.Value as byte[])?.Length; + var value = parameter.Value; + var length = (value as string)?.Length ?? (value as byte[])?.Length; - parameter.Size = length != null && length <= _maxSpecificSize - ? _maxSpecificSize + parameter.Size = value == null || value == DBNull.Value || (length != null && length <= Size.Value) + ? Size.Value : -1; } } diff --git a/src/Microsoft.EntityFrameworkCore.SqlServer/Storage/Internal/SqlServerTypeMapper.cs b/src/Microsoft.EntityFrameworkCore.SqlServer/Storage/Internal/SqlServerTypeMapper.cs index 6452c1c7f65..a71de6536be 100644 --- a/src/Microsoft.EntityFrameworkCore.SqlServer/Storage/Internal/SqlServerTypeMapper.cs +++ b/src/Microsoft.EntityFrameworkCore.SqlServer/Storage/Internal/SqlServerTypeMapper.cs @@ -88,7 +88,7 @@ private readonly RelationalTypeMapping _time = new RelationalTypeMapping("time", typeof(TimeSpan)); private readonly RelationalTypeMapping _xml - = new RelationalTypeMapping("xml", typeof(string)); + = new SqlServerMaxLengthMapping("xml", typeof(string), dbType: null, unicode: true, size: null); private readonly Dictionary _storeTypeMappings; private readonly Dictionary _clrTypeMappings; diff --git a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerFixture.cs b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerFixture.cs index 34dee55c815..ae416dc2085 100644 --- a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerFixture.cs +++ b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerFixture.cs @@ -29,6 +29,7 @@ public BuiltInDataTypesSqlServerFixture() _options = new DbContextOptionsBuilder() .UseSqlServer(_testStore.Connection) + .EnableSensitiveDataLogging() .UseInternalServiceProvider(serviceProvider) .Options; diff --git a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerTest.cs b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerTest.cs index 753b74980a0..b656a532de7 100644 --- a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerTest.cs +++ b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerTest.cs @@ -54,7 +54,7 @@ var results Assert.Equal(0, results.Count); Assert.Equal( - @"@__timeSpan_0: ? + @"@__timeSpan_0: 02:01:00 SELECT [e].[Int] FROM [MappedNullableDataTypes] AS [e] @@ -301,6 +301,7 @@ public virtual void Can_query_using_any_mapped_data_types_with_nulls() [Fact] public virtual void Can_insert_and_read_back_all_mapped_data_types() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(CreateMappedDataTypes(77)); @@ -308,12 +309,52 @@ public virtual void Can_insert_and_read_back_all_mapped_data_types() Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 77 +@p1: 78 +@p2: 0x5D5E5F60 (Nullable = false) (Size = 8000) +@p3: True +@p4: Your (Nullable = false) (Size = 8000) (DbType = AnsiString) +@p5: strong (Nullable = false) (Size = 8000) (DbType = AnsiString) +@p6: 01/02/2015 10:11:12 +@p7: 01/02/2019 14:11:12 +@p8: 01/02/2017 12:11:12 +@p9: 01/02/2016 11:11:12 +00:00 +@p10: 102.2 +@p11: 101.1 +@p12: 85.5 +@p13: 83.3 +@p14: 0x61626364 (Nullable = false) (Size = 8000) +@p15: 81.1 +@p16: help (Nullable = false) (Size = 4000) +@p17: anyone! (Nullable = false) (Size = 4000) +@p18: Gumball Rules OK! (Nullable = false) (Size = 4000) +@p19: 103.3 +@p20: don't (Nullable = false) (Size = 4000) +@p21: 84.4 +@p22: 01/02/2018 13:11:12 +@p23: 79 +@p24: 82.2 +@p25: Gumball Rules! (Nullable = false) (Size = 8000) (DbType = AnsiString) +@p26: 11:15:12 +@p27: 80 (Size = 1) +@p28: 0x595A5B5C (Nullable = false) (Size = 8000) +@p29: C (Nullable = false) (Size = 8000) (DbType = AnsiString)", + parameters); + using (var context = CreateContext()) { AssertMappedDataTypes(context.Set().Single(e => e.Int == 77), 77); } } + private static string DumpParameters() + => string.Join( + Environment.NewLine, + TestSqlLoggerFactory.CommandLogData.Single().Parameters + .Select(p => p.Name + ": " + TestSqlLoggerFactory.FormatParameter(p))); + private static void AssertMappedDataTypes(MappedDataTypes entity, int id) { Assert.Equal(id, entity.Int); @@ -386,6 +427,7 @@ private static MappedDataTypes CreateMappedDataTypes(int id) [Fact] public virtual void Can_insert_and_read_back_all_mapped_nullable_data_types() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(CreateMappedNullableDataTypes(77)); @@ -393,6 +435,40 @@ public virtual void Can_insert_and_read_back_all_mapped_nullable_data_types() Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 77 +@p1: 78 (Nullable = true) +@p2: 0x5D5E5F60 (Size = 8000) +@p3: True (Nullable = true) +@p4: Your (Size = 8000) (DbType = AnsiString) +@p5: strong (Size = 8000) (DbType = AnsiString) +@p6: 01/02/2015 10:11:12 (Nullable = true) +@p7: 01/02/2019 14:11:12 (Nullable = true) +@p8: 01/02/2017 12:11:12 (Nullable = true) +@p9: 01/02/2016 11:11:12 +00:00 (Nullable = true) +@p10: 102.2 (Nullable = true) +@p11: 101.1 (Nullable = true) +@p12: 85.5 (Nullable = true) +@p13: 83.3 (Nullable = true) +@p14: 0x61626364 (Size = 8000) +@p15: 81.1 (Nullable = true) +@p16: help (Size = 4000) +@p17: anyone! (Size = 4000) +@p18: Gumball Rules OK! (Size = 4000) +@p19: 103.3 (Nullable = true) +@p20: don't (Size = 4000) +@p21: 84.4 (Nullable = true) +@p22: 01/02/2018 13:11:12 (Nullable = true) +@p23: 79 (Nullable = true) +@p24: 82.2 (Nullable = true) +@p25: Gumball Rules! (Size = 8000) (DbType = AnsiString) +@p26: 11:15:12 (Nullable = true) +@p27: 80 (Nullable = true) (Size = 1) +@p28: 0x595A5B5C (Size = 8000) +@p29: C (Size = 8000) (DbType = AnsiString)", + parameters); + using (var context = CreateContext()) { AssertMappedNullableDataTypes(context.Set().Single(e => e.Int == 77), 77); @@ -471,6 +547,7 @@ private static MappedNullableDataTypes CreateMappedNullableDataTypes(int id) [Fact] public virtual void Can_insert_and_read_back_all_mapped_data_types_set_to_null() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(new MappedNullableDataTypes { Int = 78 }); @@ -478,6 +555,40 @@ public virtual void Can_insert_and_read_back_all_mapped_data_types_set_to_null() Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 78 +@p1: (DbType = Int64) +@p2: (Size = 8000) (DbType = Binary) +@p3: (DbType = String) +@p4: (Size = 8000) +@p5: (Size = 8000) +@p6: (DbType = DateTime2) +@p7: (DbType = DateTime2) +@p8: (DbType = DateTime2) +@p9: (DbType = String) +@p10: (DbType = String) +@p11: (DbType = String) +@p12: (DbType = String) +@p13: (DbType = String) +@p14: (Size = 8000) (DbType = Binary) +@p15: (DbType = String) +@p16: (Size = 4000) (DbType = String) +@p17: (Size = 4000) (DbType = String) +@p18: (Size = 4000) (DbType = String) +@p19: (DbType = String) +@p20: (Size = 4000) (DbType = String) +@p21: (DbType = String) +@p22: (DbType = DateTime2) +@p23: (DbType = Int16) +@p24: (DbType = String) +@p25: (Size = 8000) +@p26: (DbType = String) +@p27: (DbType = Byte) +@p28: (Size = 8000) (DbType = Binary) +@p29: (Size = 8000)", + parameters); + using (var context = CreateContext()) { AssertNullMappedNullableDataTypes(context.Set().Single(e => e.Int == 78), 78); @@ -521,6 +632,7 @@ private static void AssertNullMappedNullableDataTypes(MappedNullableDataTypes en [Fact] public virtual void Can_insert_and_read_back_all_mapped_sized_data_types() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(CreateMappedSizedDataTypes(77)); @@ -528,6 +640,24 @@ public virtual void Can_insert_and_read_back_all_mapped_sized_data_types() Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 77 +@p1: 0x0A0B0C (Size = 3) +@p2: 0x0C0D0E (Size = 3) +@p3: Wor (Size = 3) (DbType = AnsiStringFixedLength) +@p4: Thr (Size = 3) (DbType = AnsiString) +@p5: Lon (Size = 3) (DbType = AnsiStringFixedLength) +@p6: Let (Size = 3) (DbType = AnsiString) +@p7: The (Size = 3) +@p8: Squ (Size = 3) (DbType = StringFixedLength) +@p9: Col (Size = 3) +@p10: Won (Size = 3) (DbType = StringFixedLength) +@p11: Int (Size = 3) +@p12: 0x0B0C0D (Size = 3) +@p13: Tha (Size = 3) (DbType = AnsiString)", + parameters); + using (var context = CreateContext()) { AssertMappedSizedDataTypes(context.Set().Single(e => e.Id == 77), 77); @@ -574,6 +704,7 @@ private static MappedSizedDataTypes CreateMappedSizedDataTypes(int id) [Fact] public virtual void Can_insert_and_read_back_nulls_for_all_mapped_sized_data_types() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(new MappedSizedDataTypes { Id = 78 }); @@ -581,6 +712,24 @@ public virtual void Can_insert_and_read_back_nulls_for_all_mapped_sized_data_typ Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 78 +@p1: (Size = 3) (DbType = Binary) +@p2: (Size = 3) (DbType = Binary) +@p3: (Size = 3) (DbType = AnsiStringFixedLength) +@p4: (Size = 3) +@p5: (Size = 3) (DbType = AnsiStringFixedLength) +@p6: (Size = 3) +@p7: (Size = 3) (DbType = String) +@p8: (Size = 3) (DbType = StringFixedLength) +@p9: (Size = 3) (DbType = String) +@p10: (Size = 3) (DbType = StringFixedLength) +@p11: (Size = 3) (DbType = String) +@p12: (Size = 3) (DbType = Binary) +@p13: (Size = 3)", + parameters); + using (var context = CreateContext()) { AssertNullMappedSizedDataTypes(context.Set().Single(e => e.Id == 78), 78); @@ -608,6 +757,7 @@ private static void AssertNullMappedSizedDataTypes(MappedSizedDataTypes entity, [Fact] public virtual void Can_insert_and_read_back_all_mapped_data_types_with_scale() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(CreateMappedScaledDataTypes(77)); @@ -615,6 +765,18 @@ public virtual void Can_insert_and_read_back_all_mapped_data_types_with_scale() Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 77 +@p1: 01/02/2017 12:11:12 +@p2: 01/02/2016 11:11:12 +00:00 +@p3: 102.2 +@p4: 101.1 +@p5: 85.5 +@p6: 83.3 +@p7: 103.3", + parameters); + using (var context = CreateContext()) { AssertMappedScaledDataTypes(context.Set().Single(e => e.Id == 77), 77); @@ -649,6 +811,7 @@ private static MappedScaledDataTypes CreateMappedScaledDataTypes(int id) [Fact] public virtual void Can_insert_and_read_back_all_mapped_data_types_with_precision_and_scale() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(CreateMappedPrecisionAndScaledDataTypes(77)); @@ -656,6 +819,14 @@ public virtual void Can_insert_and_read_back_all_mapped_data_types_with_precisio Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 77 +@p1: 102.2 +@p2: 101.1 +@p3: 103.3", + parameters); + using (var context = CreateContext()) { AssertMappedPrecisionAndScaledDataTypes(context.Set().Single(e => e.Id == 77), 77); @@ -682,6 +853,7 @@ private static MappedPrecisionAndScaledDataTypes CreateMappedPrecisionAndScaledD [Fact] public virtual void Can_insert_and_read_back_all_mapped_data_types_with_identity() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(CreateMappedDataTypesWithIdentity(77)); @@ -689,6 +861,40 @@ public virtual void Can_insert_and_read_back_all_mapped_data_types_with_identity Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 78 +@p1: 0x5D5E5F60 (Size = 8000) +@p2: True +@p3: Your (Size = 8000) (DbType = AnsiString) +@p4: strong (Size = 8000) (DbType = AnsiString) +@p5: 01/02/2015 10:11:12 +@p6: 01/02/2019 14:11:12 +@p7: 01/02/2017 12:11:12 +@p8: 01/02/2016 11:11:12 +00:00 +@p9: 102.2 +@p10: 101.1 +@p11: 85.5 +@p12: 83.3 +@p13: 0x61626364 (Size = 8000) +@p14: 77 +@p15: 81.1 +@p16: help (Size = 4000) +@p17: anyone! (Size = 4000) +@p18: Gumball Rules OK! (Size = 4000) +@p19: 103.3 +@p20: don't (Size = 4000) +@p21: 84.4 +@p22: 01/02/2018 13:11:12 +@p23: 79 +@p24: 82.2 +@p25: Gumball Rules! (Size = 8000) (DbType = AnsiString) +@p26: 11:15:12 +@p27: 80 (Size = 1) +@p28: 0x595A5B5C (Size = 8000) +@p29: C (Size = 8000) (DbType = AnsiString)", + parameters); + using (var context = CreateContext()) { AssertMappedDataTypesWithIdentity(context.Set().Single(e => e.Int == 77), 77); @@ -767,6 +973,7 @@ private static MappedDataTypesWithIdentity CreateMappedDataTypesWithIdentity(int [Fact] public virtual void Can_insert_and_read_back_all_mapped_nullable_data_types_with_identity() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(CreateMappedNullableDataTypesWithIdentity(77)); @@ -774,6 +981,40 @@ public virtual void Can_insert_and_read_back_all_mapped_nullable_data_types_with Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 78 (Nullable = true) +@p1: 0x5D5E5F60 (Size = 8000) +@p2: True (Nullable = true) +@p3: Your (Size = 8000) (DbType = AnsiString) +@p4: strong (Size = 8000) (DbType = AnsiString) +@p5: 01/02/2015 10:11:12 (Nullable = true) +@p6: 01/02/2019 14:11:12 (Nullable = true) +@p7: 01/02/2017 12:11:12 (Nullable = true) +@p8: 01/02/2016 11:11:12 +00:00 (Nullable = true) +@p9: 102.2 (Nullable = true) +@p10: 101.1 (Nullable = true) +@p11: 85.5 (Nullable = true) +@p12: 83.3 (Nullable = true) +@p13: 0x61626364 (Size = 8000) +@p14: 77 (Nullable = true) +@p15: 81.1 (Nullable = true) +@p16: help (Size = 4000) +@p17: anyone! (Size = 4000) +@p18: Gumball Rules OK! (Size = 4000) +@p19: 103.3 (Nullable = true) +@p20: don't (Size = 4000) +@p21: 84.4 (Nullable = true) +@p22: 01/02/2018 13:11:12 (Nullable = true) +@p23: 79 (Nullable = true) +@p24: 82.2 (Nullable = true) +@p25: Gumball Rules! (Size = 8000) (DbType = AnsiString) +@p26: 11:15:12 (Nullable = true) +@p27: 80 (Nullable = true) (Size = 1) +@p28: 0x595A5B5C (Size = 8000) +@p29: C (Size = 8000) (DbType = AnsiString)", + parameters); + using (var context = CreateContext()) { AssertMappedNullableDataTypesWithIdentity(context.Set().Single(e => e.Int == 77), 77); @@ -852,6 +1093,7 @@ private static MappedNullableDataTypesWithIdentity CreateMappedNullableDataTypes [Fact] public virtual void Can_insert_and_read_back_all_mapped_data_types_set_to_null_with_identity() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(new MappedNullableDataTypesWithIdentity { Int = 78 }); @@ -859,6 +1101,40 @@ public virtual void Can_insert_and_read_back_all_mapped_data_types_set_to_null_w Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: (DbType = Int64) +@p1: (Size = 8000) (DbType = Binary) +@p2: (DbType = String) +@p3: (Size = 8000) +@p4: (Size = 8000) +@p5: (DbType = DateTime2) +@p6: (DbType = DateTime2) +@p7: (DbType = DateTime2) +@p8: (DbType = String) +@p9: (DbType = String) +@p10: (DbType = String) +@p11: (DbType = String) +@p12: (DbType = String) +@p13: (Size = 8000) (DbType = Binary) +@p14: 78 (Nullable = true) +@p15: (DbType = String) +@p16: (Size = 4000) (DbType = String) +@p17: (Size = 4000) (DbType = String) +@p18: (Size = 4000) (DbType = String) +@p19: (DbType = String) +@p20: (Size = 4000) (DbType = String) +@p21: (DbType = String) +@p22: (DbType = DateTime2) +@p23: (DbType = Int16) +@p24: (DbType = String) +@p25: (Size = 8000) +@p26: (DbType = String) +@p27: (DbType = Byte) +@p28: (Size = 8000) (DbType = Binary) +@p29: (Size = 8000)", + parameters); + using (var context = CreateContext()) { AssertNullMappedNullableDataTypesWithIdentity(context.Set().Single(e => e.Int == 78), 78); @@ -903,6 +1179,7 @@ private static void AssertNullMappedNullableDataTypesWithIdentity( [Fact] public virtual void Can_insert_and_read_back_all_mapped_sized_data_types_with_identity() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(CreateMappedSizedDataTypesWithIdentity(77)); @@ -910,6 +1187,24 @@ public virtual void Can_insert_and_read_back_all_mapped_sized_data_types_with_id Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 0x0A0B0C (Size = 3) +@p1: 0x0C0D0E (Size = 3) +@p2: Wor (Size = 3) (DbType = AnsiStringFixedLength) +@p3: Thr (Size = 3) (DbType = AnsiString) +@p4: Lon (Size = 3) (DbType = AnsiStringFixedLength) +@p5: Let (Size = 3) (DbType = AnsiString) +@p6: 77 +@p7: The (Size = 3) +@p8: Squ (Size = 3) (DbType = StringFixedLength) +@p9: Col (Size = 3) +@p10: Won (Size = 3) (DbType = StringFixedLength) +@p11: Int (Size = 3) +@p12: 0x0B0C0D (Size = 3) +@p13: Tha (Size = 3) (DbType = AnsiString)", + parameters); + using (var context = CreateContext()) { AssertMappedSizedDataTypesWithIdentity(context.Set().Single(e => e.Int == 77), 77); @@ -956,6 +1251,7 @@ private static MappedSizedDataTypesWithIdentity CreateMappedSizedDataTypesWithId [Fact] public virtual void Can_insert_and_read_back_nulls_for_all_mapped_sized_data_types_with_identity() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(new MappedSizedDataTypesWithIdentity { Int = 78 }); @@ -963,6 +1259,24 @@ public virtual void Can_insert_and_read_back_nulls_for_all_mapped_sized_data_typ Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: (Size = 3) (DbType = Binary) +@p1: (Size = 3) (DbType = Binary) +@p2: (Size = 3) (DbType = AnsiStringFixedLength) +@p3: (Size = 3) +@p4: (Size = 3) (DbType = AnsiStringFixedLength) +@p5: (Size = 3) +@p6: 78 +@p7: (Size = 3) (DbType = String) +@p8: (Size = 3) (DbType = StringFixedLength) +@p9: (Size = 3) (DbType = String) +@p10: (Size = 3) (DbType = StringFixedLength) +@p11: (Size = 3) (DbType = String) +@p12: (Size = 3) (DbType = Binary) +@p13: (Size = 3)", + parameters); + using (var context = CreateContext()) { AssertNullMappedSizedDataTypesWithIdentity(context.Set().Single(e => e.Int == 78), 78); @@ -990,6 +1304,7 @@ private static void AssertNullMappedSizedDataTypesWithIdentity(MappedSizedDataTy [Fact] public virtual void Can_insert_and_read_back_all_mapped_data_types_with_scale_with_identity() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add(CreateMappedScaledDataTypesWithIdentity(77)); @@ -997,6 +1312,18 @@ public virtual void Can_insert_and_read_back_all_mapped_data_types_with_scale_wi Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 01/02/2017 12:11:12 +@p1: 01/02/2016 11:11:12 +00:00 +@p2: 102.2 +@p3: 101.1 +@p4: 85.5 +@p5: 83.3 +@p6: 77 +@p7: 103.3", + parameters); + using (var context = CreateContext()) { AssertMappedScaledDataTypesWithIdentity(context.Set().Single(e => e.Int == 77), 77); @@ -1031,6 +1358,7 @@ private static MappedScaledDataTypesWithIdentity CreateMappedScaledDataTypesWith [Fact] public virtual void Can_insert_and_read_back_all_mapped_data_types_with_precision_and_scale_with_identity() { + TestSqlLoggerFactory.Reset(); using (var context = CreateContext()) { context.Set().Add( @@ -1039,6 +1367,14 @@ public virtual void Can_insert_and_read_back_all_mapped_data_types_with_precisio Assert.Equal(1, context.SaveChanges()); } + var parameters = DumpParameters(); + Assert.Equal( + @"@p0: 102.2 +@p1: 101.1 +@p2: 77 +@p3: 103.3", + parameters); + using (var context = CreateContext()) { AssertMappedPrecisionAndScaledDataTypesWithIdentity( @@ -1244,7 +1580,7 @@ public virtual void Can_insert_and_read_back_all_mapped_nullable_data_types_with } [Fact] - public virtual void Can_insert_and_read_back_all_mapped_data_types_set_to_null_with_identity_in_batch_in_batch() + public virtual void Can_insert_and_read_back_all_mapped_data_types_set_to_null_with_identity_in_batch() { using (var context = CreateContext()) { diff --git a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/DataAnnotationSqlServerTest.cs b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/DataAnnotationSqlServerTest.cs index 48b46ad95b3..193ec7dd2bd 100644 --- a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/DataAnnotationSqlServerTest.cs +++ b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/DataAnnotationSqlServerTest.cs @@ -52,7 +52,7 @@ public override void DatabaseGeneratedAttribute_autogenerates_values_when_set_to { base.DatabaseGeneratedAttribute_autogenerates_values_when_set_to_identity(); - Assert.Equal(@"@p0: (Size = -1) (DbType = String) + Assert.Equal(@"@p0: (Size = 10) (DbType = String) @p1: Third (Nullable = false) (Size = 4000) @p2: 00000000-0000-0000-0000-000000000003 @@ -69,7 +69,7 @@ public override void MaxLengthAttribute_throws_while_inserting_value_longer_than { base.MaxLengthAttribute_throws_while_inserting_value_longer_than_max_length(); - Assert.Equal(@"@p0: Short (Size = 4000) + Assert.Equal(@"@p0: Short (Size = 10) @p1: ValidString (Nullable = false) (Size = 4000) @p2: 00000000-0000-0000-0000-000000000001 @@ -80,7 +80,7 @@ SELECT [UniqueNo] FROM [Sample] WHERE @@ROWCOUNT = 1 AND [UniqueNo] = scope_identity(); -@p0: VeryVeryVeryVeryVeryVeryLongString (Size = 4000) +@p0: VeryVeryVeryVeryVeryVeryLongString (Size = -1) @p1: ValidString (Nullable = false) (Size = 4000) @p2: 00000000-0000-0000-0000-000000000002 @@ -97,11 +97,11 @@ public override void RequiredAttribute_for_navigation_throws_while_inserting_nul { base.RequiredAttribute_for_navigation_throws_while_inserting_null_value(); - Assert.Contains(@"@p1: Book1 (Nullable = false) (Size = 4000) + Assert.Contains(@"@p1: Book1 (Nullable = false) (Size = 450) ", Sql); - Assert.Contains(@"@p1: (Nullable = false) (Size = -1) (DbType = String) + Assert.Contains(@"@p1: (Nullable = false) (Size = 450) (DbType = String) ", Sql); } @@ -110,7 +110,7 @@ public override void RequiredAttribute_for_property_throws_while_inserting_null_ { base.RequiredAttribute_for_property_throws_while_inserting_null_value(); - Assert.Equal(@"@p0: (Size = -1) (DbType = String) + Assert.Equal(@"@p0: (Size = 10) (DbType = String) @p1: ValidString (Nullable = false) (Size = 4000) @p2: 00000000-0000-0000-0000-000000000001 @@ -121,8 +121,8 @@ SELECT [UniqueNo] FROM [Sample] WHERE @@ROWCOUNT = 1 AND [UniqueNo] = scope_identity(); -@p0: (Size = -1) (DbType = String) -@p1: (Nullable = false) (Size = -1) (DbType = String) +@p0: (Size = 10) (DbType = String) +@p1: (Nullable = false) (Size = 4000) (DbType = String) @p2: 00000000-0000-0000-0000-000000000002 SET NOCOUNT ON; @@ -138,7 +138,7 @@ public override void StringLengthAttribute_throws_while_inserting_value_longer_t { base.StringLengthAttribute_throws_while_inserting_value_longer_than_max_length(); - Assert.Equal(@"@p0: ValidString (Size = 4000) + Assert.Equal(@"@p0: ValidString (Size = 16) SET NOCOUNT ON; INSERT INTO [Two] ([Data]) @@ -147,7 +147,7 @@ INSERT INTO [Two] ([Data]) FROM [Two] WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity(); -@p0: ValidButLongString (Size = 4000) +@p0: ValidButLongString (Size = -1) SET NOCOUNT ON; INSERT INTO [Two] ([Data]) @@ -171,7 +171,7 @@ FROM [Two] AS [r] WHERE [r].[Id] = 1 @p1: 1 -@p0: ModifiedData (Size = 4000) +@p0: ModifiedData (Size = 16) @p2: 0x00000000000007D1 (Size = 8) SET NOCOUNT ON; @@ -183,7 +183,7 @@ INTO @inserted0 SELECT [Timestamp] FROM @inserted0; @p1: 1 -@p0: ChangedData (Size = 4000) +@p0: ChangedData (Size = 16) @p2: 0x00000000000007D1 (Size = 8) SET NOCOUNT ON; diff --git a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/GearsOfWarQuerySqlServerTest.cs b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/GearsOfWarQuerySqlServerTest.cs index dab9f4c376f..5a4197693f8 100644 --- a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/GearsOfWarQuerySqlServerTest.cs +++ b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/GearsOfWarQuerySqlServerTest.cs @@ -1019,7 +1019,7 @@ public override void Non_unicode_parameter_is_used_for_non_unicode_column() base.Non_unicode_parameter_is_used_for_non_unicode_column(); Assert.Equal( - @"@__value_0: Unknown (Size = 8000) (DbType = AnsiString) + @"@__value_0: Unknown (Size = 100) (DbType = AnsiString) SELECT [c].[Name], [c].[Location] FROM [City] AS [c] diff --git a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/InheritanceSqlServerTest.cs b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/InheritanceSqlServerTest.cs index 5674e4eff2b..2f4f79a87cd 100644 --- a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/InheritanceSqlServerTest.cs +++ b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/InheritanceSqlServerTest.cs @@ -296,11 +296,11 @@ public override void Can_insert_update_delete() FROM [Country] AS [c] WHERE [c].[Id] = 1 -@p0: Apteryx owenii (Nullable = false) (Size = 4000) +@p0: Apteryx owenii (Nullable = false) (Size = 100) @p1: 1 @p2: Kiwi (Nullable = false) (Size = 4000) @p3: Little spotted kiwi (Size = 4000) -@p4: (Size = -1) (DbType = String) +@p4: (Size = 100) (DbType = String) @p5: True @p6: North @@ -312,8 +312,8 @@ SELECT TOP(2) [k].[Species], [k].[CountryId], [k].[Discriminator], [k].[Name], [ FROM [Animal] AS [k] WHERE ([k].[Discriminator] = N'Kiwi') AND [k].[Species] LIKE N'%' + N'owenii' -@p1: Apteryx owenii (Nullable = false) (Size = 4000) -@p0: Aquila chrysaetos canadensis (Size = 4000) +@p1: Apteryx owenii (Nullable = false) (Size = 100) +@p0: Aquila chrysaetos canadensis (Size = 100) SET NOCOUNT ON; UPDATE [Animal] SET [EagleId] = @p0 @@ -324,7 +324,7 @@ SELECT TOP(2) [k].[Species], [k].[CountryId], [k].[Discriminator], [k].[Name], [ FROM [Animal] AS [k] WHERE ([k].[Discriminator] = N'Kiwi') AND [k].[Species] LIKE N'%' + N'owenii' -@p0: Apteryx owenii (Nullable = false) (Size = 4000) +@p0: Apteryx owenii (Nullable = false) (Size = 100) SET NOCOUNT ON; DELETE FROM [Animal] diff --git a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/QueryBugsTest.cs b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/QueryBugsTest.cs index c77e4fa0481..c525db3a6b8 100644 --- a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/QueryBugsTest.cs +++ b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/QueryBugsTest.cs @@ -434,8 +434,8 @@ public void Execute1742(CustomerDetails_1742 details) ctx.Customers.Where(c => c.FirstName == firstName && c.LastName == details.LastName).ToList(); const string expectedSql - = @"@__firstName_0: Foo (Size = 4000) -@__8__locals1_details_LastName_1: Bar (Size = 4000) + = @"@__firstName_0: Foo (Size = 450) +@__8__locals1_details_LastName_1: Bar (Size = 450) SELECT [c].[FirstName], [c].[LastName] FROM [Customer] AS [c] diff --git a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/QuerySqlServerTest.cs b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/QuerySqlServerTest.cs index 010b2552933..0d3140651fd 100644 --- a/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/QuerySqlServerTest.cs +++ b/test/Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests/QuerySqlServerTest.cs @@ -30,7 +30,7 @@ public override void Local_array() base.Local_array(); Assert.Equal( - @"@__get_Item_0: ALFKI (Size = 4000) + @"@__get_Item_0: ALFKI (Size = 450) SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] @@ -54,7 +54,7 @@ public override void Entity_equality_local() base.Entity_equality_local(); Assert.Equal( - @"@__local_0_CustomerID: ANATR (Nullable = false) (Size = 4000) + @"@__local_0_CustomerID: ANATR (Nullable = false) (Size = 450) SELECT [c].[CustomerID] FROM [Customers] AS [c] @@ -744,7 +744,7 @@ public override void Where_subquery_closure_via_query_cache() base.Where_subquery_closure_via_query_cache(); Assert.Equal( - @"@__customerID_0: ALFKI (Size = 4000) + @"@__customerID_0: ALFKI (Size = 450) SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] @@ -753,7 +753,7 @@ SELECT 1 FROM [Orders] AS [o] WHERE ([o].[CustomerID] = @__customerID_0) AND ([o].[CustomerID] = [c].[CustomerID])) -@__customerID_0: ANATR (Size = 4000) +@__customerID_0: ANATR (Size = 450) SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] @@ -4886,13 +4886,13 @@ public override void Contains_with_local_list_inline_closure_mix() base.Contains_with_local_list_inline_closure_mix(); Assert.Equal( - @"@__id_0: ALFKI (Size = 4000) + @"@__id_0: ALFKI (Size = 450) SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] WHERE [c].[CustomerID] IN (N'ABCDE', @__id_0) -@__id_0: ANATR (Size = 4000) +@__id_0: ANATR (Size = 450) SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] @@ -5362,7 +5362,7 @@ public override void Environment_newline_is_funcletized() Assert.Equal( @"@__NewLine_0: - (Size = 4000) + (Size = 450) SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] diff --git a/test/Microsoft.EntityFrameworkCore.SqlServer.Tests/SqlServerTypeMapperTest.cs b/test/Microsoft.EntityFrameworkCore.SqlServer.Tests/SqlServerTypeMapperTest.cs index c2c432966aa..0188031bf6c 100644 --- a/test/Microsoft.EntityFrameworkCore.SqlServer.Tests/SqlServerTypeMapperTest.cs +++ b/test/Microsoft.EntityFrameworkCore.SqlServer.Tests/SqlServerTypeMapperTest.cs @@ -134,7 +134,7 @@ public void Does_non_key_SQL_Server_string_mapping() Assert.Null(typeMapping.DbType); Assert.Equal("nvarchar(max)", typeMapping.StoreType); - Assert.Null(typeMapping.Size); + Assert.Equal(4000, typeMapping.Size); Assert.True(typeMapping.IsUnicode); Assert.Equal(4000, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); } @@ -148,7 +148,7 @@ public void Does_non_key_SQL_Server_string_mapping_with_max_length() Assert.Equal("nvarchar(3)", typeMapping.StoreType); Assert.Equal(3, typeMapping.Size); Assert.True(typeMapping.IsUnicode); - Assert.Equal(4000, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); + Assert.Equal(-1, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); } [Fact] @@ -158,7 +158,7 @@ public void Does_non_key_SQL_Server_string_mapping_with_long_string() Assert.Null(typeMapping.DbType); Assert.Equal("nvarchar(max)", typeMapping.StoreType); - Assert.Null(typeMapping.Size); + Assert.Equal(4000, typeMapping.Size); Assert.True(typeMapping.IsUnicode); Assert.Equal(-1, typeMapping.CreateParameter(new TestCommand(), "Name", new string('X', 4001)).Size); } @@ -182,7 +182,7 @@ public void Does_non_key_SQL_Server_required_string_mapping() Assert.Null(typeMapping.DbType); Assert.Equal("nvarchar(max)", typeMapping.StoreType); - Assert.Null(typeMapping.Size); + Assert.Equal(4000, typeMapping.Size); Assert.True(typeMapping.IsUnicode); Assert.Equal(4000, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); } @@ -200,7 +200,7 @@ public void Does_key_SQL_Server_string_mapping() Assert.Equal("nvarchar(450)", typeMapping.StoreType); Assert.Equal(450, typeMapping.Size); Assert.True(typeMapping.IsUnicode); - Assert.Equal(4000, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); + Assert.Equal(450, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); } [Fact] @@ -218,7 +218,7 @@ public void Does_foreign_key_SQL_Server_string_mapping() Assert.Equal("nvarchar(450)", typeMapping.StoreType); Assert.Equal(450, typeMapping.Size); Assert.True(typeMapping.IsUnicode); - Assert.Equal(4000, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); + Assert.Equal(450, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); } [Fact] @@ -237,7 +237,7 @@ public void Does_required_foreign_key_SQL_Server_string_mapping() Assert.Equal("nvarchar(450)", typeMapping.StoreType); Assert.Equal(450, typeMapping.Size); Assert.True(typeMapping.IsUnicode); - Assert.Equal(4000, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); + Assert.Equal(450, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); } [Fact] @@ -253,7 +253,7 @@ public void Does_indexed_column_SQL_Server_string_mapping() Assert.Equal("nvarchar(450)", typeMapping.StoreType); Assert.Equal(450, typeMapping.Size); Assert.True(typeMapping.IsUnicode); - Assert.Equal(4000, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); + Assert.Equal(450, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); } [Fact] @@ -263,7 +263,7 @@ public void Does_non_key_SQL_Server_binary_mapping() Assert.Equal(DbType.Binary, typeMapping.DbType); Assert.Equal("varbinary(max)", typeMapping.StoreType); - Assert.Null(typeMapping.Size); + Assert.Equal(8000, typeMapping.Size); Assert.Equal(8000, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); } @@ -275,7 +275,7 @@ public void Does_non_key_SQL_Server_binary_mapping_with_max_length() Assert.Equal(DbType.Binary, typeMapping.DbType); Assert.Equal("varbinary(3)", typeMapping.StoreType); Assert.Equal(3, typeMapping.Size); - Assert.Equal(8000, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); + Assert.Equal(3, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); } [Fact] @@ -285,7 +285,7 @@ public void Does_non_key_SQL_Server_binary_mapping_with_long_string() Assert.Equal(DbType.Binary, typeMapping.DbType); Assert.Equal("varbinary(max)", typeMapping.StoreType); - Assert.Null(typeMapping.Size); + Assert.Equal(8000, typeMapping.Size); Assert.Equal(-1, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[8001]).Size); } @@ -307,7 +307,7 @@ public void Does_non_key_SQL_Server_required_binary_mapping() Assert.Equal(DbType.Binary, typeMapping.DbType); Assert.Equal("varbinary(max)", typeMapping.StoreType); - Assert.Null(typeMapping.Size); + Assert.Equal(8000, typeMapping.Size); Assert.Equal(8000, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); } @@ -334,7 +334,7 @@ public void Does_key_SQL_Server_binary_mapping() Assert.Equal(DbType.Binary, typeMapping.DbType); Assert.Equal("varbinary(900)", typeMapping.StoreType); - Assert.Equal(8000, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); + Assert.Equal(900, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); } [Fact] @@ -350,7 +350,7 @@ public void Does_foreign_key_SQL_Server_binary_mapping() Assert.Equal(DbType.Binary, typeMapping.DbType); Assert.Equal("varbinary(900)", typeMapping.StoreType); - Assert.Equal(8000, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); + Assert.Equal(900, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); } [Fact] @@ -367,7 +367,7 @@ public void Does_required_foreign_key_SQL_Server_binary_mapping() Assert.Equal(DbType.Binary, typeMapping.DbType); Assert.Equal("varbinary(900)", typeMapping.StoreType); - Assert.Equal(8000, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); + Assert.Equal(900, typeMapping.CreateParameter(new TestCommand(), "Name", new byte[3]).Size); } [Fact] @@ -381,7 +381,7 @@ public void Does_indexed_column_SQL_Server_binary_mapping() Assert.Equal(DbType.Binary, typeMapping.DbType); Assert.Equal("varbinary(900)", typeMapping.StoreType); - Assert.Equal(8000, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); + Assert.Equal(900, typeMapping.CreateParameter(new TestCommand(), "Name", "Value").Size); } [Fact] @@ -486,28 +486,28 @@ public void Throws_for_unrecognized_types() } [Theory] - [InlineData("VARCHAR", typeof(string), null, false)] - [InlineData("VarCHaR", typeof(string), null, false)] // case-insensitive + [InlineData("VARCHAR", typeof(string), 8000, false)] + [InlineData("VarCHaR", typeof(string), 8000, false)] // case-insensitive [InlineData("float", typeof(double), null, false)] // This is correct. SQL Server 'float' type maps to C# double [InlineData("timestamp", typeof(byte[]), 8, false)] // note: rowversion is a synonym but SQL Server stores the data type as 'timestamp' - [InlineData("nvarchar(max)", typeof(string), null, true)] + [InlineData("nvarchar(max)", typeof(string), 4000, true)] [InlineData("nvarchar(333)", typeof(string), 333, true)] [InlineData("bigint", typeof(long), null, false)] - [InlineData("binary varying", typeof(byte[]), null, false)] - [InlineData("binary varying(max)", typeof(byte[]), null, false)] + [InlineData("binary varying", typeof(byte[]), 8000, false)] + [InlineData("binary varying(max)", typeof(byte[]), 8000, false)] [InlineData("binary varying(333)", typeof(byte[]), 333, false)] - [InlineData("binary", typeof(byte[]), null, false)] + [InlineData("binary", typeof(byte[]), 8000, false)] [InlineData("binary(333)", typeof(byte[]), 333, false)] [InlineData("bit", typeof(bool), null, false)] - [InlineData("char varying", typeof(string), null, false)] - [InlineData("char varying(max)", typeof(string), null, false)] + [InlineData("char varying", typeof(string), 8000, false)] + [InlineData("char varying(max)", typeof(string), 8000, false)] [InlineData("char varying(333)", typeof(string), 333, false)] - [InlineData("char", typeof(string), null, false)] + [InlineData("char", typeof(string), 8000, false)] [InlineData("char(333)", typeof(string), 333, false)] - [InlineData("character varying", typeof(string), null, false)] - [InlineData("character varying(max)", typeof(string), null, false)] + [InlineData("character varying", typeof(string), 8000, false)] + [InlineData("character varying(max)", typeof(string), 8000, false)] [InlineData("character varying(333)", typeof(string), 333, false)] - [InlineData("character", typeof(string), null, false)] + [InlineData("character", typeof(string), 8000, false)] [InlineData("character(333)", typeof(string), 333, false)] [InlineData("date", typeof(DateTime), null, false)] [InlineData("datetime", typeof(DateTime), null, false)] @@ -517,41 +517,41 @@ public void Throws_for_unrecognized_types() [InlineData("decimal", typeof(decimal), null, false)] [InlineData("float", typeof(double), null, false)] [InlineData("float(10, 8)", typeof(double), null, false)] - [InlineData("image", typeof(byte[]), null, false)] + [InlineData("image", typeof(byte[]), 8000, false)] [InlineData("int", typeof(int), null, false)] [InlineData("money", typeof(decimal), null, false)] - [InlineData("national char varying", typeof(string), null, true)] - [InlineData("national char varying(max)", typeof(string), null, true)] + [InlineData("national char varying", typeof(string), 4000, true)] + [InlineData("national char varying(max)", typeof(string), 4000, true)] [InlineData("national char varying(333)", typeof(string), 333, true)] - [InlineData("national character varying", typeof(string), null, true)] - [InlineData("national character varying(max)", typeof(string), null, true)] + [InlineData("national character varying", typeof(string), 4000, true)] + [InlineData("national character varying(max)", typeof(string), 4000, true)] [InlineData("national character varying(333)", typeof(string), 333, true)] - [InlineData("national character", typeof(string), null, true)] + [InlineData("national character", typeof(string), 4000, true)] [InlineData("national character(333)", typeof(string), 333, true)] - [InlineData("nchar", typeof(string), null, true)] + [InlineData("nchar", typeof(string), 4000, true)] [InlineData("nchar(333)", typeof(string), 333, true)] - [InlineData("ntext", typeof(string), null, true)] + [InlineData("ntext", typeof(string), 4000, true)] [InlineData("numeric", typeof(decimal), null, false)] - [InlineData("nvarchar", typeof(string), null, true)] - [InlineData("nvarchar(max)", typeof(string), null, true)] + [InlineData("nvarchar", typeof(string), 4000, true)] + [InlineData("nvarchar(max)", typeof(string), 4000, true)] [InlineData("nvarchar(333)", typeof(string), 333, true)] [InlineData("real", typeof(float), null, false)] [InlineData("rowversion", typeof(byte[]), 8, false)] [InlineData("smalldatetime", typeof(DateTime), null, false)] [InlineData("smallint", typeof(short), null, false)] [InlineData("smallmoney", typeof(decimal), null, false)] - [InlineData("text", typeof(string), null, false)] + [InlineData("text", typeof(string), 8000, false)] [InlineData("time", typeof(TimeSpan), null, false)] [InlineData("timestamp", typeof(byte[]), 8, false)] [InlineData("tinyint", typeof(byte), null, false)] [InlineData("uniqueidentifier", typeof(Guid), null, false)] - [InlineData("varbinary", typeof(byte[]), null, false)] - [InlineData("varbinary(max)", typeof(byte[]), null, false)] + [InlineData("varbinary", typeof(byte[]), 8000, false)] + [InlineData("varbinary(max)", typeof(byte[]), 8000, false)] [InlineData("varbinary(333)", typeof(byte[]), 333, false)] - [InlineData("varchar", typeof(string), null, false)] - [InlineData("varchar(max)", typeof(string), null, false)] + [InlineData("varchar", typeof(string), 8000, false)] + [InlineData("varchar(max)", typeof(string), 8000, false)] [InlineData("varchar(333)", typeof(string), 333, false)] - [InlineData("xml", typeof(string), null, false)] + [InlineData("xml", typeof(string), 4000, true)] public void Can_map_by_type_name(string typeName, Type clrType, int? size, bool unicode) { var mapping = new SqlServerTypeMapper().GetMapping(typeName);