diff --git a/Directory.Build.props b/Directory.Build.props
index 36432f73130..4ea29042ac6 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -42,11 +42,6 @@
https://docs.microsoft.com/ef/core/
-
-
-
-
-
$(WarningsNotAsErrors);CS1591;SA1636
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 58605e9ceb0..16f8a0c019e 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -9,7 +9,7 @@
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 033722b5eb7..aa704ddcde6 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -292,15 +292,16 @@ stages:
arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token
env:
Token: $(dn-bot-dnceng-artifact-feeds-rw)
- - script: restore.cmd -ci /p:configuration=$(_BuildConfig)
+ - script: restore.cmd -ci /p:configuration=$(_BuildConfig) $(_InternalRuntimeDownloadArgs)
displayName: Restore packages
- - script: .dotnet\dotnet build eng\helix.proj /restore /t:Test /p:configuration=$(_BuildConfig) /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog
+ - script: .dotnet\dotnet build eng\helix.proj /restore /t:Test /p:configuration=$(_BuildConfig) /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog $(_InternalRuntimeDownloadArgs)
displayName: Send job to helix
env:
HelixAccessToken: $(_HelixAccessToken)
SYSTEM_ACCESSTOKEN: $(System.AccessToken) # We need to set this env var to publish helix results to Azure Dev Ops
MSSQL_SA_PASSWORD: "Password12!"
COMPlus_EnableWriteXorExecute: 0 # Work-around for https://github.com/dotnet/runtime/issues/70758
+ DotNetBuildsInternalReadSasToken: $(dotnetbuilds-internal-container-read-token)
- ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), ne(variables.runCodeQL3000, 'true')) }}:
- template: eng\common\templates\post-build\post-build.yml
diff --git a/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj b/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj
index 0656a32498b..b693456dfed 100644
--- a/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj
+++ b/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index b98f6d8eebc..1f2996a49ec 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,72 +1,72 @@
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/runtime
- f8c110b8003d68cc635add4ca791d6cf2e645561
+ 9f4c5f7766ba6e6899bc998e17ca91a4fcc2d8d5
-
+ https://github.com/dotnet/arcade
- 385129cbc980a515ddee2fa56f6b16f3183ed9bc
+ 4665b3d04e1da3796b965c3c3e3b97f55c449a6e
-
+ https://github.com/dotnet/arcade
- 385129cbc980a515ddee2fa56f6b16f3183ed9bc
+ 4665b3d04e1da3796b965c3c3e3b97f55c449a6e
-
+ https://github.com/dotnet/arcade
- 385129cbc980a515ddee2fa56f6b16f3183ed9bc
+ 4665b3d04e1da3796b965c3c3e3b97f55c449a6e
diff --git a/eng/Versions.props b/eng/Versions.props
index b472ecee542..7981ccc2942 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -16,22 +16,22 @@
False
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
- 8.0.0-rc.1.23421.3
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
+ 9.0.0-alpha.1.23465.19
- 8.0.0-beta.23419.1
+ 8.0.0-beta.23451.1
diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake
index a88d643c8a7..0998e875e5f 100644
--- a/eng/common/cross/toolchain.cmake
+++ b/eng/common/cross/toolchain.cmake
@@ -207,6 +207,7 @@ elseif(ILLUMOS)
set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lssp")
elseif(HAIKU)
set(CMAKE_SYSROOT "${CROSS_ROOTFS}")
+ set(CMAKE_PROGRAM_PATH "${CMAKE_PROGRAM_PATH};${CROSS_ROOTFS}/cross-tools-x86_64/bin")
set(TOOLSET_PREFIX ${TOOLCHAIN}-)
function(locate_toolchain_exec exec var)
@@ -217,7 +218,6 @@ elseif(HAIKU)
endif()
find_program(EXEC_LOCATION_${exec}
- PATHS "${CROSS_ROOTFS}/cross-tools-x86_64/bin"
NAMES
"${TOOLSET_PREFIX}${exec}${CLR_CMAKE_COMPILER_FILE_NAME_VERSION}"
"${TOOLSET_PREFIX}${exec}")
diff --git a/eng/common/loc/P22DotNetHtmlLocalization.lss b/eng/common/loc/P22DotNetHtmlLocalization.lss
index 858a0b237c6..5d892d61939 100644
Binary files a/eng/common/loc/P22DotNetHtmlLocalization.lss and b/eng/common/loc/P22DotNetHtmlLocalization.lss differ
diff --git a/eng/helix.proj b/eng/helix.proj
index cb785fbeab2..fce3e5c0614 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -28,6 +28,11 @@
runtime
+
+
+ $([System.Environment]::GetEnvironmentVariable('DotNetBuildsInternalReadSasToken'))
+
diff --git a/global.json b/global.json
index 3ce448dab21..c0684a3f40e 100644
--- a/global.json
+++ b/global.json
@@ -1,11 +1,11 @@
{
"sdk": {
- "version": "8.0.100-rc.1.23407.2",
+ "version": "8.0.100-rc.2.23461.1",
"allowPrerelease": true,
"rollForward": "latestMajor"
},
"tools": {
- "dotnet": "8.0.100-rc.1.23407.2",
+ "dotnet": "8.0.100-rc.2.23461.1",
"runtimes": {
"dotnet": [
"$(MicrosoftNETCoreBrowserDebugHostTransportVersion)"
@@ -13,7 +13,7 @@
}
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23419.1",
- "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23419.1"
+ "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23451.1",
+ "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23451.1"
}
}
diff --git a/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs b/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs
index b396ce16b2f..e26e454ba6d 100644
--- a/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs
+++ b/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs
@@ -65,6 +65,17 @@ public virtual CosmosDbContextOptionsBuilder ExecutionStrategy(
public virtual CosmosDbContextOptionsBuilder Region(string region)
=> WithOption(e => e.WithRegion(Check.NotNull(region, nameof(region))));
+ ///
+ /// Configures the context to use the provided preferred regions for geo-replicated database accounts.
+ ///
+ ///
+ /// See Using DbContextOptions, and
+ /// Accessing Azure Cosmos DB with EF Core for more information and examples.
+ ///
+ /// A list of Azure Cosmos DB region names.
+ public virtual CosmosDbContextOptionsBuilder PreferredRegions(IReadOnlyList regions)
+ => WithOption(e => e.WithPreferredRegions(Check.NotNull(regions, nameof(regions))));
+
///
/// Limits the operations to the provided endpoint.
///
diff --git a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs
index 33c4c7588f0..9a7792b57e5 100644
--- a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs
+++ b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs
@@ -23,6 +23,7 @@ public class CosmosOptionsExtension : IDbContextOptionsExtension
private string? _connectionString;
private string? _databaseName;
private string? _region;
+ private IReadOnlyList? _preferredRegions;
private ConnectionMode? _connectionMode;
private bool? _limitToEndpoint;
private Func? _executionStrategyFactory;
@@ -61,6 +62,7 @@ protected CosmosOptionsExtension(CosmosOptionsExtension copyFrom)
_databaseName = copyFrom._databaseName;
_connectionString = copyFrom._connectionString;
_region = copyFrom._region;
+ _preferredRegions = copyFrom._preferredRegions;
_connectionMode = copyFrom._connectionMode;
_limitToEndpoint = copyFrom._limitToEndpoint;
_executionStrategyFactory = copyFrom._executionStrategyFactory;
@@ -247,6 +249,30 @@ public virtual CosmosOptionsExtension WithRegion(string? region)
return clone;
}
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual IReadOnlyList? PreferredRegions
+ => _preferredRegions;
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual CosmosOptionsExtension WithPreferredRegions(IReadOnlyList? regions)
+ {
+ var clone = Clone();
+
+ clone._preferredRegions = regions;
+
+ return clone;
+ }
+
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
diff --git a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosSingletonOptions.cs b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosSingletonOptions.cs
index 22f657166c6..4426c1ecc9c 100644
--- a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosSingletonOptions.cs
+++ b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosSingletonOptions.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Collections;
using System.Net;
using Azure.Core;
@@ -54,6 +55,14 @@ public class CosmosSingletonOptions : ICosmosSingletonOptions
///
public virtual string? Region { get; private set; }
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual IReadOnlyList? PreferredRegions { get; private set; }
+
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@@ -158,6 +167,7 @@ public virtual void Initialize(IDbContextOptions options)
TokenCredential = cosmosOptions.TokenCredential;
ConnectionString = cosmosOptions.ConnectionString;
Region = cosmosOptions.Region;
+ PreferredRegions = cosmosOptions.PreferredRegions;
LimitToEndpoint = cosmosOptions.LimitToEndpoint;
EnableContentResponseOnWrite = cosmosOptions.EnableContentResponseOnWrite;
ConnectionMode = cosmosOptions.ConnectionMode;
@@ -188,6 +198,7 @@ public virtual void Validate(IDbContextOptions options)
|| TokenCredential != cosmosOptions.TokenCredential
|| ConnectionString != cosmosOptions.ConnectionString
|| Region != cosmosOptions.Region
+ || !StructuralComparisons.StructuralEqualityComparer.Equals(PreferredRegions, cosmosOptions.PreferredRegions)
|| LimitToEndpoint != cosmosOptions.LimitToEndpoint
|| ConnectionMode != cosmosOptions.ConnectionMode
|| WebProxy != cosmosOptions.WebProxy
diff --git a/src/EFCore.Cosmos/Infrastructure/Internal/ICosmosSingletonOptions.cs b/src/EFCore.Cosmos/Infrastructure/Internal/ICosmosSingletonOptions.cs
index b38e4f40993..a26b79a82b3 100644
--- a/src/EFCore.Cosmos/Infrastructure/Internal/ICosmosSingletonOptions.cs
+++ b/src/EFCore.Cosmos/Infrastructure/Internal/ICosmosSingletonOptions.cs
@@ -60,6 +60,14 @@ public interface ICosmosSingletonOptions : ISingletonOptions
///
string? Region { get; }
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ IReadOnlyList? PreferredRegions { get; }
+
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs
index eb8c3c01766..b5e7fb2c6bc 100644
--- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs
@@ -154,6 +154,24 @@ static bool ExtractPartitionKeyFromPredicate(
return true;
}
}
+ else if (joinCondition is MethodCallExpression
+ {
+ Method.Name: "Equals",
+ Object: null,
+ Arguments: [MethodCallExpression equalsMethodCallExpression, ParameterExpression parameterExpresion]
+ }
+ && equalsMethodCallExpression.TryGetEFPropertyArguments(out _, out var propertyName))
+ {
+ var property = entityType.FindProperty(propertyName);
+ if (property == null)
+ {
+ return false;
+ }
+
+ properties.Add(property);
+ parameterNames.Add(parameterExpresion.Name);
+ return true;
+ }
return false;
}
diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs
index 7079cec7b45..f34e5b1c1cb 100644
--- a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs
@@ -840,7 +840,7 @@ private bool TryRewriteContainsEntity(Expression source, Expression item, out Ex
var propertyGetter = property.GetGetter();
foreach (var value in values)
{
- propertyValueList.Add(propertyGetter.GetStructuralTypeClrValue(value));
+ propertyValueList.Add(propertyGetter.GetClrValue(value));
}
rewrittenSource = Expression.Constant(propertyValueList);
@@ -971,7 +971,7 @@ private Expression CreatePropertyAccessExpression(Expression target, IProperty p
{
case SqlConstantExpression sqlConstantExpression:
return Expression.Constant(
- property.GetGetter().GetStructuralTypeClrValue(sqlConstantExpression.Value!), property.ClrType.MakeNullable());
+ property.GetGetter().GetClrValue(sqlConstantExpression.Value!), property.ClrType.MakeNullable());
case SqlParameterExpression sqlParameterExpression
when sqlParameterExpression.Name.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal):
@@ -1002,7 +1002,7 @@ when memberInitExpression.Bindings.SingleOrDefault(
private static T ParameterValueExtractor(QueryContext context, string baseParameterName, IProperty property)
{
var baseParameter = context.ParameterValues[baseParameterName];
- return baseParameter == null ? (T)(object)null : (T)property.GetGetter().GetStructuralTypeClrValue(baseParameter);
+ return baseParameter == null ? (T)(object)null : (T)property.GetGetter().GetClrValue(baseParameter);
}
private static List ParameterListValueExtractor(
@@ -1016,7 +1016,7 @@ private static List ParameterListValueExtractor(
}
var getter = property.GetGetter();
- return baseListParameter.Select(e => e != null ? (TProperty)getter.GetStructuralTypeClrValue(e) : (TProperty)(object)null).ToList();
+ return baseListParameter.Select(e => e != null ? (TProperty)getter.GetClrValue(e) : (TProperty)(object)null).ToList();
}
private static bool IsNullSqlConstantExpression(Expression expression)
diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMapping.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMapping.cs
index cb62bd9a9e5..726e907c271 100644
--- a/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMapping.cs
+++ b/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMapping.cs
@@ -60,12 +60,13 @@ protected CosmosTypeMapping(CoreTypeMappingParameters parameters)
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
- public override CoreTypeMapping Clone(
+ public override CoreTypeMapping WithComposedConverter(
ValueConverter? converter,
ValueComparer? comparer = null,
+ ValueComparer? keyComparer = null,
CoreTypeMapping? elementMapping = null,
JsonValueReaderWriter? jsonValueReaderWriter = null)
- => new CosmosTypeMapping(Parameters.WithComposedConverter(converter, comparer, elementMapping, jsonValueReaderWriter));
+ => new CosmosTypeMapping(Parameters.WithComposedConverter(converter, comparer, keyComparer, elementMapping, jsonValueReaderWriter));
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs
index ce9dd461aaf..d01c7aedd18 100644
--- a/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs
+++ b/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs
@@ -71,6 +71,12 @@ public CosmosTypeMappingSource(TypeMappingSourceDependencies dependencies)
private CoreTypeMapping? FindCollectionMapping(in TypeMappingInfo mappingInfo)
{
var clrType = mappingInfo.ClrType!;
+
+ if (mappingInfo.ElementTypeMapping != null)
+ {
+ return null;
+ }
+
var elementType = clrType.TryGetSequenceType();
if (elementType == null)
{
diff --git a/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs
index bc4f620c922..4e99f2e0b00 100644
--- a/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs
+++ b/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs
@@ -41,6 +41,11 @@ public SingletonCosmosClientWrapper(ICosmosSingletonOptions options)
configuration.ApplicationRegion = options.Region;
}
+ if (options.PreferredRegions != null)
+ {
+ configuration.ApplicationPreferredRegions = options.PreferredRegions;
+ }
+
if (options.LimitToEndpoint != null)
{
configuration.LimitToEndpoint = options.LimitToEndpoint.Value;
diff --git a/src/EFCore.Design/Extensions/MethodCallCodeFragmentExtensions.cs b/src/EFCore.Design/Extensions/MethodCallCodeFragmentExtensions.cs
new file mode 100644
index 00000000000..e1c3e4d54bd
--- /dev/null
+++ b/src/EFCore.Design/Extensions/MethodCallCodeFragmentExtensions.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.EntityFrameworkCore.Design;
+
+///
+/// Design-time extensions.
+///
+public static class MethodCallCodeFragmentExtensions
+{
+ ///
+ /// Gets the using statements required for this method call.
+ ///
+ /// The method call.
+ /// The usings.
+ public static IEnumerable GetRequiredUsings(this MethodCallCodeFragment methodCall)
+ {
+ var method = methodCall.MethodInfo;
+ if (method?.IsStatic == true)
+ {
+ yield return method.DeclaringType!.Namespace!;
+ }
+
+ foreach (var argument in methodCall.Arguments)
+ {
+ if (argument is NestedClosureCodeFragment nestedClosure)
+ {
+ foreach (var nestedUsing in nestedClosure.MethodCalls.SelectMany(GetRequiredUsings))
+ {
+ yield return nestedUsing;
+ }
+ }
+ else if (argument is not null)
+ {
+ yield return argument.GetType().Namespace!;
+ }
+ }
+ }
+}
diff --git a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
index 7092724682c..365a06a3f97 100644
--- a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
+++ b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
@@ -576,7 +576,8 @@ protected virtual void GenerateComplexProperty(
{
stringBuilder
.AppendLine()
- .Append(".IsRequired()");
+ .Append(complexTypeBuilderName)
+ .AppendLine(".IsRequired();");
}
GenerateProperties(complexTypeBuilderName, complexType.GetDeclaredProperties(), stringBuilder);
diff --git a/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs b/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs
index c29f44c1e4e..32e50b6be63 100644
--- a/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs
+++ b/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs
@@ -882,7 +882,7 @@ protected override Expression VisitConstant(ConstantExpression constant)
ExpressionSyntax GenerateValue(object? value)
=> value switch
{
- int or long or uint or ulong or short or sbyte or ushort or byte or double or float or decimal
+ int or long or uint or ulong or short or sbyte or ushort or byte or double or float or decimal or char
=> (ExpressionSyntax)_g.LiteralExpression(constant.Value),
string or bool or null => (ExpressionSyntax)_g.LiteralExpression(constant.Value),
diff --git a/src/EFCore.Design/README.md b/src/EFCore.Design/README.md
new file mode 100644
index 00000000000..ba2b49b132b
--- /dev/null
+++ b/src/EFCore.Design/README.md
@@ -0,0 +1,45 @@
+The Entity Framework Core tools help with design-time development tasks. They're primarily used to manage Migrations and to scaffold a DbContext and entity types by reverse engineering the schema of a database.
+Microsoft.EntityFrameworkCore.Design is for cross-platform command line tooling.
+
+## Getting started
+
+`Microsoft.EntityFrameworkCore.Design` contains all the design-time logic for Entity Framework Core. It's the code that all of the various tools (PMC cmdlets like `Add-Migration`, `dotnet ef` & `ef.exe`) call into.
+
+If you don't use Migrations or Reverse Engineering, you don't need it.
+
+And when you do need it, we encourage `PrivateAssets="All" `so it doesn't get published to the server where you almost certainly won't need it.
+
+### Prerequisites
+
+Before using the tools:
+
+- [Understand the difference between target and startup project](https://learn.microsoft.com/en-us/ef/core/cli/powershell#target-and-startup-project).
+- [Learn how to use the tools with .NET Standard class libraries](https://learn.microsoft.com/en-us/ef/core/cli/powershell#other-target-frameworks).
+- [For ASP.NET Core projects, set the environment](https://learn.microsoft.com/en-us/ef/core/cli/powershell#aspnet-core-environment).
+
+## Usage
+
+PMC Command | Usage
+-- | --
+Get-Help entityframework |Displays information about entity framework commands.
+[Add-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#add-migration) | Creates a migration by adding a migration snapshot.
+[Bundle-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#bundle-migration) | Creates an executable to update the database.
+[Get-DbContext](https://learn.microsoft.com/en-us/ef/core/cli/powershell#get-dbcontext) | Gets information about a DbContext type.
+[Drop-Database](https://learn.microsoft.com/en-us/ef/core/cli/powershell#drop-database) | Drops the database.
+[Get-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#get-migration) | Lists available migrations.
+[Optimize-DbContext](https://learn.microsoft.com/en-us/ef/core/cli/powershell#optimize-dbcontext) | Generates a compiled version of the model used by the `DbContext`.
+[Remove-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#remove-migration) | Removes the last migration snapshot.
+[Scaffold-DbContext](https://learn.microsoft.com/en-us/ef/core/cli/powershell#scaffold-dbcontext) | Generates a DbContext and entity type classes for a specified database. This is called reverse engineering.
+[Script-DbContext](https://learn.microsoft.com/en-us/ef/core/cli/powershell#script-dbcontext) | Generates a SQL script from the DbContext. Bypasses any migrations.
+[Script-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#script-migration) | Generates a SQL script using all the migration snapshots.
+[Update-Database](https://learn.microsoft.com/en-us/ef/core/cli/powershell#update-database) | Updates the database schema based on the last migration snapshot.
+
+## Additional documentation
+
+- [Migrations](https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/)
+- [Reverse Engineering](https://learn.microsoft.com/en-us/ef/core/managing-schemas/scaffolding/?tabs=dotnet-core-cli)
+- [Compiled models](https://learn.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-di%2Cwith-constant#compiled-models)
+
+## Feedback
+
+If you encounter a bug or issues with this package,you can [open an Github issue](https://github.com/dotnet/efcore/issues/new/choose). For more details, see [getting support](https://github.com/dotnet/efcore/blob/main/.github/SUPPORT.md).
\ No newline at end of file
diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs
index 79dd3634758..c28d92bf0a0 100644
--- a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs
+++ b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs
@@ -101,8 +101,11 @@ public virtual string TransformText()
}
+ var useProviderCall = providerCode.GenerateUseProvider(Options.ConnectionString);
+ usings.AddRange(useProviderCall.GetRequiredUsings());
+
this.Write(" => optionsBuilder");
- this.Write(this.ToStringHelper.ToStringWithCulture(code.Fragment(providerCode.GenerateUseProvider(Options.ConnectionString), indent: 3)));
+ this.Write(this.ToStringHelper.ToStringWithCulture(code.Fragment(useProviderCall, indent: 3)));
this.Write(";\r\n\r\n");
}
@@ -617,7 +620,7 @@ public class CSharpDbContextGeneratorBase
///
/// The string builder that generation-time code is using to assemble generated output
///
- protected System.Text.StringBuilder GenerationEnvironment
+ public System.Text.StringBuilder GenerationEnvironment
{
get
{
diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.tt b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.tt
index 80e3c9eca95..0741e40e6b9 100644
--- a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.tt
+++ b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.tt
@@ -78,8 +78,11 @@ public partial class <#= Options.ContextName #> : DbContext
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
<#
}
+
+ var useProviderCall = providerCode.GenerateUseProvider(Options.ConnectionString);
+ usings.AddRange(useProviderCall.GetRequiredUsings());
#>
- => optionsBuilder<#= code.Fragment(providerCode.GenerateUseProvider(Options.ConnectionString), indent: 3) #>;
+ => optionsBuilder<#= code.Fragment(useProviderCall, indent: 3) #>;
<#
}
diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs
index b6c4f0131db..f649b462a92 100644
--- a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs
+++ b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs
@@ -1288,7 +1288,7 @@ private bool TryRewriteContainsEntity(Expression? source, Expression item, [NotN
var propertyGetter = property.GetGetter();
foreach (var value in values)
{
- propertyValueList.Add(propertyGetter.GetStructuralTypeClrValue(value));
+ propertyValueList.Add(propertyGetter.GetClrValue(value));
}
rewrittenSource = Expression.Constant(propertyValueList);
@@ -1436,7 +1436,7 @@ private Expression CreatePropertyAccessExpression(Expression target, IProperty p
return Expression.Constant(
constantExpression.Value is null
? null
- : property.GetGetter().GetStructuralTypeClrValue(constantExpression.Value),
+ : property.GetGetter().GetClrValue(constantExpression.Value),
property.ClrType.MakeNullable());
case MethodCallExpression { Method.IsGenericMethod: true } methodCallExpression
@@ -1479,7 +1479,7 @@ when CanEvaluate(memberInitExpression):
private static T? ParameterValueExtractor(QueryContext context, string baseParameterName, IProperty property)
{
var baseParameter = context.ParameterValues[baseParameterName];
- return baseParameter == null ? (T?)(object?)null : (T?)property.GetGetter().GetStructuralTypeClrValue(baseParameter);
+ return baseParameter == null ? (T?)(object?)null : (T?)property.GetGetter().GetClrValue(baseParameter);
}
private static List? ParameterListValueExtractor(
@@ -1493,7 +1493,7 @@ when CanEvaluate(memberInitExpression):
}
var getter = property.GetGetter();
- return baseListParameter.Select(e => e != null ? (TProperty?)getter.GetStructuralTypeClrValue(e) : (TProperty?)(object?)null).ToList();
+ return baseListParameter.Select(e => e != null ? (TProperty?)getter.GetClrValue(e) : (TProperty?)(object?)null).ToList();
}
private static ConstantExpression GetValue(Expression expression)
diff --git a/src/EFCore.InMemory/Storage/Internal/InMemoryTypeMapping.cs b/src/EFCore.InMemory/Storage/Internal/InMemoryTypeMapping.cs
index bfd8126ac82..34bd3b51288 100644
--- a/src/EFCore.InMemory/Storage/Internal/InMemoryTypeMapping.cs
+++ b/src/EFCore.InMemory/Storage/Internal/InMemoryTypeMapping.cs
@@ -53,12 +53,13 @@ private InMemoryTypeMapping(CoreTypeMappingParameters parameters)
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
- public override CoreTypeMapping Clone(
+ public override CoreTypeMapping WithComposedConverter(
ValueConverter? converter,
ValueComparer? comparer = null,
+ ValueComparer? keyComparer = null,
CoreTypeMapping? elementMapping = null,
JsonValueReaderWriter? jsonValueReaderWriter = null)
- => new InMemoryTypeMapping(Parameters.WithComposedConverter(converter, comparer, elementMapping, jsonValueReaderWriter));
+ => new InMemoryTypeMapping(Parameters.WithComposedConverter(converter, comparer, keyComparer, elementMapping, jsonValueReaderWriter));
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
diff --git a/src/EFCore.InMemory/Storage/Internal/InMemoryTypeMappingSource.cs b/src/EFCore.InMemory/Storage/Internal/InMemoryTypeMappingSource.cs
index cff9a52809d..f5e83539fb6 100644
--- a/src/EFCore.InMemory/Storage/Internal/InMemoryTypeMappingSource.cs
+++ b/src/EFCore.InMemory/Storage/Internal/InMemoryTypeMappingSource.cs
@@ -37,7 +37,7 @@ public InMemoryTypeMappingSource(TypeMappingSourceDependencies dependencies)
if (clrType.IsValueType
|| clrType == typeof(string)
- || clrType == typeof(byte[]))
+ || (clrType == typeof(byte[]) && mappingInfo.ElementTypeMapping == null))
{
return new InMemoryTypeMapping(
clrType, jsonValueReaderWriter: jsonValueReaderWriter);
diff --git a/src/EFCore.Proxies/Proxies/Internal/PropertyChangedInterceptor.cs b/src/EFCore.Proxies/Proxies/Internal/PropertyChangedInterceptor.cs
index f67e5fc52a0..2637f9e07c8 100644
--- a/src/EFCore.Proxies/Proxies/Internal/PropertyChangedInterceptor.cs
+++ b/src/EFCore.Proxies/Proxies/Internal/PropertyChangedInterceptor.cs
@@ -94,7 +94,7 @@ private void HandleChanged(IInvocation invocation, IPropertyBase property, IEqua
if (_checkEquality)
{
- var oldValue = property.GetGetter().GetClrValue(invocation.Proxy);
+ var oldValue = property.GetGetter().GetClrValueUsingContainingEntity(invocation.Proxy);
invocation.Proceed();
diff --git a/src/EFCore.Proxies/Proxies/Internal/PropertyChangingInterceptor.cs b/src/EFCore.Proxies/Proxies/Internal/PropertyChangingInterceptor.cs
index 670639d5369..ed1cfe38e51 100644
--- a/src/EFCore.Proxies/Proxies/Internal/PropertyChangingInterceptor.cs
+++ b/src/EFCore.Proxies/Proxies/Internal/PropertyChangingInterceptor.cs
@@ -92,7 +92,7 @@ private void HandleChanging(IInvocation invocation, IPropertyBase property, IEqu
{
if (_checkEquality)
{
- var oldValue = property.GetGetter().GetClrValue(invocation.Proxy);
+ var oldValue = property.GetGetter().GetClrValueUsingContainingEntity(invocation.Proxy);
var newValue = invocation.Arguments[^1];
if (!(comparer?.Equals(oldValue, newValue) ?? Equals(oldValue, newValue)))
diff --git a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs
index fe28ee86dc2..aafeac6f7f8 100644
--- a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs
+++ b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs
@@ -61,6 +61,12 @@ public static class RelationalEntityTypeExtensions
return entityType.GetRootType().GetTableName();
}
+ if (entityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy
+ && !entityType.ClrType.IsInstantiable())
+ {
+ return null;
+ }
+
var ownership = entityType.FindOwnership();
if (ownership != null
&& (ownership.IsUnique || entityType.IsMappedToJson()))
@@ -81,12 +87,6 @@ public static class RelationalEntityTypeExtensions
: $"{ownership.PrincipalToDependent.Name}_{name}";
}
- if (entityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy
- && !entityType.ClrType.IsInstantiable())
- {
- return null;
- }
-
return truncate
? Uniquifier.Truncate(name, entityType.Model.GetMaxIdentifierLength())
: name;
@@ -1379,13 +1379,16 @@ public static bool IsTableExcludedFromMigrations(this IReadOnlyEntityType entity
return excluded.Value;
}
- if (entityType.BaseType != null)
+ if (entityType.BaseType != null
+ && entityType.GetMappingStrategy() == RelationalAnnotationNames.TphMappingStrategy)
{
return entityType.GetRootType().IsTableExcludedFromMigrations();
}
var ownership = entityType.FindOwnership();
- if (ownership is { IsUnique: true })
+ if (ownership is { IsUnique: true }
+ && ownership.DeclaringEntityType.GetTableName() == entityType.GetTableName()
+ && ownership.DeclaringEntityType.GetSchema() == entityType.GetSchema())
{
return ownership.PrincipalEntityType.IsTableExcludedFromMigrations();
}
diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs
index 187f3297208..157dc23d827 100644
--- a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs
+++ b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs
@@ -1145,7 +1145,7 @@ public static void SetIsFixedLength(this IMutableProperty property, bool? fixedL
/// if the mapped column is nullable; otherwise.
public static bool IsColumnNullable(this IReadOnlyProperty property)
=> property.IsNullable
- || (property.DeclaringType is IReadOnlyEntityType entityType
+ || (property.DeclaringType.ContainingEntityType is IReadOnlyEntityType entityType
&& entityType.BaseType != null
&& entityType.GetMappingStrategy() == RelationalAnnotationNames.TphMappingStrategy);
diff --git a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs
index 47251be8f88..a14998c9fd4 100644
--- a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs
+++ b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs
@@ -558,7 +558,7 @@ protected virtual IEnumerable Diff(
DiffContext diffContext)
{
if (source.IsExcludedFromMigrations
- && target.IsExcludedFromMigrations)
+ || target.IsExcludedFromMigrations)
{
// Populate column mapping
foreach (var _ in Diff(source.Columns, target.Columns, diffContext))
diff --git a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs
index 2bc8f88fe1c..2b9713407ab 100644
--- a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs
+++ b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs
@@ -53,6 +53,12 @@ public static string BadSequenceType
public static string CannotChangeWhenOpen
=> GetString("CannotChangeWhenOpen");
+ ///
+ /// Comparing complex types to null is not supported.
+ ///
+ public static string CannotCompareComplexTypeToNull
+ => GetString("CannotCompareComplexTypeToNull");
+
///
/// Can't configure a trigger on entity type '{entityType}', which is in a TPH hierarchy and isn't the root. Configure the trigger on the TPH root entity type '{rootEntityType}' instead.
///
diff --git a/src/EFCore.Relational/Properties/RelationalStrings.resx b/src/EFCore.Relational/Properties/RelationalStrings.resx
index 9f1db59cbb4..f426a92d9d0 100644
--- a/src/EFCore.Relational/Properties/RelationalStrings.resx
+++ b/src/EFCore.Relational/Properties/RelationalStrings.resx
@@ -130,6 +130,9 @@
The instance of DbConnection is currently in use. The connection can only be changed when the existing connection is not being used.
+
+ Comparing complex types to null is not supported.
+
Can't configure a trigger on entity type '{entityType}', which is in a TPH hierarchy and isn't the root. Configure the trigger on the TPH root entity type '{rootEntityType}' instead.
diff --git a/src/EFCore.Relational/Query/Internal/QueryableJsonProjectionInfo.cs b/src/EFCore.Relational/Query/Internal/QueryableJsonProjectionInfo.cs
new file mode 100644
index 00000000000..12b168b43c3
--- /dev/null
+++ b/src/EFCore.Relational/Query/Internal/QueryableJsonProjectionInfo.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.
+
+namespace Microsoft.EntityFrameworkCore.Query.Internal;
+
+///
+/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+/// the same compatibility standards as public APIs. It may be changed or removed without notice in
+/// any release. You should only use it directly in your code with extreme caution and knowing that
+/// doing so can result in application failures when updating to a new Entity Framework Core release.
+///
+public readonly struct QueryableJsonProjectionInfo
+{
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public QueryableJsonProjectionInfo(
+ Dictionary propertyIndexMap,
+ List<(JsonProjectionInfo, INavigation)> childrenProjectionInfo)
+ {
+ PropertyIndexMap = propertyIndexMap;
+ ChildrenProjectionInfo = childrenProjectionInfo;
+ }
+
+ ///
+ /// Map between entity properties and corresponding column indexes.
+ ///
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public IDictionary PropertyIndexMap { get; }
+
+ ///
+ /// Information needed to construct each child JSON entity.
+ /// - JsonProjection info (same one we use for simple JSON projection),
+ /// - navigation between parent and the child JSON entity.
+ ///
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public IList<(JsonProjectionInfo JsonProjectionInfo, INavigation Navigation)> ChildrenProjectionInfo { get; }
+}
diff --git a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs
index e5e261e048c..e12b70645f4 100644
--- a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs
+++ b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs
@@ -182,15 +182,17 @@ public virtual Expression Translate(SelectExpression selectExpression, Expressio
if (expression is MethodCallExpression methodCallExpression)
{
- if (methodCallExpression.Method.IsGenericMethod
- && methodCallExpression.Method.DeclaringType == typeof(Enumerable)
- && methodCallExpression.Method.Name == nameof(Enumerable.ToList)
- && methodCallExpression.Arguments.Count == 1
- && methodCallExpression.Arguments[0].Type.TryGetElementType(typeof(IQueryable<>)) != null)
+ if (methodCallExpression is
+ {
+ Method.IsGenericMethod: true,
+ Method.Name: nameof(Enumerable.ToList),
+ Method: var method,
+ Arguments: [var argument]
+ }
+ && method.DeclaringType == typeof(Enumerable)
+ && argument.Type.TryGetElementType(typeof(IQueryable<>)) != null)
{
- var subquery = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(
- methodCallExpression.Arguments[0]);
- if (subquery != null)
+ if (_queryableMethodTranslatingExpressionVisitor.TranslateSubquery(argument) is ShapedQueryExpression subquery)
{
_clientProjections!.Add(subquery);
// expression.Type here will be List
diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
index c2717e60443..837b777070b 100644
--- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
@@ -266,14 +266,9 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
{
// Attempt to translate access into a primitive collection property (i.e. array column)
- // TODO: We should be detecting primitive collections by looking at GetElementType() of the property and not at its type
- // mapping; but #31469 is blocking that for shadow properties.
if (_sqlTranslator.TryTranslatePropertyAccess(methodCallExpression, out var translatedExpression, out var property)
- && property is IProperty regularProperty
- && translatedExpression is SqlExpression
- {
- TypeMapping.ElementTypeMapping: RelationalTypeMapping
- } sqlExpression)
+ && property is IProperty { IsPrimitiveCollection: true } regularProperty
+ && translatedExpression is SqlExpression sqlExpression)
{
var tableAlias = sqlExpression switch
{
@@ -2309,10 +2304,8 @@ static TableExpressionBase FindRootTableExpressionForColumn(ColumnExpression col
}
}
- // TODO: Check that the property is a primitive collection property directly once we have that in metadata, rather than
- // looking at the type mapping.
var property = type.FindProperty(memberName);
- if (property?.GetRelationalTypeMapping().ElementTypeMapping is null)
+ if (property?.IsPrimitiveCollection != true)
{
return null;
}
diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs
index 8d250d96c18..c5b89fc588f 100644
--- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs
+++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs
@@ -433,7 +433,11 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression)
if (newExpression.Arguments[0] is ProjectionBindingExpression projectionBindingExpression)
{
- var propertyMap = (IDictionary)GetProjectionIndex(projectionBindingExpression);
+ var projectionIndex = GetProjectionIndex(projectionBindingExpression);
+ var propertyMap = projectionIndex is IDictionary
+ ? (IDictionary)projectionIndex
+ : ((QueryableJsonProjectionInfo)projectionIndex).PropertyIndexMap;
+
_materializationContextBindings[parameterExpression] = propertyMap;
_entityTypeIdentifyingExpressionInfo[parameterExpression] =
// If single entity type is being selected in hierarchy then we use the value directly else we store the offset
@@ -535,6 +539,50 @@ protected override Expression VisitExtension(Expression extensionExpression)
visitedShaperResultParameter,
shaper.Type);
}
+ else if (GetProjectionIndex(projectionBindingExpression) is QueryableJsonProjectionInfo queryableJsonEntityProjectionInfo)
+ {
+ if (_isTracking)
+ {
+ throw new InvalidOperationException(
+ RelationalStrings.JsonEntityOrCollectionProjectedAtRootLevelInTrackingQuery(nameof(EntityFrameworkQueryableExtensions.AsNoTracking)));
+ }
+
+ // json entity converted to query root and projected
+ var entityParameter = Parameter(shaper.Type);
+ _variables.Add(entityParameter);
+ var entityMaterializationExpression = (BlockExpression)_parentVisitor.InjectEntityMaterializers(shaper);
+
+ var mappedProperties = queryableJsonEntityProjectionInfo.PropertyIndexMap.Keys.ToList();
+ var rewrittenEntityMaterializationExpression = new QueryableJsonEntityMaterializerRewriter(mappedProperties)
+ .Rewrite(entityMaterializationExpression);
+
+ var visitedEntityMaterializationExpression = Visit(rewrittenEntityMaterializationExpression);
+ _expressions.Add(Assign(entityParameter, visitedEntityMaterializationExpression));
+
+ foreach (var childProjectionInfo in queryableJsonEntityProjectionInfo.ChildrenProjectionInfo)
+ {
+ var (jsonReaderDataVariable, keyValuesParameter) = JsonShapingPreProcess(
+ childProjectionInfo.JsonProjectionInfo,
+ childProjectionInfo.Navigation.TargetEntityType,
+ childProjectionInfo.Navigation.IsCollection);
+
+ var shaperResult = CreateJsonShapers(
+ childProjectionInfo.Navigation.TargetEntityType,
+ nullable: true,
+ jsonReaderDataVariable,
+ keyValuesParameter,
+ parentEntityExpression: entityParameter,
+ navigation: childProjectionInfo.Navigation);
+
+ var visitedShaperResult = Visit(shaperResult);
+
+ _includeExpressions.Add(visitedShaperResult);
+ }
+
+ accessor = CompensateForCollectionMaterialization(
+ entityParameter,
+ shaper.Type);
+ }
else
{
var entityParameter = Parameter(shaper.Type);
@@ -1473,6 +1521,39 @@ protected override Expression VisitSwitch(SwitchExpression switchExpression)
//sometimes we have shadow value buffer and sometimes not, but type initializer always comes last
switch (body.Expressions[^1])
{
+ case UnaryExpression { Operand: BlockExpression innerBlock } jsonEntityTypeInitializerUnary
+ when jsonEntityTypeInitializerUnary.NodeType is ExpressionType.Convert or ExpressionType.ConvertChecked:
+ {
+ // in case of proxies, the entity initializer block is wrapped around Convert node
+ // that converts from the proxy type to the actual entity type.
+ // We normalize that into a block by pushing the convert inside the inner block. Rather than:
+ //
+ // return (MyEntity)
+ // {
+ // ProxyEntity instance;
+ // (...)
+ // return instance;
+ // }
+ //
+ // we produce:
+ // return
+ // {
+ // ProxyEntity instance;
+ // MyEntity actualInstance;
+ // (...)
+ // actualInstance = (MyEntity)instance;
+ // return actualInstance;
+ // }
+ var newVariables = innerBlock.Variables.ToList();
+ var proxyConversionVariable = Variable(jsonEntityTypeInitializerUnary.Type);
+ newVariables.Add(proxyConversionVariable);
+ var newExpressions = innerBlock.Expressions.ToList()[..^1];
+ newExpressions.Add(Assign(proxyConversionVariable, jsonEntityTypeInitializerUnary.Update(innerBlock.Expressions[^1])));
+ newExpressions.Add(proxyConversionVariable);
+ jsonEntityTypeInitializerBlock = Block(newVariables, newExpressions);
+ break;
+ }
+
case BlockExpression b:
jsonEntityTypeInitializerBlock = b;
break;
@@ -1922,15 +2003,14 @@ protected override Expression VisitBinary(BinaryExpression node)
if (node.Right is MethodCallExpression methodCallExpression
&& IsPropertyAssignment(methodCallExpression, out var property, out var parameter))
{
- if (property!.GetTypeMapping().ElementTypeMapping != null
+ if (property!.IsPrimitiveCollection
&& !property.ClrType.IsArray)
{
var currentVariable = Variable(parameter!.Type);
return Block(
new[] { currentVariable },
- Assign(
- currentVariable,
- MakeMemberAccess(_instance, property.GetMemberInfo(forMaterialization: true, forSet: false))),
+ MakeMemberAccess(_instance, property.GetMemberInfo(forMaterialization: true, forSet: false))
+ .Assign(currentVariable),
IfThenElse(
OrElse(
ReferenceEqual(currentVariable, Constant(null)),
@@ -1943,7 +2023,11 @@ protected override Expression VisitBinary(BinaryExpression node)
));
}
- return MakeBinary(node.NodeType, Visit(node.Left), parameter!);
+ var visitedLeft = Visit(node.Left);
+ return node.NodeType == ExpressionType.Assign
+ && visitedLeft is MemberExpression memberExpression
+ ? memberExpression.Assign(parameter!)
+ : MakeBinary(node.NodeType, visitedLeft, parameter!);
}
return base.VisitBinary(node);
@@ -2141,6 +2225,62 @@ ParameterExpression ExtractAndCacheNonConstantJsonArrayElementAccessValue(int in
}
}
+ private sealed class QueryableJsonEntityMaterializerRewriter : ExpressionVisitor
+ {
+ private readonly List _mappedProperties;
+
+ public QueryableJsonEntityMaterializerRewriter(List mappedProperties)
+ {
+ _mappedProperties = mappedProperties;
+ }
+
+ public BlockExpression Rewrite(BlockExpression jsonEntityShaperMaterializer)
+ => (BlockExpression)VisitBlock(jsonEntityShaperMaterializer);
+
+ protected override Expression VisitBinary(BinaryExpression binaryExpression)
+ {
+ // here we try to pattern match part of the shaper code that checks if key values are null
+ // if they are all non-null then we generate the entity
+ // problem for JSON entities is that some of the keys are synthesized and should be omitted
+ // if the key is one of the mapped ones, we leave the expression as is, otherwise replace with Constant(true)
+ // i.e. removing it
+ if (binaryExpression is
+ {
+ NodeType: ExpressionType.NotEqual,
+ Left: MethodCallExpression
+ {
+ Method: { IsGenericMethod: true } method,
+ Arguments: [_, _, ConstantExpression { Value: IProperty property }]
+ },
+ Right: ConstantExpression { Value: null }
+ }
+ && method.GetGenericMethodDefinition() == Infrastructure.ExpressionExtensions.ValueBufferTryReadValueMethod)
+ {
+ return _mappedProperties.Contains(property)
+ ? binaryExpression
+ : Constant(true);
+ }
+
+ return base.VisitBinary(binaryExpression);
+ }
+
+ protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
+ {
+ if (methodCallExpression is
+ {
+ Method: { IsGenericMethod: true } method,
+ Arguments: [_, _, ConstantExpression { Value: IProperty property }]
+ }
+ && method.GetGenericMethodDefinition() == Infrastructure.ExpressionExtensions.ValueBufferTryReadValueMethod
+ && !_mappedProperties.Contains(property))
+ {
+ return Default(methodCallExpression.Type);
+ }
+
+ return base.VisitMethodCall(methodCallExpression);
+ }
+ }
+
private static LambdaExpression GenerateFixup(
Type entityType,
Type relatedEntityType,
diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs
index 46309019c68..d9e35874574 100644
--- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs
@@ -1684,7 +1684,7 @@ private bool TryRewriteContainsEntity(Expression source, Expression item, [NotNu
var propertyGetter = property.GetGetter();
foreach (var value in values)
{
- propertyValueList.Add(propertyGetter.GetStructuralTypeClrValue(value));
+ propertyValueList.Add(propertyGetter.GetClrValue(value));
}
rewrittenSource = Expression.Constant(propertyValueList);
@@ -1791,19 +1791,23 @@ bool TryRewriteEntityEquality([NotNullWhen(true)] out Expression? result)
if (allNonPrincipalSharedNonPkProperties.Count != 0
&& allNonPrincipalSharedNonPkProperties.All(p => p.IsNullable))
{
- var atLeastOneNonNullValueInNullablePropertyCondition = allNonPrincipalSharedNonPkProperties
+ // if we don't have any required properties to properly check the nullability,
+ // we rely on optional ones (somewhat unreliably)
+ // - if entity is to be null, all the properties must be null
+ // - if the entity is to be not null, at least one property must be not null
+ var optionalPropertiesCondition = allNonPrincipalSharedNonPkProperties
.Select(
p => Infrastructure.ExpressionExtensions.CreateEqualsExpression(
CreatePropertyAccessExpression(nonNullEntityReference, p),
Expression.Constant(null, p.ClrType.MakeNullable()),
nodeType != ExpressionType.Equal))
- .Aggregate((l, r) => nodeType == ExpressionType.Equal ? Expression.OrElse(l, r) : Expression.AndAlso(l, r));
+ .Aggregate((l, r) => nodeType == ExpressionType.Equal ? Expression.AndAlso(l, r) : Expression.OrElse(l, r));
condition = condition == null
- ? atLeastOneNonNullValueInNullablePropertyCondition
+ ? optionalPropertiesCondition
: nodeType == ExpressionType.Equal
- ? Expression.OrElse(condition, atLeastOneNonNullValueInNullablePropertyCondition)
- : Expression.AndAlso(condition, atLeastOneNonNullValueInNullablePropertyCondition);
+ ? Expression.OrElse(condition, optionalPropertiesCondition)
+ : Expression.AndAlso(condition, optionalPropertiesCondition);
}
if (condition != null)
@@ -1890,7 +1894,7 @@ bool TryRewriteComplexTypeEquality([NotNullWhen(true)] out Expression? result)
{
// TODO: when we support optional complex types - or projecting required complex types via optional navigations - we'll
// be able to translate this.
- throw new InvalidOperationException(); // TODO: Message
+ throw new InvalidOperationException(RelationalStrings.CannotCompareComplexTypeToNull);
}
var leftComplexType = leftReference?.StructuralType as IComplexType;
@@ -1974,14 +1978,14 @@ private Expression CreatePropertyAccessExpression(Expression target, IProperty p
return Expression.Constant(
sqlConstantExpression.Value is null
? null
- : property.GetGetter().GetStructuralTypeClrValue(sqlConstantExpression.Value),
+ : property.GetGetter().GetClrValue(sqlConstantExpression.Value),
property.ClrType.MakeNullable());
case ConstantExpression sqlConstantExpression:
return Expression.Constant(
sqlConstantExpression.Value is null
? null
- : property.GetGetter().GetStructuralTypeClrValue(sqlConstantExpression.Value),
+ : property.GetGetter().GetClrValue(sqlConstantExpression.Value),
property.ClrType.MakeNullable());
case SqlParameterExpression sqlParameterExpression
@@ -2035,7 +2039,7 @@ private Expression CreateComplexPropertyAccessExpression(Expression target, ICom
=> target switch
{
SqlConstantExpression constant => Expression.Constant(
- constant.Value is null ? null : complexProperty.GetGetter().GetStructuralTypeClrValue(constant.Value),
+ constant.Value is null ? null : complexProperty.GetGetter().GetClrValue(constant.Value),
complexProperty.ClrType.MakeNullable()),
SqlParameterExpression sqlParameterExpression
@@ -2070,11 +2074,11 @@ when memberInitExpression.Bindings.SingleOrDefault(mb => mb.Member.Name == compl
break;
}
- baseValue = complexProperty.GetGetter().GetStructuralTypeClrValue(baseValue);
+ baseValue = complexProperty.GetGetter().GetClrValue(baseValue);
}
}
- return baseValue == null ? (T?)(object?)null : (T?)property.GetGetter().GetStructuralTypeClrValue(baseValue);
+ return baseValue == null ? (T?)(object?)null : (T?)property.GetGetter().GetClrValue(baseValue);
}
private static List? ParameterListValueExtractor(
@@ -2088,7 +2092,7 @@ when memberInitExpression.Bindings.SingleOrDefault(mb => mb.Member.Name == compl
}
var getter = property.GetGetter();
- return baseListParameter.Select(e => e != null ? (TProperty?)getter.GetStructuralTypeClrValue(e) : (TProperty?)(object?)null).ToList();
+ return baseListParameter.Select(e => e != null ? (TProperty?)getter.GetClrValue(e) : (TProperty?)(object?)null).ToList();
}
private sealed class ParameterBasedComplexPropertyChainExpression : Expression
diff --git a/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs
index 9f58ec09b4b..c1ba6d964eb 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs
@@ -38,7 +38,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
///
/// The property of the result.
/// This expression if no children changed, or an expression with the updated children.
- public virtual CrossApplyExpression Update(TableExpressionBase table)
+ public override CrossApplyExpression Update(TableExpressionBase table)
=> table != Table
? new CrossApplyExpression(table, GetAnnotations())
: this;
diff --git a/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs
index c5e6c4eef09..89f87da89dc 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/CrossJoinExpression.cs
@@ -38,7 +38,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
///
/// The property of the result.
/// This expression if no children changed, or an expression with the updated children.
- public virtual CrossJoinExpression Update(TableExpressionBase table)
+ public override CrossJoinExpression Update(TableExpressionBase table)
=> table != Table
? new CrossJoinExpression(table, GetAnnotations())
: this;
diff --git a/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs
index dc4fc43fa47..f3287684c79 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs
@@ -48,11 +48,22 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
/// The property of the result.
/// The property of the result.
/// This expression if no children changed, or an expression with the updated children.
- public virtual InnerJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate)
+ public override InnerJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate)
=> table != Table || joinPredicate != JoinPredicate
? new InnerJoinExpression(table, joinPredicate, GetAnnotations())
: this;
+ ///
+ /// Creates a new expression that is like this one, but using the supplied children. If all of the children are the same, it will
+ /// return this expression.
+ ///
+ /// The property of the result.
+ /// This expression if no children changed, or an expression with the updated children.
+ public override InnerJoinExpression Update(TableExpressionBase table)
+ => table != Table
+ ? new InnerJoinExpression(table, JoinPredicate, GetAnnotations())
+ : this;
+
///
protected override TableExpressionBase CreateWithAnnotations(IEnumerable annotations)
=> new InnerJoinExpression(Table, JoinPredicate, annotations);
diff --git a/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs
index 7e5653e041f..15fae8a45db 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs
@@ -39,6 +39,14 @@ protected JoinExpressionBase(TableExpressionBase table, IEnumerable
///
public virtual TableExpressionBase Table { get; }
+ ///
+ /// Creates a new expression that is like this one, but using the supplied children. If all of the children are the same, it will
+ /// return this expression.
+ ///
+ /// The property of the result.
+ /// This expression if no children changed, or an expression with the updated children.
+ public abstract JoinExpressionBase Update(TableExpressionBase table);
+
///
public override bool Equals(object? obj)
=> obj != null
diff --git a/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs
index ca8e42132ec..b0eceb1e0a2 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs
@@ -48,11 +48,22 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
/// The property of the result.
/// The property of the result.
/// This expression if no children changed, or an expression with the updated children.
- public virtual LeftJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate)
+ public override LeftJoinExpression Update(TableExpressionBase table, SqlExpression joinPredicate)
=> table != Table || joinPredicate != JoinPredicate
? new LeftJoinExpression(table, joinPredicate, GetAnnotations())
: this;
+ ///
+ /// Creates a new expression that is like this one, but using the supplied children. If all of the children are the same, it will
+ /// return this expression.
+ ///
+ /// The property of the result.
+ /// This expression if no children changed, or an expression with the updated children.
+ public override LeftJoinExpression Update(TableExpressionBase table)
+ => table != Table
+ ? new LeftJoinExpression(table, JoinPredicate, GetAnnotations())
+ : this;
+
///
protected override TableExpressionBase CreateWithAnnotations(IEnumerable annotations)
=> new LeftJoinExpression(Table, JoinPredicate, annotations);
diff --git a/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs
index 2cc30f8dda0..7f20fd74494 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs
@@ -38,7 +38,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
///
/// The property of the result.
/// This expression if no children changed, or an expression with the updated children.
- public virtual OuterApplyExpression Update(TableExpressionBase table)
+ public override OuterApplyExpression Update(TableExpressionBase table)
=> table != Table
? new OuterApplyExpression(table, GetAnnotations())
: this;
diff --git a/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs
index 8c40d3043a0..a1df3330052 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs
@@ -44,6 +44,15 @@ protected PredicateJoinExpressionBase(
///
public virtual SqlExpression JoinPredicate { get; }
+ ///
+ /// Creates a new expression that is like this one, but using the supplied children. If all of the children are the same, it will
+ /// return this expression.
+ ///
+ /// The property of the result.
+ /// The property of the result.
+ /// This expression if no children changed, or an expression with the updated children.
+ public abstract PredicateJoinExpressionBase Update(TableExpressionBase table, SqlExpression joinPredicate);
+
///
public override bool Equals(object? obj)
=> obj != null
diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
index 856a485ec2a..0ad1dfc7ec8 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
@@ -807,6 +807,7 @@ when entityType.IsMappedToJson():
// For JSON entities, the identifier is the key that was generated when we convert from json to query root
// (OPENJSON, json_each, etc), but we can't use it for distinct, as it would warp the results.
// Instead, we will treat every non-key property as identifier.
+
foreach (var property in entityType.GetDeclaredProperties().Where(p => !p.IsPrimaryKey()))
{
typeProjectionIdentifiers.Add(entityProjection.BindProperty(property));
@@ -823,6 +824,7 @@ when entityType.IsMappedToJson():
// We know that there are existing identifiers (see condition above); we know we must have a key since a keyless
// entity type would have wiped the identifiers when generating the join.
Check.DebugAssert(primaryKey != null, "primary key is null.");
+
foreach (var property in primaryKey.Properties)
{
typeProjectionIdentifiers.Add(entityProjection.BindProperty(property));
@@ -1297,15 +1299,7 @@ static void UpdateLimit(SelectExpression selectExpression)
case JsonQueryExpression jsonQueryExpression:
{
- var jsonProjectionResult = AddJsonProjection(
- jsonQueryExpression,
- jsonScalarToAdd: new JsonScalarExpression(
- jsonQueryExpression.JsonColumn,
- jsonQueryExpression.Path,
- jsonQueryExpression.JsonColumn.Type,
- jsonQueryExpression.JsonColumn.TypeMapping!,
- jsonQueryExpression.IsNullable));
-
+ var jsonProjectionResult = AddJsonProjection(jsonQueryExpression);
newClientProjections.Add(jsonProjectionResult);
clientProjectionIndexMap.Add(newClientProjections.Count - 1);
@@ -1765,6 +1759,33 @@ Expression CopyProjectionToOuter(SelectExpression innerSelectExpression, Express
projectionIndexMap[jsonProjectionInfo.JsonColumnIndex],
newKeyAccessInfo));
}
+ else if (constantValue is QueryableJsonProjectionInfo queryableJsonProjectionInfo)
+ {
+ var newPropertyIndexMap = new Dictionary(queryableJsonProjectionInfo.PropertyIndexMap.Count);
+ foreach (var (property, value) in queryableJsonProjectionInfo.PropertyIndexMap)
+ {
+ newPropertyIndexMap[property] = projectionIndexMap[value];
+ }
+
+ var newChildrenProjectionInfo = new List<(JsonProjectionInfo, INavigation)>();
+ foreach (var childProjectionInfo in queryableJsonProjectionInfo.ChildrenProjectionInfo)
+ {
+ var newKeyAccessInfo = new List<(IProperty?, int?, int?)>();
+ foreach (var (keyProperty, constantKeyValue, keyProjectionIndex) in childProjectionInfo.JsonProjectionInfo.KeyAccessInfo)
+ {
+ newKeyAccessInfo.Add((keyProperty, constantKeyValue, keyProjectionIndex != null ? projectionIndexMap[keyProjectionIndex.Value] : null));
+ }
+
+ newChildrenProjectionInfo.Add(
+ (new JsonProjectionInfo(
+ projectionIndexMap[childProjectionInfo.JsonProjectionInfo.JsonColumnIndex],
+ newKeyAccessInfo),
+ childProjectionInfo.Navigation));
+ }
+
+ remappedConstant = Constant(
+ new QueryableJsonProjectionInfo(newPropertyIndexMap, newChildrenProjectionInfo));
+ }
else
{
remappedConstant = Constant(projectionIndexMap[(int)constantValue]);
@@ -1792,14 +1813,7 @@ Expression CopyProjectionToOuter(SelectExpression innerSelectExpression, Express
result[projectionMember] = expression switch
{
StructuralTypeProjectionExpression projection => AddStructuralTypeProjection(projection),
- JsonQueryExpression jsonQueryExpression => AddJsonProjection(
- jsonQueryExpression,
- new JsonScalarExpression(
- jsonQueryExpression.JsonColumn,
- jsonQueryExpression.Path,
- jsonQueryExpression.JsonColumn.Type,
- jsonQueryExpression.JsonColumn.TypeMapping!,
- jsonQueryExpression.IsNullable)),
+ JsonQueryExpression jsonQueryExpression => AddJsonProjection(jsonQueryExpression),
_ => Constant(AddToProjection((SqlExpression)expression, projectionMember.Last?.Name))
};
}
@@ -1817,41 +1831,90 @@ ConstantExpression AddStructuralTypeProjection(StructuralTypeProjectionExpressio
throw new InvalidOperationException(RelationalStrings.CannotProjectNullableComplexType(complexType.DisplayName()));
}
- var projections = new Dictionary();
+ // JSON entity that had some query operations applied on it - it has been converted to a query root via OPENJSON/json_each
+ // so it requires different materialization path than regular entity
+ // e.g. we need to also add all the child navigations, JSON entity builds all the includes as part of it's own materializer
+ // rather than relying on IncludeExpressions in the shaper query
+ // also, we don't want to add projection map for synthesized keys, whereas regular entity needs to project every single property it has
+ if (projection is { StructuralType: IEntityType entityType }
+ && entityType.IsMappedToJson())
+ {
+ var propertyIndexMap = new Dictionary();
+ var ownerEntity = entityType;
- ProcessType(projection);
+ do
+ {
+ var ownership = ownerEntity.FindOwnership();
+ if (ownership != null)
+ {
+ ownerEntity = ownership.PrincipalEntityType;
+ }
+ }
+ while (ownerEntity.IsMappedToJson());
+
+ var keyPropertyCount = ownerEntity.FindPrimaryKey()!.Properties.Count;
+ foreach (var property in entityType.FindPrimaryKey()!.Properties.Take(keyPropertyCount)
+ .Concat(entityType.GetDeclaredProperties().Where(p => p.GetJsonPropertyName() is not null)))
+ {
+ propertyIndexMap[property] = AddToProjection(projection.BindProperty(property), null);
+ }
+
+ var childrenProjectionInfo = new List<(JsonProjectionInfo, INavigation)>();
+ foreach (var ownedNavigation in entityType.GetNavigations().Where(
+ n => n.TargetEntityType.IsMappedToJson() && n.ForeignKey.IsOwnership && n == n.ForeignKey.PrincipalToDependent))
+ {
+ var jsonQueryExpression = (JsonQueryExpression)projection.BindNavigation(ownedNavigation)!.ValueBufferExpression;
+ var jsonProjectionInfo = (JsonProjectionInfo)AddJsonProjection(jsonQueryExpression).Value!;
+ childrenProjectionInfo.Add((jsonProjectionInfo, ownedNavigation));
+ }
- void ProcessType(StructuralTypeProjectionExpression typeProjection)
+ return Constant(new QueryableJsonProjectionInfo(propertyIndexMap, childrenProjectionInfo));
+ }
+ else
{
- foreach (var property in GetAllPropertiesInHierarchy(typeProjection.StructuralType))
+ var projections = new Dictionary();
+
+ ProcessType(projection);
+
+ void ProcessType(StructuralTypeProjectionExpression typeProjection)
{
- if (typeProjection is { StructuralType: IEntityType entityType }
- && entityType.IsMappedToJson()
- && property.IsOrdinalKeyProperty())
+ foreach (var property in GetAllPropertiesInHierarchy(typeProjection.StructuralType))
{
- continue;
+ if (typeProjection is { StructuralType: IEntityType entityType }
+ && entityType.IsMappedToJson()
+ && property.IsOrdinalKeyProperty())
+ {
+ continue;
+ }
+
+ projections[property] = AddToProjection(typeProjection.BindProperty(property), alias: null);
}
- projections[property] = AddToProjection(typeProjection.BindProperty(property), alias: null);
+ foreach (var complexProperty in GetAllComplexPropertiesInHierarchy(typeProjection.StructuralType))
+ {
+ ProcessType((StructuralTypeProjectionExpression)typeProjection.BindComplexProperty(complexProperty).ValueBufferExpression);
+ }
}
- foreach (var complexProperty in GetAllComplexPropertiesInHierarchy(typeProjection.StructuralType))
+ if (projection.DiscriminatorExpression is not null)
{
- ProcessType((StructuralTypeProjectionExpression)typeProjection.BindComplexProperty(complexProperty).ValueBufferExpression);
+ AddToProjection(projection.DiscriminatorExpression, DiscriminatorColumnAlias);
}
- }
- if (projection.DiscriminatorExpression is not null)
- {
- AddToProjection(projection.DiscriminatorExpression, DiscriminatorColumnAlias);
+ return Constant(projections);
}
-
- return Constant(projections);
}
- ConstantExpression AddJsonProjection(JsonQueryExpression jsonQueryExpression, JsonScalarExpression jsonScalarToAdd)
+ ConstantExpression AddJsonProjection(JsonQueryExpression jsonQueryExpression)
{
- var sqlExpression = AssignUniqueAliases(jsonScalarToAdd);
+ var jsonScalarExpression = new JsonScalarExpression(
+ jsonQueryExpression.JsonColumn,
+ jsonQueryExpression.Path,
+ jsonQueryExpression.JsonColumn.Type,
+ jsonQueryExpression.JsonColumn.TypeMapping!,
+ jsonQueryExpression.IsNullable);
+
+ var sqlExpression = AssignUniqueAliases(jsonScalarExpression);
_projection.Add(new ProjectionExpression(sqlExpression, ""));
var jsonColumnIndex = _projection.Count - 1;
var keyAccessInfo = new List<(IProperty?, int?, int?)>();
@@ -1862,7 +1925,7 @@ ConstantExpression AddJsonProjection(JsonQueryExpression jsonQueryExpression, Js
keyAccessInfo.Add((keyProperty, null, AddToProjection(keyColumn)));
}
- foreach (var elementAccessSegment in jsonScalarToAdd.Path.Where(x => x.ArrayIndex != null))
+ foreach (var elementAccessSegment in jsonScalarExpression.Path.Where(x => x.ArrayIndex != null))
{
if (elementAccessSegment.ArrayIndex is SqlConstantExpression { Value: int intValue })
{
diff --git a/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs b/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs
index 129eff60447..732f143af92 100644
--- a/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs
+++ b/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs
@@ -307,7 +307,7 @@ public virtual void AddNavigationBinding(INavigation navigation, StructuralTypeS
{
if (StructuralType is not IEntityType entityType)
{
- throw new InvalidOperationException(); // TODO: Message
+ throw new UnreachableException("Navigations are only supported on entity types");
}
if (!entityType.IsAssignableFrom(navigation.DeclaringEntityType)
@@ -330,7 +330,7 @@ public virtual void AddNavigationBinding(INavigation navigation, StructuralTypeS
{
if (StructuralType is not IEntityType entityType)
{
- throw new InvalidOperationException(); // TODO: Message
+ throw new UnreachableException("Navigations are only supported on entity types");
}
if (!entityType.IsAssignableFrom(navigation.DeclaringEntityType)
diff --git a/src/EFCore.Relational/Storage/Internal/NullTypeMapping.cs b/src/EFCore.Relational/Storage/Internal/NullTypeMapping.cs
index 366d62c80ed..19e4aa9aeb3 100644
--- a/src/EFCore.Relational/Storage/Internal/NullTypeMapping.cs
+++ b/src/EFCore.Relational/Storage/Internal/NullTypeMapping.cs
@@ -3,7 +3,7 @@
using Microsoft.EntityFrameworkCore.Storage.Json;
-namespace Microsoft.EntityFrameworkCore.Storage;
+namespace Microsoft.EntityFrameworkCore.Storage.Internal;
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
diff --git a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs
index 1f12134f7b3..e6588e4e1d9 100644
--- a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs
+++ b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs
@@ -4,6 +4,7 @@
using System.Collections.Concurrent;
using System.Data;
using System.Globalization;
+using Microsoft.EntityFrameworkCore.Storage.Internal;
using Microsoft.EntityFrameworkCore.Storage.Json;
namespace Microsoft.EntityFrameworkCore.Storage;
@@ -231,16 +232,18 @@ public RelationalTypeMappingParameters WithScale(int? scale)
///
/// The converter.
/// The comparer.
+ /// The key comparer.
/// The element mapping, or for non-collection mappings.
/// The JSON reader/writer, or to leave unchanged.
/// The new parameter object.
public RelationalTypeMappingParameters WithComposedConverter(
ValueConverter? converter,
ValueComparer? comparer,
+ ValueComparer? keyComparer,
CoreTypeMapping? elementMapping,
JsonValueReaderWriter? jsonValueReaderWriter)
=> new(
- CoreParameters.WithComposedConverter(converter, comparer, elementMapping, jsonValueReaderWriter),
+ CoreParameters.WithComposedConverter(converter, comparer, keyComparer, elementMapping, jsonValueReaderWriter),
StoreType,
StoreTypePostfix,
DbType,
@@ -276,7 +279,7 @@ private static MethodInfo GetDataReaderMethod(string name)
///
/// Gets the mapping to be used when the only piece of information is that there is a null value.
///
- public static readonly NullTypeMapping NullMapping = NullTypeMapping.Default;
+ public static readonly RelationalTypeMapping NullMapping = NullTypeMapping.Default;
///
/// Initializes a new instance of the class.
@@ -415,7 +418,7 @@ protected override CoreTypeMapping Clone(CoreTypeMappingParameters parameters)
/// The name of the database type.
/// The size of data the property is configured to store, or null if no size is configured.
/// The newly created mapping.
- public virtual RelationalTypeMapping Clone(string storeType, int? size)
+ public virtual RelationalTypeMapping WithStoreTypeAndSize(string storeType, int? size)
=> Clone(Parameters.WithStoreTypeAndSize(storeType, size));
///
@@ -424,52 +427,27 @@ public virtual RelationalTypeMapping Clone(string storeType, int? size)
/// The precision of data the property is configured to store, or null if no size is configured.
/// The scale of data the property is configured to store, or null if no size is configured.
/// The newly created mapping.
- public virtual RelationalTypeMapping Clone(int? precision, int? scale)
+ public virtual RelationalTypeMapping WithPrecisionAndScale(int? precision, int? scale)
=> Clone(Parameters.WithPrecisionAndScale(precision, scale));
///
- public override CoreTypeMapping Clone(
+ public override CoreTypeMapping WithComposedConverter(
ValueConverter? converter,
ValueComparer? comparer = null,
+ ValueComparer? keyComparer = null,
CoreTypeMapping? elementMapping = null,
JsonValueReaderWriter? jsonValueReaderWriter = null)
- => Clone(Parameters.WithComposedConverter(converter, comparer, elementMapping, jsonValueReaderWriter));
+ => Clone(Parameters.WithComposedConverter(converter, comparer, keyComparer, elementMapping, jsonValueReaderWriter));
///
/// Clones the type mapping to update facets from the mapping info, if needed.
///
/// The mapping info containing the facets to use.
/// The cloned mapping, or the original mapping if no clone was needed.
- public virtual RelationalTypeMapping Clone(
+ public virtual RelationalTypeMapping WithTypeMappingInfo(
in RelationalTypeMappingInfo mappingInfo)
=> Clone(Parameters.WithTypeMappingInfo(mappingInfo));
- ///
- public override CoreTypeMapping Clone(
- in TypeMappingInfo? mappingInfo = null,
- Type? clrType = null,
- ValueConverter? converter = null,
- ValueComparer? comparer = null,
- ValueComparer? keyComparer = null,
- ValueComparer? providerValueComparer = null,
- CoreTypeMapping? elementMapping = null,
- JsonValueReaderWriter? jsonValueReaderWriter = null)
- => Clone(
- mappingInfo == null
- ? null
- : new RelationalTypeMappingInfo(
- unicode: mappingInfo.Value.IsUnicode,
- size: mappingInfo.Value.Size,
- precision: mappingInfo.Value.Precision,
- scale: mappingInfo.Value.Scale),
- clrType,
- converter,
- comparer,
- keyComparer,
- providerValueComparer,
- elementMapping,
- jsonValueReaderWriter);
-
///
/// Clones the type mapping to update any parameter if needed.
///
diff --git a/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs b/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs
index 3c21d0202ed..4804af11bd0 100644
--- a/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs
+++ b/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs
@@ -151,7 +151,7 @@ public RelationalTypeMappingInfo(
int? scale)
{
// Note: Empty string is allowed for store type name because SQLite
- _coreTypeMappingInfo = new TypeMappingInfo(null, false, unicode, size, null, precision, scale);
+ _coreTypeMappingInfo = new TypeMappingInfo(null, null, false, unicode, size, null, precision, scale);
StoreTypeName = storeTypeName;
StoreTypeNameBase = storeTypeNameBase;
IsFixedLength = null;
@@ -161,6 +161,7 @@ public RelationalTypeMappingInfo(
/// Creates a new instance of .
///
/// The property or field for which mapping is needed.
+ /// The type mapping for elements, if known.
/// The provider-specific relational type name for which mapping is needed.
/// The provider-specific relational type name, with any facets removed.
/// Specifies Unicode or ANSI mapping, or for default.
@@ -169,6 +170,7 @@ public RelationalTypeMappingInfo(
/// Specifies a scale for the mapping, or for default.
public RelationalTypeMappingInfo(
MemberInfo member,
+ RelationalTypeMapping? elementTypeMapping = null,
string? storeTypeName = null,
string? storeTypeNameBase = null,
bool? unicode = null,
@@ -176,7 +178,7 @@ public RelationalTypeMappingInfo(
int? precision = null,
int? scale = null)
{
- _coreTypeMappingInfo = new TypeMappingInfo(member, unicode, size, precision, scale);
+ _coreTypeMappingInfo = new TypeMappingInfo(member, elementTypeMapping, unicode, size, precision, scale);
StoreTypeName = storeTypeName;
StoreTypeNameBase = storeTypeNameBase;
@@ -212,6 +214,7 @@ public RelationalTypeMappingInfo(
/// Creates a new instance of .
///
/// The CLR type in the model for which mapping is needed.
+ /// The type mapping for elements, if known.
/// The database type name.
/// The provider-specific relational type name, with any facets removed.
/// If , then a special mapping for a key or index may be returned.
@@ -224,6 +227,7 @@ public RelationalTypeMappingInfo(
/// The suggested , or for default.
public RelationalTypeMappingInfo(
Type? type = null,
+ RelationalTypeMapping? elementTypeMapping = null,
string? storeTypeName = null,
string? storeTypeNameBase = null,
bool keyOrIndex = false,
@@ -235,7 +239,7 @@ public RelationalTypeMappingInfo(
int? scale = null,
DbType? dbType = null)
{
- _coreTypeMappingInfo = new TypeMappingInfo(type, keyOrIndex, unicode, size, rowVersion, precision, scale);
+ _coreTypeMappingInfo = new TypeMappingInfo(type, elementTypeMapping, keyOrIndex, unicode, size, rowVersion, precision, scale);
IsFixedLength = fixedLength;
StoreTypeName = storeTypeName;
@@ -341,6 +345,15 @@ public JsonValueReaderWriter? JsonValueReaderWriter
init => _coreTypeMappingInfo = _coreTypeMappingInfo with { JsonValueReaderWriter = value };
}
+ ///
+ /// The element type of the mapping, if any.
+ ///
+ public RelationalTypeMapping? ElementTypeMapping
+ {
+ get => (RelationalTypeMapping?)_coreTypeMappingInfo.ElementTypeMapping;
+ init => _coreTypeMappingInfo = _coreTypeMappingInfo with { ElementTypeMapping = value };
+ }
+
///
/// Returns a new with the given converter applied.
///
diff --git a/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs b/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs
index 06097c77f64..bb0d5bf2bac 100644
--- a/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs
+++ b/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs
@@ -4,6 +4,7 @@
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
+using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
namespace Microsoft.EntityFrameworkCore.Storage;
@@ -85,7 +86,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
RelationalStrings.NoneRelationalTypeMappingOnARelationalTypeMappingSource);
private RelationalTypeMapping? FindMappingWithConversion(
- in RelationalTypeMappingInfo mappingInfo,
+ RelationalTypeMappingInfo mappingInfo,
IReadOnlyList? principals)
{
Type? providerClrType = null;
@@ -114,15 +115,19 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
}
}
- var element = principal.GetElementType();
- if (element != null)
+ if (elementMapping == null)
{
- elementMapping = FindMapping(element);
+ var element = principal.GetElementType();
+ if (element != null)
+ {
+ elementMapping = FindMapping(element);
+ mappingInfo = mappingInfo with { ElementTypeMapping = (RelationalTypeMapping?)elementMapping };
+ }
}
}
}
- var resolvedMapping = FindMappingWithConversion(mappingInfo, providerClrType, customConverter, elementMapping);
+ var resolvedMapping = FindMappingWithConversion(mappingInfo, providerClrType, customConverter);
ValidateMapping(resolvedMapping, principals?[0]);
@@ -132,26 +137,23 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
private RelationalTypeMapping? FindMappingWithConversion(
RelationalTypeMappingInfo mappingInfo,
Type? providerClrType,
- ValueConverter? customConverter,
- CoreTypeMapping? elementMapping)
+ ValueConverter? customConverter)
=> _explicitMappings.GetOrAdd(
- (mappingInfo, providerClrType, customConverter, elementMapping),
+ (mappingInfo, providerClrType, customConverter, mappingInfo.ElementTypeMapping),
static (k, self) =>
{
var (mappingInfo, providerClrType, customConverter, elementMapping) = k;
var sourceType = mappingInfo.ClrType;
- RelationalTypeMapping? mapping = null;
+ var mapping = providerClrType == null
+ || providerClrType == mappingInfo.ClrType
+ ? self.FindMapping(mappingInfo)
+ : null;
- if (elementMapping == null
- || customConverter != null)
+ if (mapping == null)
{
- mapping = providerClrType == null
- || providerClrType == mappingInfo.ClrType
- ? self.FindMapping(mappingInfo)
- : null;
-
- if (mapping == null)
+ if (elementMapping == null
+ || customConverter != null)
{
if (sourceType != null)
{
@@ -173,7 +175,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
if (mapping != null)
{
- mapping = (RelationalTypeMapping)mapping.Clone(
+ mapping = (RelationalTypeMapping)mapping.WithComposedConverter(
secondConverterInfo.Create(),
jsonValueReaderWriter: mappingInfoUsed.JsonValueReaderWriter);
break;
@@ -183,7 +185,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
if (mapping != null)
{
- mapping = (RelationalTypeMapping)mapping.Clone(
+ mapping = (RelationalTypeMapping)mapping.WithComposedConverter(
converterInfo.Create(),
jsonValueReaderWriter: mappingInfo.JsonValueReaderWriter);
break;
@@ -193,16 +195,16 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
mapping ??= self.FindCollectionMapping(mappingInfo, sourceType, providerClrType, elementMapping);
}
}
- }
- else if (sourceType != null)
- {
- mapping = self.FindCollectionMapping(mappingInfo, sourceType, providerClrType, elementMapping);
+ else if (sourceType != null)
+ {
+ mapping = self.FindCollectionMapping(mappingInfo, sourceType, providerClrType, elementMapping);
+ }
}
if (mapping != null
&& customConverter != null)
{
- mapping = (RelationalTypeMapping)mapping.Clone(
+ mapping = (RelationalTypeMapping)mapping.WithComposedConverter(
customConverter,
jsonValueReaderWriter: mappingInfo.JsonValueReaderWriter);
}
@@ -212,39 +214,32 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
this);
///
- /// Attempts to find a type mapping for a collection of primitive types.
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
///
- /// The mapping info being used.
- /// The model type.
- /// The provider type.
- /// The element mapping, if known.
- /// The type mapping, or if none was found.
+ [EntityFrameworkInternal]
protected virtual RelationalTypeMapping? FindCollectionMapping(
RelationalTypeMappingInfo info,
Type modelType,
Type? providerType,
CoreTypeMapping? elementMapping)
- {
- var elementType = modelType.TryGetElementType(typeof(IEnumerable<>))!;
-
- return TryFindJsonCollectionMapping(
- info.CoreTypeMappingInfo, modelType, providerType, ref elementMapping, out var collectionReaderWriter)
+ => TryFindJsonCollectionMapping(
+ info.CoreTypeMappingInfo, modelType, providerType, ref elementMapping, out var comparer, out var collectionReaderWriter)
? (RelationalTypeMapping)FindMapping(
info.WithConverter(
// Note that the converter info is only used temporarily here and never creates an instance.
new ValueConverterInfo(modelType, typeof(string), _ => null!)))!
- .Clone(
+ .WithComposedConverter(
(ValueConverter)Activator.CreateInstance(
- typeof(CollectionToJsonStringConverter<>).MakeGenericType(elementType), collectionReaderWriter!)!,
- (ValueComparer?)Activator.CreateInstance(
- elementType.IsNullableValueType()
- ? typeof(NullableValueTypeListComparer<>).MakeGenericType(elementType.UnwrapNullableType())
- : typeof(ListComparer<>).MakeGenericType(elementMapping!.Comparer.Type),
- elementMapping!.Comparer),
+ typeof(CollectionToJsonStringConverter<>).MakeGenericType(
+ modelType.TryGetElementType(typeof(IEnumerable<>))!), collectionReaderWriter!)!,
+ comparer,
+ comparer,
elementMapping,
collectionReaderWriter)
: null;
- }
///
/// Finds the type mapping for a given .
@@ -309,7 +304,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
var resolvedMapping = FindMappingWithConversion(
new RelationalTypeMappingInfo(elementType, storeTypeName, storeTypeNameBase, unicode, isFixedLength, size, precision, scale),
- providerClrType, customConverter, null);
+ providerClrType, customConverter);
ValidateMapping(resolvedMapping, null);
@@ -354,7 +349,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
ValueConverter? customConverter = null;
if (typeConfiguration == null)
{
- mappingInfo = new RelationalTypeMappingInfo(type);
+ mappingInfo = new RelationalTypeMappingInfo(type, (RelationalTypeMapping?)elementMapping);
}
else
{
@@ -376,6 +371,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
var isFixedLength = (bool?)typeConfiguration[RelationalAnnotationNames.IsFixedLength];
mappingInfo = new RelationalTypeMappingInfo(
customConverter?.ProviderClrType ?? type,
+ (RelationalTypeMapping?)elementMapping,
storeTypeName,
storeTypeBaseName,
keyOrIndex: false,
@@ -387,7 +383,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
scale: scale);
}
- return FindMappingWithConversion(mappingInfo, providerClrType, customConverter, (RelationalTypeMapping?)elementMapping);
+ return FindMappingWithConversion(mappingInfo, providerClrType, customConverter);
}
///
@@ -419,7 +415,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
attribute.TypeName, ref unicode, ref size, ref precision, ref scale);
return FindMappingWithConversion(
- new RelationalTypeMappingInfo(member, storeTypeName, storeTypeNameBase, unicode, size, precision, scale), null);
+ new RelationalTypeMappingInfo(member, null, storeTypeName, storeTypeNameBase, unicode, size, precision, scale), null);
}
return FindMappingWithConversion(new RelationalTypeMappingInfo(member), null);
@@ -493,7 +489,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo)
return FindMappingWithConversion(
new RelationalTypeMappingInfo(
- type, storeTypeName, storeTypeBaseName, keyOrIndex, unicode, size, rowVersion, fixedLength, precision, scale), null);
+ type, null, storeTypeName, storeTypeBaseName, keyOrIndex, unicode, size, rowVersion, fixedLength, precision, scale), null);
}
///
diff --git a/src/EFCore.Relational/Storage/ValueConversion/RelationalConverterMappingHints.cs b/src/EFCore.Relational/Storage/ValueConversion/RelationalConverterMappingHints.cs
index ea677e5b762..24ab3940d2b 100644
--- a/src/EFCore.Relational/Storage/ValueConversion/RelationalConverterMappingHints.cs
+++ b/src/EFCore.Relational/Storage/ValueConversion/RelationalConverterMappingHints.cs
@@ -77,7 +77,7 @@ public override ConverterMappingHints With(ConverterMappingHints? hints)
(hints as RelationalConverterMappingHints)?.DbType ?? DbType);
///
- public override ConverterMappingHints Override(ConverterMappingHints? hints)
+ public override ConverterMappingHints OverrideWith(ConverterMappingHints? hints)
=> hints == null
? this
: new RelationalConverterMappingHints(
diff --git a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions.cs b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions.cs
index 5374f027ef4..2d16c843968 100644
--- a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions.cs
+++ b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Spatial data, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions
diff --git a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs
index eed9924ec79..2dcf2a7b4e1 100644
--- a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs
+++ b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs
@@ -14,7 +14,7 @@ namespace Microsoft.Extensions.DependencyInjection;
///
///
/// See Spatial data, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerNetTopologySuiteServiceCollectionExtensions
diff --git a/src/EFCore.SqlServer/DataCompressionType.cs b/src/EFCore.SqlServer/DataCompressionType.cs
new file mode 100644
index 00000000000..058f8f0567d
--- /dev/null
+++ b/src/EFCore.SqlServer/DataCompressionType.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.EntityFrameworkCore;
+
+///
+/// Indicates type of data compression used on a index.
+///
+///
+/// See Data Compression for more information on data compression.
+///
+public enum DataCompressionType
+{
+ ///
+ /// Index is not compressed.
+ ///
+ None,
+
+ ///
+ /// Index is compressed by using row compression.
+ ///
+ Row,
+
+ ///
+ /// Index is compressed by using page compression.
+ ///
+ Page
+}
diff --git a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs
index bb46a3e6be7..701b3896e90 100644
--- a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs
+++ b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs
@@ -79,6 +79,14 @@ private static readonly MethodInfo IndexHasFillFactorMethodInfo
= typeof(SqlServerIndexBuilderExtensions).GetRuntimeMethod(
nameof(SqlServerIndexBuilderExtensions.HasFillFactor), new[] { typeof(IndexBuilder), typeof(int) })!;
+ private static readonly MethodInfo IndexSortInTempDbMethodInfo
+ = typeof(SqlServerIndexBuilderExtensions).GetRuntimeMethod(
+ nameof(SqlServerIndexBuilderExtensions.SortInTempDb), new[] { typeof(IndexBuilder), typeof(bool) })!;
+
+ private static readonly MethodInfo IndexUseDataCompressionMethodInfo
+ = typeof(SqlServerIndexBuilderExtensions).GetRuntimeMethod(
+ nameof(SqlServerIndexBuilderExtensions.UseDataCompression), new[] { typeof(IndexBuilder), typeof(DataCompressionType) })!;
+
private static readonly MethodInfo KeyIsClusteredMethodInfo
= typeof(SqlServerKeyBuilderExtensions).GetRuntimeMethod(
nameof(SqlServerKeyBuilderExtensions.IsClustered), new[] { typeof(KeyBuilder), typeof(bool) })!;
@@ -341,6 +349,8 @@ protected override bool IsHandledByConvention(IProperty property, IAnnotation an
SqlServerAnnotationNames.Include => new MethodCallCodeFragment(IndexIncludePropertiesMethodInfo, annotation.Value),
SqlServerAnnotationNames.FillFactor => new MethodCallCodeFragment(IndexHasFillFactorMethodInfo, annotation.Value),
+ SqlServerAnnotationNames.SortInTempDb => new MethodCallCodeFragment(IndexSortInTempDbMethodInfo, annotation.Value),
+ SqlServerAnnotationNames.DataCompression => new MethodCallCodeFragment(IndexUseDataCompressionMethodInfo, annotation.Value),
_ => null
};
diff --git a/src/EFCore.SqlServer/Design/Internal/SqlServerCSharpRuntimeAnnotationCodeGenerator.cs b/src/EFCore.SqlServer/Design/Internal/SqlServerCSharpRuntimeAnnotationCodeGenerator.cs
index 793eb75ca00..7bb1012a136 100644
--- a/src/EFCore.SqlServer/Design/Internal/SqlServerCSharpRuntimeAnnotationCodeGenerator.cs
+++ b/src/EFCore.SqlServer/Design/Internal/SqlServerCSharpRuntimeAnnotationCodeGenerator.cs
@@ -104,6 +104,8 @@ public override void Generate(IIndex index, CSharpRuntimeAnnotationCodeGenerator
annotations.Remove(SqlServerAnnotationNames.CreatedOnline);
annotations.Remove(SqlServerAnnotationNames.Include);
annotations.Remove(SqlServerAnnotationNames.FillFactor);
+ annotations.Remove(SqlServerAnnotationNames.SortInTempDb);
+ annotations.Remove(SqlServerAnnotationNames.DataCompression);
}
base.Generate(index, parameters);
@@ -119,6 +121,8 @@ public override void Generate(ITableIndex index, CSharpRuntimeAnnotationCodeGene
annotations.Remove(SqlServerAnnotationNames.CreatedOnline);
annotations.Remove(SqlServerAnnotationNames.Include);
annotations.Remove(SqlServerAnnotationNames.FillFactor);
+ annotations.Remove(SqlServerAnnotationNames.SortInTempDb);
+ annotations.Remove(SqlServerAnnotationNames.DataCompression);
}
base.Generate(index, parameters);
diff --git a/src/EFCore.SqlServer/Diagnostics/ConflictingValueGenerationStrategiesEventData.cs b/src/EFCore.SqlServer/Diagnostics/ConflictingValueGenerationStrategiesEventData.cs
index 5e3790bbc7b..689afa66ef5 100644
--- a/src/EFCore.SqlServer/Diagnostics/ConflictingValueGenerationStrategiesEventData.cs
+++ b/src/EFCore.SqlServer/Diagnostics/ConflictingValueGenerationStrategiesEventData.cs
@@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics;
///
///
/// See Logging, events, and diagnostics, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class ConflictingValueGenerationStrategiesEventData : EventData
diff --git a/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs b/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs
index a952d93627d..2fd40c196ef 100644
--- a/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs
+++ b/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs
@@ -14,7 +14,7 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics;
///
///
/// See Logging, events, and diagnostics, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePrimitiveCollectionBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePrimitiveCollectionBuilderExtensions.cs
index afd29bd2087..c4747993ba7 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePrimitiveCollectionBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePrimitiveCollectionBuilderExtensions.cs
@@ -8,7 +8,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerComplexTypePrimitiveCollectionBuilderExtensions
@@ -18,7 +18,7 @@ public static class SqlServerComplexTypePrimitiveCollectionBuilderExtensions
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
@@ -38,7 +38,7 @@ public static ComplexTypePrimitiveCollectionBuilder IsSparse(this ComplexTypePri
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePropertyBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePropertyBuilderExtensions.cs
index 3e55e93207a..bb624ebc71d 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePropertyBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePropertyBuilderExtensions.cs
@@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerComplexTypePropertyBuilderExtensions
@@ -20,7 +20,7 @@ public static class SqlServerComplexTypePropertyBuilderExtensions
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -61,7 +61,7 @@ public static ComplexTypePropertyBuilder UseHiLo(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of the property being configured.
@@ -81,7 +81,7 @@ public static ComplexTypePropertyBuilder UseHiLo(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -115,7 +115,7 @@ public static ComplexTypePropertyBuilder UseSequence(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of the property being configured.
@@ -135,7 +135,7 @@ public static ComplexTypePropertyBuilder UseSequence(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -165,7 +165,7 @@ public static ComplexTypePropertyBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -184,7 +184,7 @@ public static ComplexTypePropertyBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of the property being configured.
@@ -204,7 +204,7 @@ public static ComplexTypePropertyBuilder UseIdentityColumn
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of the property being configured.
@@ -223,7 +223,7 @@ public static ComplexTypePropertyBuilder UseIdentityColumn
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
@@ -243,7 +243,7 @@ public static ComplexTypePropertyBuilder IsSparse(this ComplexTypePropertyBuilde
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDatabaseFacadeExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDatabaseFacadeExtensions.cs
index 3b9ba661860..d623ef40586 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerDatabaseFacadeExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerDatabaseFacadeExtensions.cs
@@ -22,7 +22,7 @@ public static class SqlServerDatabaseFacadeExtensions
/// provider to use as part of configuring the context.
///
///
- /// See Accessing SQL Server and SQL Azure databases with EF Core
+ /// See Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbContextOptionsBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbContextOptionsBuilderExtensions.cs
index 6859203cfc4..8ab8663f40f 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerDbContextOptionsBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerDbContextOptionsBuilderExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Using DbContextOptions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerDbContextOptionsExtensions
@@ -28,7 +28,7 @@ public static class SqlServerDbContextOptionsExtensions
///
///
/// See Using DbContextOptions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -41,11 +41,7 @@ public static DbContextOptionsBuilder UseSqlServer(
{
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(GetOrCreateExtension(optionsBuilder));
- ConfigureWarnings(optionsBuilder);
-
- sqlServerOptionsAction?.Invoke(new SqlServerDbContextOptionsBuilder(optionsBuilder));
-
- return optionsBuilder;
+ return ApplyConfiguration(optionsBuilder, sqlServerOptionsAction);
}
///
@@ -53,7 +49,7 @@ public static DbContextOptionsBuilder UseSqlServer(
///
///
/// See Using DbContextOptions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder being used to configure the context.
@@ -68,11 +64,7 @@ public static DbContextOptionsBuilder UseSqlServer(
var extension = (SqlServerOptionsExtension)GetOrCreateExtension(optionsBuilder).WithConnectionString(connectionString);
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
- ConfigureWarnings(optionsBuilder);
-
- sqlServerOptionsAction?.Invoke(new SqlServerDbContextOptionsBuilder(optionsBuilder));
-
- return optionsBuilder;
+ return ApplyConfiguration(optionsBuilder, sqlServerOptionsAction);
}
// Note: Decision made to use DbConnection not SqlConnection: Issue #772
@@ -81,7 +73,7 @@ public static DbContextOptionsBuilder UseSqlServer(
///
///
/// See Using DbContextOptions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder being used to configure the context.
@@ -105,7 +97,7 @@ public static DbContextOptionsBuilder UseSqlServer(
///
///
/// See Using DbContextOptions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder being used to configure the context.
@@ -132,11 +124,7 @@ public static DbContextOptionsBuilder UseSqlServer(
var extension = (SqlServerOptionsExtension)GetOrCreateExtension(optionsBuilder).WithConnection(connection, contextOwnsConnection);
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
- ConfigureWarnings(optionsBuilder);
-
- sqlServerOptionsAction?.Invoke(new SqlServerDbContextOptionsBuilder(optionsBuilder));
-
- return optionsBuilder;
+ return ApplyConfiguration(optionsBuilder, sqlServerOptionsAction);
}
///
@@ -151,7 +139,7 @@ public static DbContextOptionsBuilder UseSqlServer(
///
///
/// See Using DbContextOptions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -170,7 +158,7 @@ public static DbContextOptionsBuilder UseSqlServer(
///
///
/// See Using DbContextOptions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of context to be configured.
@@ -192,7 +180,7 @@ public static DbContextOptionsBuilder UseSqlServer(
///
///
/// See Using DbContextOptions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of context to be configured.
@@ -219,7 +207,7 @@ public static DbContextOptionsBuilder UseSqlServer(
///
///
/// See Using DbContextOptions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of context to be configured.
@@ -249,6 +237,18 @@ private static SqlServerOptionsExtension GetOrCreateExtension(DbContextOptionsBu
=> optionsBuilder.Options.FindExtension()
?? new SqlServerOptionsExtension();
+ private static DbContextOptionsBuilder ApplyConfiguration(DbContextOptionsBuilder optionsBuilder, Action? sqlServerOptionsAction)
+ {
+ ConfigureWarnings(optionsBuilder);
+
+ sqlServerOptionsAction?.Invoke(new SqlServerDbContextOptionsBuilder(optionsBuilder));
+
+ var extension = (SqlServerOptionsExtension)GetOrCreateExtension(optionsBuilder).ApplyDefaults(optionsBuilder.Options);
+ ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
+
+ return optionsBuilder;
+ }
+
private static void ConfigureWarnings(DbContextOptionsBuilder optionsBuilder)
{
var coreOptionsExtension
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs
index 6180a64a702..9854fd86dde 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Database functions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerDbFunctionsExtensions
@@ -23,7 +23,7 @@ public static class SqlServerDbFunctionsExtensions
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -42,7 +42,7 @@ public static bool FreeText(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -59,7 +59,7 @@ public static bool FreeText(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -78,7 +78,7 @@ public static bool Contains(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -100,7 +100,7 @@ public static bool Contains(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -119,7 +119,7 @@ public static int DateDiffYear(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -138,7 +138,7 @@ public static int DateDiffYear(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -157,7 +157,7 @@ public static int DateDiffYear(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -176,7 +176,7 @@ public static int DateDiffYear(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -195,7 +195,7 @@ public static int DateDiffYear(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -218,7 +218,7 @@ public static int DateDiffYear(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -237,7 +237,7 @@ public static int DateDiffMonth(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -256,7 +256,7 @@ public static int DateDiffMonth(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -275,7 +275,7 @@ public static int DateDiffMonth(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -294,7 +294,7 @@ public static int DateDiffMonth(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -313,7 +313,7 @@ public static int DateDiffMonth(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -336,7 +336,7 @@ public static int DateDiffMonth(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -355,7 +355,7 @@ public static int DateDiffDay(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -374,7 +374,7 @@ public static int DateDiffDay(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -393,7 +393,7 @@ public static int DateDiffDay(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -412,7 +412,7 @@ public static int DateDiffDay(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -431,7 +431,7 @@ public static int DateDiffDay(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -454,7 +454,7 @@ public static int DateDiffDay(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -473,7 +473,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -492,7 +492,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -511,7 +511,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -530,7 +530,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -549,7 +549,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -568,7 +568,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -587,7 +587,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -606,7 +606,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -625,7 +625,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -648,7 +648,7 @@ public static int DateDiffHour(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -667,7 +667,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -686,7 +686,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -705,7 +705,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -724,7 +724,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -743,7 +743,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -762,7 +762,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -781,7 +781,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -800,7 +800,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -819,7 +819,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -842,7 +842,7 @@ public static int DateDiffMinute(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -861,7 +861,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -880,7 +880,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -899,7 +899,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -918,7 +918,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -937,7 +937,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -956,7 +956,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -975,7 +975,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -994,7 +994,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1013,7 +1013,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1036,7 +1036,7 @@ public static int DateDiffSecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1055,7 +1055,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1074,7 +1074,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1093,7 +1093,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1112,7 +1112,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1131,7 +1131,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1150,7 +1150,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1169,7 +1169,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1188,7 +1188,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1207,7 +1207,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1230,7 +1230,7 @@ public static int DateDiffMillisecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1249,7 +1249,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1268,7 +1268,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1287,7 +1287,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1306,7 +1306,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1325,7 +1325,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1344,7 +1344,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1363,7 +1363,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1382,7 +1382,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1401,7 +1401,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1424,7 +1424,7 @@ public static int DateDiffMicrosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1443,7 +1443,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1462,7 +1462,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1481,7 +1481,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1500,7 +1500,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1519,7 +1519,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1538,7 +1538,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1557,7 +1557,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1576,7 +1576,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1595,7 +1595,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1618,7 +1618,7 @@ public static int DateDiffNanosecond(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1637,7 +1637,7 @@ public static int DateDiffWeek(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1656,7 +1656,7 @@ public static int DateDiffWeek(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1675,7 +1675,7 @@ public static int DateDiffWeek(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1694,7 +1694,7 @@ public static int DateDiffWeek(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1713,7 +1713,7 @@ public static int DateDiffWeek(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1734,7 +1734,7 @@ public static int DateDiffWeek(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1752,7 +1752,7 @@ public static bool IsDate(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1784,7 +1784,7 @@ public static DateTime DateTimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1806,7 +1806,7 @@ public static DateTime DateFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1846,7 +1846,7 @@ public static DateTime DateTime2FromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1884,7 +1884,7 @@ public static DateTimeOffset DateTimeOffsetFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1909,7 +1909,7 @@ public static DateTime SmallDateTimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1935,7 +1935,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1951,7 +1951,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1967,7 +1967,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1983,7 +1983,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -1999,7 +1999,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -2015,7 +2015,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -2031,7 +2031,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -2047,7 +2047,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -2063,7 +2063,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -2080,7 +2080,7 @@ public static TimeSpan TimeFromParts(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
@@ -2102,7 +2102,7 @@ public static bool IsNumeric(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -2123,7 +2123,7 @@ public static DateTimeOffset AtTimeZone(
///
///
/// See Database functions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The instance.
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeBuilderExtensions.cs
index 30c00ffcbb6..c5ce3eac1fc 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeBuilderExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerEntityTypeBuilderExtensions
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs
index f0e15f9f2a3..1f69486cb80 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerEntityTypeExtensions
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs
index 4d5e3de65db..f57205ac507 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerIndexBuilderExtensions
@@ -21,7 +21,7 @@ public static class SqlServerIndexBuilderExtensions
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -39,7 +39,7 @@ public static IndexBuilder IsClustered(this IndexBuilder indexBuilder, bool clus
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -55,7 +55,7 @@ public static IndexBuilder IsClustered(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -84,7 +84,7 @@ public static IndexBuilder IsClustered(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -102,7 +102,7 @@ public static bool CanSetIsClustered(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -122,7 +122,7 @@ public static IndexBuilder IncludeProperties(this IndexBuilder indexBuilder, par
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -144,7 +144,7 @@ public static IndexBuilder IncludeProperties(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -177,7 +177,7 @@ public static IndexBuilder IncludeProperties(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -207,7 +207,7 @@ public static IndexBuilder IncludeProperties(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -229,7 +229,7 @@ public static bool CanSetIncludeProperties(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -247,7 +247,7 @@ public static IndexBuilder IsCreatedOnline(this IndexBuilder indexBuilder, bool
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -263,7 +263,7 @@ public static IndexBuilder IsCreatedOnline(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -293,7 +293,7 @@ public static IndexBuilder IsCreatedOnline(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -315,7 +315,7 @@ public static bool CanSetIsCreatedOnline(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -333,7 +333,7 @@ public static IndexBuilder HasFillFactor(this IndexBuilder indexBuilder, int fil
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -349,7 +349,7 @@ public static IndexBuilder HasFillFactor(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -379,7 +379,7 @@ public static IndexBuilder HasFillFactor(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the index being configured.
@@ -391,4 +391,176 @@ public static bool CanSetFillFactor(
int? fillFactor,
bool fromDataAnnotation = false)
=> indexBuilder.CanSetAnnotation(SqlServerAnnotationNames.FillFactor, fillFactor, fromDataAnnotation);
+
+ ///
+ /// Configures whether the index is created with sort in tempdb option when targeting SQL Server.
+ ///
+ ///
+ /// See Modeling entity types and relationships, and
+ /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// for more information and examples.
+ ///
+ /// The builder for the index being configured.
+ /// A value indicating whether the index is created with sort in tempdb option.
+ /// A builder to further configure the index.
+ public static IndexBuilder SortInTempDb(this IndexBuilder indexBuilder, bool sortInTempDb = true)
+ {
+ indexBuilder.Metadata.SetSortInTempDb(sortInTempDb);
+
+ return indexBuilder;
+ }
+
+ ///
+ /// Configures whether the index is created with sort in tempdb option when targeting SQL Server.
+ ///
+ ///
+ /// See Modeling entity types and relationships, and
+ /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// for more information and examples.
+ ///
+ /// The builder for the index being configured.
+ /// A value indicating whether the index is created with sort in tempdb option.
+ /// A builder to further configure the index.
+ public static IndexBuilder SortInTempDb(
+ this IndexBuilder indexBuilder,
+ bool sortInTempDb = true)
+ => (IndexBuilder)SortInTempDb((IndexBuilder)indexBuilder, sortInTempDb);
+
+ ///
+ /// Configures whether the index is created with sort in tempdb option when targeting SQL Server.
+ ///
+ ///
+ /// See Modeling entity types and relationships, and
+ /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// for more information and examples.
+ ///
+ /// The builder for the index being configured.
+ /// A value indicating whether the index is created with sort in tempdb option.
+ /// Indicates whether the configuration was specified using a data annotation.
+ ///
+ /// The same builder instance if the configuration was applied,
+ /// otherwise.
+ ///
+ public static IConventionIndexBuilder? SortInTempDb(
+ this IConventionIndexBuilder indexBuilder,
+ bool? sortInTempDb,
+ bool fromDataAnnotation = false)
+ {
+ if (indexBuilder.CanSetSortInTempDb(sortInTempDb, fromDataAnnotation))
+ {
+ indexBuilder.Metadata.SetSortInTempDb(sortInTempDb, fromDataAnnotation);
+
+ return indexBuilder;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Returns a value indicating whether the index can be configured with sort in tempdb option when targeting SQL Server.
+ ///
+ ///
+ /// See Modeling entity types and relationships, and
+ /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// for more information and examples.
+ ///
+ /// The builder for the index being configured.
+ /// A value indicating whether the index is created with sort in tempdb option.
+ /// Indicates whether the configuration was specified using a data annotation.
+ ///
+ /// The same builder instance if the configuration was applied,
+ /// otherwise.
+ ///
+ /// if the index can be configured with sort in tempdb option when targeting SQL Server.
+ public static bool CanSetSortInTempDb(
+ this IConventionIndexBuilder indexBuilder,
+ bool? sortInTempDb,
+ bool fromDataAnnotation = false)
+ => indexBuilder.CanSetAnnotation(SqlServerAnnotationNames.SortInTempDb, sortInTempDb, fromDataAnnotation);
+
+ ///
+ /// Configures whether the index is created with data compression option when targeting SQL Server.
+ ///
+ ///
+ /// See Modeling entity types and relationships, and
+ /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// for more information and examples.
+ ///
+ /// The builder for the index being configured.
+ /// A value indicating the data compression option to be used.
+ /// A builder to further configure the index.
+ public static IndexBuilder UseDataCompression(this IndexBuilder indexBuilder, DataCompressionType dataCompressionType)
+ {
+ indexBuilder.Metadata.SetDataCompression(dataCompressionType);
+
+ return indexBuilder;
+ }
+
+ ///
+ /// Configures whether the index is created with data compression option when targeting SQL Server.
+ ///
+ ///
+ /// See Modeling entity types and relationships, and
+ /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// for more information and examples.
+ ///
+ /// The builder for the index being configured.
+ /// A value indicating the data compression option to be used.
+ /// A builder to further configure the index.
+ public static IndexBuilder UseDataCompression(
+ this IndexBuilder indexBuilder,
+ DataCompressionType dataCompressionType)
+ => (IndexBuilder)UseDataCompression((IndexBuilder)indexBuilder, dataCompressionType);
+
+ ///
+ /// Configures whether the index is created with data compression option when targeting SQL Server.
+ ///
+ ///
+ /// See Modeling entity types and relationships, and
+ /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// for more information and examples.
+ ///
+ /// The builder for the index being configured.
+ /// A value indicating the data compression option to be used.
+ /// Indicates whether the configuration was specified using a data annotation.
+ ///
+ /// The same builder instance if the configuration was applied,
+ /// otherwise.
+ ///
+ public static IConventionIndexBuilder? UseDataCompression(
+ this IConventionIndexBuilder indexBuilder,
+ DataCompressionType? dataCompressionType,
+ bool fromDataAnnotation = false)
+ {
+ if (indexBuilder.CanSetDataCompression(dataCompressionType, fromDataAnnotation))
+ {
+ indexBuilder.Metadata.SetDataCompression(dataCompressionType, fromDataAnnotation);
+
+ return indexBuilder;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Returns a value indicating whether the index can be configured with data compression option when targeting SQL Server.
+ ///
+ ///
+ /// See Modeling entity types and relationships, and
+ /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// for more information and examples.
+ ///
+ /// The builder for the index being configured.
+ /// A value indicating the data compression option to be used.
+ /// Indicates whether the configuration was specified using a data annotation.
+ ///
+ /// The same builder instance if the configuration was applied,
+ /// otherwise.
+ ///
+ /// if the index can be configured with data compression option when targeting SQL Server.
+ public static bool CanSetDataCompression(
+ this IConventionIndexBuilder indexBuilder,
+ DataCompressionType? dataCompressionType,
+ bool fromDataAnnotation = false)
+ => indexBuilder.CanSetAnnotation(SqlServerAnnotationNames.DataCompression, dataCompressionType, fromDataAnnotation);
}
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerIndexExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerIndexExtensions.cs
index af32ab3f1dd..58310d77a54 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerIndexExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerIndexExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerIndexExtensions
@@ -297,4 +297,136 @@ public static void SetFillFactor(this IMutableIndex index, int? fillFactor)
/// The for whether the index uses the fill factor.
public static ConfigurationSource? GetFillFactorConfigurationSource(this IConventionIndex index)
=> index.FindAnnotation(SqlServerAnnotationNames.FillFactor)?.GetConfigurationSource();
+
+ ///
+ /// Returns a value indicating whether the index is sorted in tempdb.
+ ///
+ /// The index.
+ /// if the index is sorted in tempdb.
+ public static bool? GetSortInTempDb(this IReadOnlyIndex index)
+ => (index is RuntimeIndex)
+ ? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData)
+ : (bool?)index[SqlServerAnnotationNames.SortInTempDb];
+
+ ///
+ /// Returns a value indicating whether the index is sorted in tempdb.
+ ///
+ /// The index.
+ /// The identifier of the store object.
+ /// if the index is sorted in tempdb.
+ public static bool? GetSortInTempDb(this IReadOnlyIndex index, in StoreObjectIdentifier storeObject)
+ {
+ if (index is RuntimeIndex)
+ {
+ throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData);
+ }
+
+ var annotation = index.FindAnnotation(SqlServerAnnotationNames.SortInTempDb);
+ if (annotation != null)
+ {
+ return (bool?)annotation.Value;
+ }
+
+ var sharedTableRootIndex = index.FindSharedObjectRootIndex(storeObject);
+ return sharedTableRootIndex?.GetSortInTempDb(storeObject);
+ }
+
+ ///
+ /// Sets a value indicating whether the index is sorted in tempdb.
+ ///
+ /// The index.
+ /// The value to set.
+ public static void SetSortInTempDb(this IMutableIndex index, bool? sortInTempDb)
+ => index.SetAnnotation(
+ SqlServerAnnotationNames.SortInTempDb,
+ sortInTempDb);
+
+ ///
+ /// Sets a value indicating whether the index is sorted in tempdb.
+ ///
+ /// The index.
+ /// The value to set.
+ /// Indicates whether the configuration was specified using a data annotation.
+ /// The configured value.
+ public static bool? SetSortInTempDb(
+ this IConventionIndex index,
+ bool? sortInTempDb,
+ bool fromDataAnnotation = false)
+ => (bool?)index.SetAnnotation(
+ SqlServerAnnotationNames.SortInTempDb,
+ sortInTempDb,
+ fromDataAnnotation)?.Value;
+
+ ///
+ /// Returns the for whether the index is sorted in tempdb.
+ ///
+ /// The index.
+ /// The for whether the index is sorted in tempdb.
+ public static ConfigurationSource? GetSortInTempDbConfigurationSource(this IConventionIndex index)
+ => index.FindAnnotation(SqlServerAnnotationNames.SortInTempDb)?.GetConfigurationSource();
+
+ ///
+ /// Returns the data compression that the index uses.
+ ///
+ /// The index.
+ /// The data compression that the index uses
+ public static DataCompressionType? GetDataCompression(this IReadOnlyIndex index)
+ => (index is RuntimeIndex)
+ ? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData)
+ : (DataCompressionType?)index[SqlServerAnnotationNames.DataCompression];
+
+ ///
+ /// Returns the data compression that the index uses.
+ ///
+ /// The index.
+ /// The identifier of the store object.
+ /// The data compression that the index uses
+ public static DataCompressionType? GetDataCompression(this IReadOnlyIndex index, in StoreObjectIdentifier storeObject)
+ {
+ if (index is RuntimeIndex)
+ {
+ throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData);
+ }
+
+ var annotation = index.FindAnnotation(SqlServerAnnotationNames.DataCompression);
+ if (annotation != null)
+ {
+ return (DataCompressionType?)annotation.Value;
+ }
+
+ var sharedTableRootIndex = index.FindSharedObjectRootIndex(storeObject);
+ return sharedTableRootIndex?.GetDataCompression(storeObject);
+ }
+
+ ///
+ /// Sets a value indicating the data compression the index uses.
+ ///
+ /// The index.
+ /// The value to set.
+ public static void SetDataCompression(this IMutableIndex index, DataCompressionType? dataCompression) => index.SetAnnotation(
+ SqlServerAnnotationNames.DataCompression,
+ dataCompression);
+
+ ///
+ /// Sets a value indicating the data compression the index uses.
+ ///
+ /// The index.
+ /// The value to set.
+ /// Indicates whether the configuration was specified using a data annotation.
+ /// The configured value.
+ public static DataCompressionType? SetDataCompression(
+ this IConventionIndex index,
+ DataCompressionType? dataCompression,
+ bool fromDataAnnotation = false) => (DataCompressionType?)index.SetAnnotation(
+ SqlServerAnnotationNames.DataCompression,
+ dataCompression,
+ fromDataAnnotation)?.Value;
+
+ ///
+ /// Returns the for the data compression the index uses.
+ ///
+ /// The index.
+ /// The for the data compression the index uses.
+ public static ConfigurationSource? GetDataCompressionConfigurationSource(this IConventionIndex index)
+ => index.FindAnnotation(SqlServerAnnotationNames.DataCompression)?.GetConfigurationSource();
}
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerKeyBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerKeyBuilderExtensions.cs
index 2a248e20eb6..0deb6c04875 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerKeyBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerKeyBuilderExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerKeyBuilderExtensions
@@ -21,7 +21,7 @@ public static class SqlServerKeyBuilderExtensions
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the key being configured.
@@ -39,7 +39,7 @@ public static KeyBuilder IsClustered(this KeyBuilder keyBuilder, bool clustered
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the key being configured.
@@ -55,7 +55,7 @@ public static KeyBuilder IsClustered(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the key being configured.
@@ -84,7 +84,7 @@ public static KeyBuilder IsClustered(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the key being configured.
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerKeyExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerKeyExtensions.cs
index 8f22e06b691..5a5c7d1e1b4 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerKeyExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerKeyExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerKeyExtensions
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerMigrationBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerMigrationBuilderExtensions.cs
index 368ba006a8a..d996d0ca99a 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerMigrationBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerMigrationBuilderExtensions.cs
@@ -15,7 +15,7 @@ public static class SqlServerMigrationBuilderExtensions
/// Returns if the database provider currently in use is the SQL Server provider.
///
///
- /// See Accessing SQL Server and SQL Azure databases with EF Core
+ /// See Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerModelBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerModelBuilderExtensions.cs
index 0ab2c60f7ae..f615ffad5c3 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerModelBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerModelBuilderExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerModelBuilderExtensions
@@ -22,7 +22,7 @@ public static class SqlServerModelBuilderExtensions
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -63,7 +63,7 @@ public static ModelBuilder UseHiLo(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -93,7 +93,7 @@ public static ModelBuilder UseHiLo(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -120,7 +120,7 @@ public static bool CanSetHiLoSequence(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -157,7 +157,7 @@ public static ModelBuilder UseKeySequences(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -189,7 +189,7 @@ public static ModelBuilder UseIdentityColumns(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -207,7 +207,7 @@ public static ModelBuilder UseIdentityColumns(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -236,7 +236,7 @@ public static ModelBuilder UseIdentityColumns(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -254,7 +254,7 @@ public static bool CanSetIdentityColumnSeed(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -283,7 +283,7 @@ public static bool CanSetIdentityColumnSeed(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -302,7 +302,7 @@ public static bool CanSetIdentityColumnIncrement(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -357,7 +357,7 @@ void RemoveKeySequenceAnnotations()
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -380,7 +380,7 @@ public static bool CanSetValueGenerationStrategy(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -405,7 +405,7 @@ public static ModelBuilder HasDatabaseMaxSize(this ModelBuilder modelBuilder, st
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -435,7 +435,7 @@ public static ModelBuilder HasDatabaseMaxSize(this ModelBuilder modelBuilder, st
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -457,7 +457,7 @@ public static bool CanSetDatabaseMaxSize(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -482,7 +482,7 @@ public static ModelBuilder HasServiceTier(this ModelBuilder modelBuilder, string
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -507,7 +507,7 @@ public static ModelBuilder HasServiceTierSql(this ModelBuilder modelBuilder, str
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -537,7 +537,7 @@ public static ModelBuilder HasServiceTierSql(this ModelBuilder modelBuilder, str
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
@@ -559,7 +559,7 @@ public static bool CanSetServiceTierSql(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -584,7 +584,7 @@ public static ModelBuilder HasPerformanceLevel(this ModelBuilder modelBuilder, s
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -609,7 +609,7 @@ public static ModelBuilder HasPerformanceLevelSql(this ModelBuilder modelBuilder
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -639,7 +639,7 @@ public static ModelBuilder HasPerformanceLevelSql(this ModelBuilder modelBuilder
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The model builder.
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerModelExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerModelExtensions.cs
index 7d494049b24..2925804927e 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerModelExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerModelExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerModelExtensions
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerPrimitiveCollectionBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerPrimitiveCollectionBuilderExtensions.cs
index 17dd2d26dfe..87fa60c5132 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerPrimitiveCollectionBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerPrimitiveCollectionBuilderExtensions.cs
@@ -8,7 +8,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerPrimitiveCollectionBuilderExtensions
@@ -18,7 +18,7 @@ public static class SqlServerPrimitiveCollectionBuilderExtensions
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
@@ -38,7 +38,7 @@ public static PrimitiveCollectionBuilder IsSparse(this PrimitiveCollectionBuilde
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs
index 11d8e694a1c..f959733c7e3 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerPropertyBuilderExtensions
@@ -22,7 +22,7 @@ public static class SqlServerPropertyBuilderExtensions
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -63,7 +63,7 @@ public static PropertyBuilder UseHiLo(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of the property being configured.
@@ -83,7 +83,7 @@ public static PropertyBuilder UseHiLo(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -115,7 +115,7 @@ public static PropertyBuilder UseHiLo(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -142,7 +142,7 @@ public static bool CanSetHiLoSequence(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -176,7 +176,7 @@ public static PropertyBuilder UseSequence(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of the property being configured.
@@ -196,7 +196,7 @@ public static PropertyBuilder UseSequence(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -228,7 +228,7 @@ public static PropertyBuilder UseSequence(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -255,7 +255,7 @@ public static bool CanSetSequence(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -285,7 +285,7 @@ public static PropertyBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -304,7 +304,7 @@ public static PropertyBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the column being configured.
@@ -330,7 +330,7 @@ public static ColumnBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of the property being configured.
@@ -350,7 +350,7 @@ public static PropertyBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of the property being configured.
@@ -370,7 +370,7 @@ public static PropertyBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The type of the property being configured.
@@ -389,7 +389,7 @@ public static ColumnBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -418,7 +418,7 @@ public static ColumnBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -449,7 +449,7 @@ public static ColumnBuilder UseIdentityColumn(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -468,7 +468,7 @@ public static bool CanSetIdentityColumnSeed(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -493,7 +493,7 @@ public static bool CanSetIdentityColumnSeed(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -522,7 +522,7 @@ public static bool CanSetIdentityColumnSeed(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -553,7 +553,7 @@ public static bool CanSetIdentityColumnSeed(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -572,7 +572,7 @@ public static bool CanSetIdentityColumnIncrement(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -597,7 +597,7 @@ public static bool CanSetIdentityColumnIncrement(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -647,7 +647,7 @@ public static bool CanSetIdentityColumnIncrement(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -684,7 +684,7 @@ public static bool CanSetIdentityColumnIncrement(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -705,7 +705,7 @@ public static bool CanSetValueGenerationStrategy(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
/// The builder for the property being configured.
@@ -732,7 +732,7 @@ public static bool CanSetValueGenerationStrategy(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
@@ -752,7 +752,7 @@ public static PropertyBuilder IsSparse(this PropertyBuilder propertyBuilder, boo
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
@@ -770,7 +770,7 @@ public static PropertyBuilder IsSparse(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
@@ -799,7 +799,7 @@ public static PropertyBuilder IsSparse(
///
///
/// See Modeling entity types and relationships, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples. Also see
/// Sparse columns for
/// general information on SQL Server sparse columns.
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs
index 5251dbdabbf..079a85b724e 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs
@@ -12,7 +12,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
/// See Modeling entity types and relationships, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public static class SqlServerPropertyExtensions
diff --git a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs
index a994c313168..12f2d4cf882 100644
--- a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs
+++ b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs
@@ -45,7 +45,7 @@ public static class SqlServerServiceCollectionExtensions
///
///
/// See Using DbContextOptions, and
- /// Accessing SQL Server and SQL Azure databases with EF Core
+ /// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
diff --git a/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerOptionsExtension.cs b/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerOptionsExtension.cs
index 50c0d07e894..69a5c9802a7 100644
--- a/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerOptionsExtension.cs
+++ b/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerOptionsExtension.cs
@@ -11,10 +11,11 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal;
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
-public class SqlServerOptionsExtension : RelationalOptionsExtension
+public class SqlServerOptionsExtension : RelationalOptionsExtension, IDbContextOptionsExtension
{
private DbContextOptionsExtensionInfo? _info;
private int? _compatibilityLevel;
+ private bool? _azureSql;
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -52,6 +53,7 @@ protected SqlServerOptionsExtension(SqlServerOptionsExtension copyFrom)
: base(copyFrom)
{
_compatibilityLevel = copyFrom._compatibilityLevel;
+ _azureSql = copyFrom._azureSql;
}
///
@@ -105,6 +107,50 @@ public virtual SqlServerOptionsExtension WithCompatibilityLevel(int? compatibili
return clone;
}
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual bool IsAzureSql
+ => _azureSql ?? IsAzureSqlDefault;
+
+ private bool IsAzureSqlDefault
+ => (ConnectionString ?? Connection?.ConnectionString)
+ ?.Contains(".database.windows.net", StringComparison.InvariantCultureIgnoreCase) == true;
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual SqlServerOptionsExtension WithAzureSql(bool enable)
+ {
+ var clone = (SqlServerOptionsExtension)Clone();
+
+ clone._azureSql = enable;
+
+ return clone;
+ }
+
+ ///
+ public virtual IDbContextOptionsExtension ApplyDefaults(IDbContextOptions options)
+ {
+ if (!IsAzureSql)
+ {
+ return this;
+ }
+
+ if (ExecutionStrategyFactory == null)
+ {
+ return WithExecutionStrategyFactory(c => new SqlServerRetryingExecutionStrategy(c));
+ }
+
+ return this;
+ }
+
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
diff --git a/src/EFCore.SqlServer/Infrastructure/SqlServerDbContextOptionsBuilder.cs b/src/EFCore.SqlServer/Infrastructure/SqlServerDbContextOptionsBuilder.cs
index 066f6eccc03..16e9221fbc8 100644
--- a/src/EFCore.SqlServer/Infrastructure/SqlServerDbContextOptionsBuilder.cs
+++ b/src/EFCore.SqlServer/Infrastructure/SqlServerDbContextOptionsBuilder.cs
@@ -29,7 +29,7 @@ public SqlServerDbContextOptionsBuilder(DbContextOptionsBuilder optionsBuilder)
///
///
///
- /// This strategy is specifically tailored to SQL Server (including SQL Azure). It is pre-configured with
+ /// This strategy is specifically tailored to SQL Server (including Azure SQL). It is pre-configured with
/// error numbers for transient errors that can be retried.
///
///
@@ -48,7 +48,7 @@ public virtual SqlServerDbContextOptionsBuilder EnableRetryOnFailure()
///
///
///
- /// This strategy is specifically tailored to SQL Server (including SQL Azure). It is pre-configured with
+ /// This strategy is specifically tailored to SQL Server (including Azure SQL). It is pre-configured with
/// error numbers for transient errors that can be retried.
///
///
@@ -67,7 +67,7 @@ public virtual SqlServerDbContextOptionsBuilder EnableRetryOnFailure(int maxRetr
///
///
///
- /// This strategy is specifically tailored to SQL Server (including SQL Azure). It is pre-configured with
+ /// This strategy is specifically tailored to SQL Server (including Azure SQL). It is pre-configured with
/// error numbers for transient errors that can be retried.
///
///
@@ -87,7 +87,7 @@ public virtual SqlServerDbContextOptionsBuilder EnableRetryOnFailure(ICollection
///
///
///
- /// This strategy is specifically tailored to SQL Server (including SQL Azure). It is pre-configured with
+ /// This strategy is specifically tailored to SQL Server (including Azure SQL). It is pre-configured with
/// error numbers for transient errors that can be retried, but additional error numbers can also be supplied.
///
///
@@ -116,4 +116,11 @@ public virtual SqlServerDbContextOptionsBuilder EnableRetryOnFailure(
/// to have null resource
public virtual SqlServerDbContextOptionsBuilder UseCompatibilityLevel(int compatibilityLevel)
=> WithOption(e => e.WithCompatibilityLevel(compatibilityLevel));
+
+ ///
+ /// Configures the context to use defaults optimized for Azure SQL, including retries on errors.
+ ///
+ /// Whether the defaults should be enabled.
+ public virtual SqlServerDbContextOptionsBuilder UseAzureSql(bool enable = true)
+ => WithOption(e => e.WithAzureSql(enable));
}
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs
index 3638209f525..2ad3a9237be 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs
@@ -18,7 +18,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs
index 872b6ee91c1..0a256c30604 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerDbFunctionConvention : IModelFinalizingConvention
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs
index 16df1332b66..b83cc49b1d7 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs
@@ -13,7 +13,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerIndexConvention :
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs
index 0f71d79bb53..5dc3c3705bc 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerMemoryOptimizedTablesConvention :
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs
index 3c29be31606..d250176508b 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerOnDeleteConvention : CascadeDeleteConvention,
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOutputClauseConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOutputClauseConvention.cs
index eb128e7620c..0be9eb80f6c 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOutputClauseConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOutputClauseConvention.cs
@@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerOutputClauseConvention : ITriggerAddedConvention, ITriggerRemovedConvention
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerRuntimeModelConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerRuntimeModelConvention.cs
index e9118e97711..b821f0a0a21 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerRuntimeModelConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerRuntimeModelConvention.cs
@@ -12,7 +12,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerRuntimeModelConvention : RelationalRuntimeModelConvention
@@ -101,6 +101,8 @@ protected override void ProcessIndexAnnotations(
annotations.Remove(SqlServerAnnotationNames.CreatedOnline);
annotations.Remove(SqlServerAnnotationNames.Include);
annotations.Remove(SqlServerAnnotationNames.FillFactor);
+ annotations.Remove(SqlServerAnnotationNames.SortInTempDb);
+ annotations.Remove(SqlServerAnnotationNames.DataCompression);
}
}
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerSharedTableConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerSharedTableConvention.cs
index 3c26013b06a..d40b142c7e2 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerSharedTableConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerSharedTableConvention.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerSharedTableConvention : SharedTableConvention
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs
index 090821f4581..01e251ed153 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs
@@ -13,7 +13,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerStoreGenerationConvention : StoreGenerationConvention
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs
index 722eca989e2..32bc4f23ca1 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs
@@ -10,7 +10,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerTemporalConvention : IEntityTypeAnnotationChangedConvention,
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs
index 338cd8c1fd4..b7a201bed31 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs
@@ -15,7 +15,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerValueGenerationConvention : RelationalValueGenerationConvention
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs
index 2e58ef8dde1..8085d6f5027 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerValueGenerationStrategyConvention : IModelInitializedConvention, IModelFinalizingConvention
diff --git a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationNames.cs b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationNames.cs
index 8bf33226c28..c7905166617 100644
--- a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationNames.cs
+++ b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationNames.cs
@@ -51,6 +51,22 @@ public static class SqlServerAnnotationNames
///
public const string FillFactor = Prefix + "FillFactor";
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public const string SortInTempDb = Prefix + "SortInTempDb";
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public const string DataCompression = Prefix + "DataCompression";
+
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
diff --git a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs
index 40ed99df85c..deec2eb5561 100644
--- a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs
+++ b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs
@@ -203,6 +203,16 @@ public override IEnumerable For(ITableIndex index, bool designTime)
{
yield return new Annotation(SqlServerAnnotationNames.FillFactor, fillFactor);
}
+
+ if (modelIndex.GetSortInTempDb(table) is bool sortInTempDb)
+ {
+ yield return new Annotation(SqlServerAnnotationNames.SortInTempDb, sortInTempDb);
+ }
+
+ if (modelIndex.GetDataCompression(table) is DataCompressionType dataCompressionType)
+ {
+ yield return new Annotation(SqlServerAnnotationNames.DataCompression, dataCompressionType);
+ }
}
///
diff --git a/src/EFCore.SqlServer/Metadata/Internal/SqlServerIndexExtensions.cs b/src/EFCore.SqlServer/Metadata/Internal/SqlServerIndexExtensions.cs
index 49f21891482..416f1064329 100644
--- a/src/EFCore.SqlServer/Metadata/Internal/SqlServerIndexExtensions.cs
+++ b/src/EFCore.SqlServer/Metadata/Internal/SqlServerIndexExtensions.cs
@@ -100,6 +100,40 @@ public static bool AreCompatibleForSqlServer(
return false;
}
+ if (index.GetSortInTempDb() != duplicateIndex.GetSortInTempDb())
+ {
+ if (shouldThrow)
+ {
+ throw new InvalidOperationException(
+ SqlServerStrings.DuplicateIndexSortInTempDbMismatch(
+ index.DisplayName(),
+ index.DeclaringEntityType.DisplayName(),
+ duplicateIndex.DisplayName(),
+ duplicateIndex.DeclaringEntityType.DisplayName(),
+ index.DeclaringEntityType.GetSchemaQualifiedTableName(),
+ index.GetDatabaseName(storeObject)));
+ }
+
+ return false;
+ }
+
+ if (index.GetDataCompression() != duplicateIndex.GetDataCompression())
+ {
+ if (shouldThrow)
+ {
+ throw new InvalidOperationException(
+ SqlServerStrings.DuplicateIndexDataCompressionMismatch(
+ index.DisplayName(),
+ index.DeclaringEntityType.DisplayName(),
+ duplicateIndex.DisplayName(),
+ duplicateIndex.DeclaringEntityType.DisplayName(),
+ index.DeclaringEntityType.GetSchemaQualifiedTableName(),
+ index.GetDatabaseName(storeObject)));
+ }
+
+ return false;
+ }
+
return true;
static bool SameColumnNames(IReadOnlyIndex index, IReadOnlyIndex duplicateIndex, StoreObjectIdentifier storeObject)
diff --git a/src/EFCore.SqlServer/Metadata/SqlServerValueGenerationStrategy.cs b/src/EFCore.SqlServer/Metadata/SqlServerValueGenerationStrategy.cs
index e90240b9cee..8e88482a994 100644
--- a/src/EFCore.SqlServer/Metadata/SqlServerValueGenerationStrategy.cs
+++ b/src/EFCore.SqlServer/Metadata/SqlServerValueGenerationStrategy.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata;
///
///
/// See Model building conventions, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public enum SqlServerValueGenerationStrategy
diff --git a/src/EFCore.SqlServer/Migrations/Operations/SqlServerCreateDatabaseOperation.cs b/src/EFCore.SqlServer/Migrations/Operations/SqlServerCreateDatabaseOperation.cs
index 05ecc66db12..6be93893200 100644
--- a/src/EFCore.SqlServer/Migrations/Operations/SqlServerCreateDatabaseOperation.cs
+++ b/src/EFCore.SqlServer/Migrations/Operations/SqlServerCreateDatabaseOperation.cs
@@ -8,7 +8,7 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations;
///
///
/// See Database migrations, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
[DebuggerDisplay("CREATE DATABASE {Name}")]
diff --git a/src/EFCore.SqlServer/Migrations/Operations/SqlServerDropDatabaseOperation.cs b/src/EFCore.SqlServer/Migrations/Operations/SqlServerDropDatabaseOperation.cs
index 0cc5675a2e0..6d638a91f23 100644
--- a/src/EFCore.SqlServer/Migrations/Operations/SqlServerDropDatabaseOperation.cs
+++ b/src/EFCore.SqlServer/Migrations/Operations/SqlServerDropDatabaseOperation.cs
@@ -8,7 +8,7 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations;
///
///
/// See Database migrations, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
public class SqlServerDropDatabaseOperation : MigrationOperation
diff --git a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs
index ded9236cb74..e478aad78de 100644
--- a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs
+++ b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs
@@ -23,7 +23,7 @@ namespace Microsoft.EntityFrameworkCore.Migrations;
///
///
/// See Database migrations, and
-/// Accessing SQL Server and SQL Azure databases with EF Core
+/// Accessing SQL Server and Azure SQL databases with EF Core
/// for more information and examples.
///
///
@@ -1851,6 +1851,27 @@ private static void IndexWithOptions(CreateIndexOperation operation, MigrationCo
options.Add("ONLINE = ON");
}
+ if (operation[SqlServerAnnotationNames.SortInTempDb] is bool sortInTempDb && sortInTempDb)
+ {
+ options.Add("SORT_IN_TEMPDB = ON");
+ }
+
+ if (operation[SqlServerAnnotationNames.DataCompression] is DataCompressionType dataCompressionType)
+ {
+ switch (dataCompressionType)
+ {
+ case DataCompressionType.None:
+ options.Add("DATA_COMPRESSION = NONE");
+ break;
+ case DataCompressionType.Row:
+ options.Add("DATA_COMPRESSION = ROW");
+ break;
+ case DataCompressionType.Page:
+ options.Add("DATA_COMPRESSION = PAGE");
+ break;
+ }
+ }
+
if (options.Count > 0)
{
builder
diff --git a/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs b/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs
index 22c3a3a7fe8..a36445d1869 100644
--- a/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs
+++ b/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs
@@ -99,6 +99,14 @@ public static string DuplicateIndexClusteredMismatch(object? index1, object? ent
GetString("DuplicateIndexClusteredMismatch", nameof(index1), nameof(entityType1), nameof(index2), nameof(entityType2), nameof(table), nameof(indexName)),
index1, entityType1, index2, entityType2, table, indexName);
+ ///
+ /// The indexes {index1} on '{entityType1}' and {index2} on '{entityType2}' are both mapped to '{table}.{indexName}', but have different data compression configurations.
+ ///
+ public static string DuplicateIndexDataCompressionMismatch(object? index1, object? entityType1, object? index2, object? entityType2, object? table, object? indexName)
+ => string.Format(
+ GetString("DuplicateIndexDataCompressionMismatch", nameof(index1), nameof(entityType1), nameof(index2), nameof(entityType2), nameof(table), nameof(indexName)),
+ index1, entityType1, index2, entityType2, table, indexName);
+
///
/// The indexes {index1} on '{entityType1}' and {index2} on '{entityType2}' are both mapped to '{table}.{indexName}', but have different fill factor configurations.
///
@@ -123,6 +131,14 @@ public static string DuplicateIndexOnlineMismatch(object? index1, object? entity
GetString("DuplicateIndexOnlineMismatch", nameof(index1), nameof(entityType1), nameof(index2), nameof(entityType2), nameof(table), nameof(indexName)),
index1, entityType1, index2, entityType2, table, indexName);
+ ///
+ /// The indexes {index1} on '{entityType1}' and {index2} on '{entityType2}' are both mapped to '{table}.{indexName}', but have different sort in tempdb configurations.
+ ///
+ public static string DuplicateIndexSortInTempDbMismatch(object? index1, object? entityType1, object? index2, object? entityType2, object? table, object? indexName)
+ => string.Format(
+ GetString("DuplicateIndexSortInTempDbMismatch", nameof(index1), nameof(entityType1), nameof(index2), nameof(entityType2), nameof(table), nameof(indexName)),
+ index1, entityType1, index2, entityType2, table, indexName);
+
///
/// The keys {key1} on '{entityType1}' and {key2} on '{entityType2}' are both mapped to '{table}.{keyName}', but have different clustering configurations.
///
diff --git a/src/EFCore.SqlServer/Properties/SqlServerStrings.resx b/src/EFCore.SqlServer/Properties/SqlServerStrings.resx
index beb38d33c4e..59c92b4e2b0 100644
--- a/src/EFCore.SqlServer/Properties/SqlServerStrings.resx
+++ b/src/EFCore.SqlServer/Properties/SqlServerStrings.resx
@@ -156,6 +156,12 @@
The indexes {index1} on '{entityType1}' and {index2} on '{entityType2}' are both mapped to '{table}.{indexName}', but have different online configurations.
+
+ The indexes {index1} on '{entityType1}' and {index2} on '{entityType2}' are both mapped to '{table}.{indexName}', but have different sort in tempdb configurations.
+
+
+ The indexes {index1} on '{entityType1}' and {index2} on '{entityType2}' are both mapped to '{table}.{indexName}', but have different data compression configurations.
+
The keys {key1} on '{entityType1}' and {key2} on '{entityType2}' are both mapped to '{table}.{keyName}', but have different clustering configurations.
diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerJsonPostprocessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerJsonPostprocessor.cs
index b7499aa02a3..b7fdcb9111a 100644
--- a/src/EFCore.SqlServer/Query/Internal/SqlServerJsonPostprocessor.cs
+++ b/src/EFCore.SqlServer/Query/Internal/SqlServerJsonPostprocessor.cs
@@ -92,12 +92,9 @@ public virtual Expression Process(Expression expression)
table = table switch
{
- InnerJoinExpression ij => ij.Update(newOpenJsonExpression, ij.JoinPredicate),
- LeftJoinExpression lj => lj.Update(newOpenJsonExpression, lj.JoinPredicate),
- CrossJoinExpression cj => cj.Update(newOpenJsonExpression),
- CrossApplyExpression ca => ca.Update(newOpenJsonExpression),
- OuterApplyExpression oa => oa.Update(newOpenJsonExpression),
- _ => newOpenJsonExpression,
+ JoinExpressionBase j => j.Update(newOpenJsonExpression),
+ SqlServerOpenJsonExpression => newOpenJsonExpression,
+ _ => throw new UnreachableException()
};
foreach (var columnInfo in openJsonExpression.ColumnInfos!)
@@ -239,8 +236,10 @@ SqlExpression RewriteOpenJsonColumn(
columnExpression.Table, "value", columnExpression.Type, _nvarcharMaxTypeMapping, columnExpression.IsNullable);
Check.DebugAssert(columnInfo.Path is not null, "Path shouldn't be null in OPENJSON WITH");
- Check.DebugAssert(!columnInfo.AsJson, "AS JSON signifies an owned sub-entity being projected out of OPENJSON/WITH. "
- + "Columns referring to that must be wrapped be Json{Scalar,Query}Expression and will have been already dealt with above");
+ //Check.DebugAssert(
+ // !columnInfo.AsJson || columnInfo.TypeMapping.ElementTypeMapping is not null,
+ // "AS JSON signifies an owned sub-entity or array of primitives being projected out of OPENJSON/WITH. "
+ // + "Columns referring to sub-entities must be wrapped in Json{Scalar,Query}Expression and will have been already dealt with above");
if (columnInfo.Path is [])
{
diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs
index 73ec9a2759b..7a725559658 100644
--- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs
@@ -167,10 +167,7 @@ protected override Expression VisitExtension(Expression extensionExpression)
// which case we only have the CLR type (note that we cannot produce different SQLs based on the nullability of an *element* in
// a parameter collection - our caching mechanism only supports varying by the nullability of the parameter itself (i.e. the
// collection).
- // TODO: if property is non-null, GetElementType() should never be null, but we have #31469 for shadow properties
- var isElementNullable = property?.GetElementType() is null
- ? elementClrType.IsNullableType()
- : property.GetElementType()!.IsNullable;
+ var isElementNullable = property?.GetElementType()!.IsNullable;
#pragma warning disable EF1001 // Internal EF Core API usage.
var selectExpression = new SelectExpression(
@@ -245,7 +242,8 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr
{
Name = jsonPropertyName,
TypeMapping = property.GetRelationalTypeMapping(),
- Path = new PathSegment[] { new(jsonPropertyName) }
+ Path = new PathSegment[] { new(jsonPropertyName) },
+ AsJson = property.GetRelationalTypeMapping().ElementTypeMapping is not null
});
}
}
@@ -606,14 +604,14 @@ protected virtual SqlServerOpenJsonExpression ApplyTypeMappingsOnOpenJsonExpress
// First, find the collection type mapping and apply it to the parameter
if (_typeMappingSource.FindMapping(parameterExpression.Type, Model, elementTypeMapping) is not SqlServerStringTypeMapping
- parameterTypeMapping)
+ {
+ ElementTypeMapping: not null
+ }
+ parameterTypeMapping)
{
- // TODO: Message
- throw new InvalidOperationException("Type mapping for 'string' could not be found or was not a SqlServerStringTypeMapping");
+ throw new UnreachableException("A SqlServerStringTypeMapping collection type mapping could not be found");
}
- Check.DebugAssert(parameterTypeMapping.ElementTypeMapping != null, "Collection type mapping missing element mapping.");
-
return openJsonExpression.Update(
parameterExpression.ApplyTypeMapping(parameterTypeMapping),
path: null,
diff --git a/src/EFCore.SqlServer/README.md b/src/EFCore.SqlServer/README.md
new file mode 100644
index 00000000000..e1540d20a2b
--- /dev/null
+++ b/src/EFCore.SqlServer/README.md
@@ -0,0 +1,35 @@
+Microsoft.EntityFrameworkCore.SqlServer is the database provider for Microsoft SQL Server and Azure SQL. This providers allows you to use Entity Framework Core with Microsoft SQL Server and Azure SQL databases.
+
+## Getting started
+
+`Microsoft.EntityFrameworkCore.SqlServer` is the EF Core provider for Microsoft SQL Server and Azure SQL. See [Getting Started](https://learn.microsoft.com/ef/core/modeling/#use-fluent-api-to-configure-a-model) for more information.
+
+### Prerequisites
+
+- Supported database Engines: Microsoft SQL Server (2012 onwards)
+- The provider references Microsoft.Data.SqlClient (not System.Data.SqlClient). If your project takes a direct dependency on SqlClient, make sure it references the Microsoft.Data.SqlClient package.
+
+## Usage
+
+Once you've installed the package, you can use it in your Entity Framework Core application by specifying the SQL Server provider in your DbContext's OnConfiguring method:
+
+```csharp
+protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+{
+ optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;");
+}
+```
+
+In this example, we're using the (localdb)\mssqllocaldb server with the MyDatabase database. You'll need to adjust the connection string to match your own SQL Server instance and database.
+
+## Features
+
+The SQL Server provider supports all common features of [Entity Framework Core](https://learn.microsoft.com/ef/core/) as well as some [SQL Server-specific features](https://learn.microsoft.com/ef/core/providers/sql-server/?tabs=dotnet-core-cli) including temporal tables and memory-optimized tables.
+
+## Additional documentation
+
+For more information on using the SQL Server provider for Entity Framework Core, you can refer to the official [documentation](https://learn.microsoft.com/en-us/ef/core/providers/sql-server/?tabs=dotnet-core-cli).
+
+## Feedback
+
+If you encounter a bug or would like to request a feature, [submit an Github issue](https://github.com/dotnet/efcore/issues/new/choose). For more details, see [getting support](https://github.com/dotnet/efcore/blob/main/.github/SUPPORT.md).
\ No newline at end of file
diff --git a/src/EFCore.SqlServer/SqlServerRetryingExecutionStrategy.cs b/src/EFCore.SqlServer/SqlServerRetryingExecutionStrategy.cs
index b621c7be216..498be2db2b3 100644
--- a/src/EFCore.SqlServer/SqlServerRetryingExecutionStrategy.cs
+++ b/src/EFCore.SqlServer/SqlServerRetryingExecutionStrategy.cs
@@ -12,7 +12,7 @@ namespace Microsoft.EntityFrameworkCore;
///
///
///
-/// This strategy is specifically tailored to SQL Server (including SQL Azure). It is pre-configured with
+/// This strategy is specifically tailored to SQL Server (including Azure SQL). It is pre-configured with
/// error numbers for transient errors that can be retried. Additional error numbers to retry on can also be supplied.
///
///
@@ -30,6 +30,11 @@ public class SqlServerRetryingExecutionStrategy : ExecutionStrategy
{
private readonly HashSet? _additionalErrorNumbers;
+ ///
+ /// The default minimum time delay between retries for Azure SQL.
+ ///
+ protected static readonly TimeSpan DefaultMinDelayAzureSql = TimeSpan.FromSeconds(5);
+
///
/// Creates a new instance of .
///
@@ -138,6 +143,11 @@ public SqlServerRetryingExecutionStrategy(
_additionalErrorNumbers = errorNumbersToAdd?.ToHashSet();
}
+ ///
+ /// Additional SQL error numbers that should be considered transient.
+ ///
+ public virtual IEnumerable? AdditionalErrorNumbers => _additionalErrorNumbers;
+
///
/// Determines whether the specified exception represents a transient failure that can be
/// compensated by a retry. Additional exceptions to retry on can be passed to the constructor.
@@ -181,7 +191,9 @@ protected override bool ShouldRetryOn(Exception exception)
return CallOnWrappedException(lastException, IsMemoryOptimizedError)
? TimeSpan.FromMilliseconds(baseDelay.Value.TotalSeconds)
- : baseDelay;
+ : CallOnWrappedException(lastException, IsThrottlingError)
+ ? baseDelay + DefaultMinDelayAzureSql
+ : baseDelay;
}
private static bool IsMemoryOptimizedError(Exception exception)
@@ -204,4 +216,58 @@ private static bool IsMemoryOptimizedError(Exception exception)
return false;
}
+
+ private static bool IsThrottlingError(Exception exception)
+ {
+ if (exception is SqlException sqlException)
+ {
+ foreach (SqlError err in sqlException.Errors)
+ {
+ switch (err.Number)
+ {
+ case 49977:
+ case 49920:
+ case 49919:
+ case 49918:
+ case 45319:
+ case 45182:
+ case 45161:
+ case 45157:
+ case 45156:
+ case 41840:
+ case 41823:
+ case 40903:
+ case 40890:
+ case 40675:
+ case 40648:
+ case 40642:
+ case 40613:
+ case 40501:
+ case 40189:
+ case 39110:
+ case 39108:
+ case 37327:
+ case 30085:
+ case 25740:
+ case 25738:
+ case 22498:
+ case 22335:
+ case 17889:
+ case 14355:
+ case 10930:
+ case 10929:
+ case 9985:
+ case 3950:
+ case 3935:
+ case 1404:
+ case 1204:
+ case 233:
+ case -2:
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
}
diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerTransientExceptionDetector.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerTransientExceptionDetector.cs
index 92d26598bce..e41457194f3 100644
--- a/src/EFCore.SqlServer/Storage/Internal/SqlServerTransientExceptionDetector.cs
+++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerTransientExceptionDetector.cs
@@ -1,7 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Text.RegularExpressions;
using Microsoft.Data.SqlClient;
+using static System.Net.Mime.MediaTypeNames;
namespace Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal;
@@ -24,6 +26,12 @@ public static bool ShouldRetryOn(Exception? ex)
{
switch (err.Number)
{
+ // SQL Error Code: 49983
+ // The '%ls' operation failed to complete. Retry the operation. Create a support request if the retry attempts do not succeed.
+ case 49983:
+ // SQL Error Code: 49977
+ // The elastic pool '%ls' is busy with another operation. Please wait until the ongoing operation finishes and try again.
+ case 49977:
// SQL Error Code: 49920
// Cannot process request. Too many operations in progress for subscription "%ld".
// The service is busy processing multiple requests for this subscription.
@@ -39,11 +47,95 @@ public static bool ShouldRetryOn(Exception? ex)
case 49919:
// SQL Error Code: 49918
// Cannot process request. Not enough resources to process request.
- // The service is currently busy.Please retry the request later.
+ // The service is currently busy. Please retry the request later.
case 49918:
+ // SQL Error Code: 49802
+ // Database is unavailable at the moment, please retry connection at later time.
+ case 49802:
+ // SQL Error Code: 49510
+ // Managed instance is busy with another operation. Please try your operation later.
+ case 49510:
+ // SQL Error Code: 47139
+ // Join contained availability group '%.*ls' failed to create group master '%.*ls' Database ID. Please retry the operation again.
+ case 47139:
+ // SQL Error Code: 47137
+ // Cannot create contained system databases in contained availability group '%.*ls' It might be caused by
+ // temporary condition. Retry the operation.
+ case 47137:
+ // SQL Error Code: 47132
+ // Joining availability group '%.*ls' with rebuilding contained system DB has failed because rebuilding contained MSDB
+ // has failed. This is caused by contained MSDB is still used. Retry the operation later.
+ case 47132:
+ // SQL Error Code: 45547
+ // The create operation has timed out in one of the backend workflows. Please retry the operation.
+ case 45547:
+ // SQL Error Code: 45319
+ // The service objective assignment for database '%.*ls' on server '%.*ls' could not be completed as the database
+ // is too busy. Reduce the workload before initiating another service objective update.
+ case 45319:
+ // SQL Error Code: 45182
+ // Database '%ls' is busy with another operation. Please try your operation later.
+ case 45182:
+ // SQL Error Code: 45179
+ // The operation timed out and automatically rolled back. Please retry the operation.
+ case 45179:
+ // SQL Error Code: 45161
+ // Managed instance '%.*ls' is busy with another operation. Please try your operation later.
+ case 45161:
+ // SQL Error Code: 45157
+ // Server '%.*ls' is busy with another operation. Please try your operation later.
+ case 45157:
+ // SQL Error Code: 45156
+ // Subscription '%.*ls' is busy with another operation. Please try your operation later.
+ case 45156:
+ // SQL Error Code: 45153
+ // Management Service is not currently available. Please retry the operation later. If the problem persists,
+ // contact customer support, and provide them the session tracing ID of '%ls'.
+ case 45153:
+ // SQL Error Code: 42029
+ // An internal error happened while generating a new DBTS for database %.*ls. Please retry the operation.
+ case 42029:
+ // SQL Error Code: 41840
+ // Could not perform the operation because the elastic pool or managed instance has reached its quota for in-memory tables.
+ // This error may be transient. Please retry the operation. See 'http://go.microsoft.com/fwlink/?LinkID=623028' for more information.
+ case 41840:
// SQL Error Code: 41839
// Transaction exceeded the maximum number of commit dependencies.
case 41839:
+ // SQL Error Code: 41823
+ // Could not perform the operation because the database has reached its quota for in-memory tables. This error may be transient.
+ // Please retry the operation. See 'http://go.microsoft.com/fwlink/?LinkID=623028' for more information.
+ case 41823:
+ // SQL Error Code: 41701
+ // The Activation Context is unavailable at this time. The Windows Fabric Runtime is unavailable at this time,
+ // retry later. Wait for the activation context to become available, then retry.
+ case 41701:
+ // SQL Error Code: 41700
+ // System views related to Windows Fabric partitions and replicas are not available at this time,
+ // because replica manager has not yet started. Wait for replica manager to start, then retry the system view query.
+ case 41700:
+ // SQL Error Code: 41640
+ // Database '%ls' encountered a transient error (error code: 0x%08X) while performing task '%ls'.
+ // Refer to the SQL Server error log for information about the errors that were encountered.
+ // If this condition persists, contact the system administrator.
+ case 41640:
+ // SQL Error Code: 41619
+ // Windows Fabric '%ls' (partition ID '%ls')encountered transient error %d while waiting for build replica operation
+ // on database '%ls' (ID %d). Refer to the SQL Server error log for information about the errors that were encountered.
+ // If this condition persists, contact the system administrator.
+ case 41619:
+ // SQL Error Code: 41614
+ // Fabric Service '%ls' encountered a transient error while performing Windows Fabric operation on '%ls' database
+ // (ID %d). Refer to the SQL Server error log for information about the errors that were encountered.
+ // If this condition persists, contact the system administrator.
+ case 41614:
+ // SQL Error Code: 41383
+ // An internal error occurred while running the DMV query. This was likely caused by concurrent DDL operations. Please retry the query.
+ case 41383:
+ // SQL Error Code: 41339
+ // The table '%.*ls' has been created or altered after the start of the current transaction. The transaction was aborted.
+ // Please retry the transaction.
+ case 41339:
// SQL Error Code: 41325
// The current transaction failed to commit due to a serializable validation failure.
case 41325:
@@ -56,30 +148,274 @@ public static bool ShouldRetryOn(Exception? ex)
// SQL Error Code: 41301
// Dependency failure: a dependency was taken on another transaction that later failed to commit.
case 41301:
+ // SQL Error Code: 40938
+ // The Server DNS Alias '%.*ls' is busy with another operation and cannot perform the '%.*ls' operation. Please try again later.
+ case 40938:
+ // SQL Error Code: 40918
+ // The Failover Group '%.*ls' is busy with another operation and cannot perform the '%.*ls' operation. Please try again later
+ case 40918:
+ // SQL Error Code: 40903
+ // The server '%.*ls' is currently busy. Please wait a few minutes before trying again.
+ case 40903:
+ // SQL Error Code: 40890
+ // The elastic pool is busy with another operation.
+ case 40890:
+ // SQL Error Code: 40675
+ // The service is currently too busy. Please try again later.
+ case 40675:
+ // SQL Error Code: 40671
+ // Unable to '%.*ls' '%.*ls' on server '%.*ls'. Please retry the connection later.
+ case 40671:
+ // SQL Error Code: 40648
+ // Too many requests have been performed. Please retry later.
+ case 40648:
+ // SQL Error Code: 40642
+ // The server is currently too busy. Please try again later.
+ case 40642:
+ // SQL Error Code: 40623
+ // Reauthentication failed for login %.*ls. Within the past reauthentification interval, the login has become invalid
+ // due to a password change, a dropped login, or other cause. Please retry login.
+ case 40623:
// SQL Error Code: 40613
// Database XXXX on server YYYY is not currently available. Please retry the connection later.
// If the problem persists, contact customer support, and provide them the session tracing ID of ZZZZZ.
case 40613:
+ // SQL Error Code: 40540
+ // The service has encountered an error processing your request. Please try again.
+ case 40540:
// SQL Error Code: 40501
// The service is currently busy. Retry the request after 10 seconds. Code: (reason code to be decoded).
case 40501:
// SQL Error Code: 40197
// The service has encountered an error processing your request. Please try again.
case 40197:
+ // SQL Error Code: 40189
+ // The resource quota for the current database has been exceeded and this request has been aborted.
+ // Please rerun your request in the next quota window. %s
+ case 40189:
+ // SQL Error Code: 40143
+ // The service has encountered an error processing your request. Please try again.
+ case 40143:
+ // SQL Error Code: 40106
+ // The schema scope set in the session is not the current schema scope for the current partition. Please rerun your query.
+ case 40106:
+ // SQL Error Code: 39152
+ // Transient error communicating with the streaming runtime due to unfinished stop streaming job operation. Please retry the operation.
+ case 39152:
+ // SQL Error Code: 39151
+ // Transient error communicating with the streaming runtime. Please retry the operation.
+ case 39151:
+ // SQL Error Code: 39110
+ // Maximum number of concurrent external script queries for this user has been reached. Limit is %d.
+ // Please retry the operation. External script request id is %ls.
+ case 39110:
+ // SQL Error Code: 39108
+ // Maximum number of concurrent external script users has been reached. Limit is %d. Please retry the operation. External script request id is %ls.
+ case 39108:
+ // SQL Error Code: 39025
+ // External script execution failed as extensibility environment is not ready yet. Retry the operation when the server is fully started.
+ case 39025:
+ // SQL Error Code: 37327
+ // Maximum number of concurrent DBCC commands running in the enclave has been reached. The maximum number of
+ // concurrent DBCC queries is %d. Try rerunning the query.
+ case 37327:
+ // SQL Error Code: 37202
+ // An instance pool with name '%.*ls' is busy with another ongoing operation.
+ case 37202:
+ // SQL Error Code: 35293
+ // Error in retrieving extended recovery forks from the primary replica. The extended-recovery-fork stack changed
+ // while being retrieved by the secondary replica. Retry the operation.
+ case 35293:
+ // SQL Error Code: 35256
+ // The session timeout value was exceeded while waiting for a response from the other availability replica in the
+ // session. That replica or the network might be down, or the command might be misconfigured. If the partner is running
+ // and visible over the network, retry the command using correctly configured partner-connection parameters.
+ case 35256:
+ // SQL Error Code: 35218
+ // An error occurred while trying to set the initial Backup LSN of database '%.*ls'. Primary database is temporarily
+ // offline due to restart or other transient condition. Retry the operation.
+ case 35218:
+ // SQL Error Code: 35216
+ // An error occurred while adding or removing a log truncation holdup to build secondary replica from primary availability
+ // database '%.*ls'. Primary database is temporarily offline due to restart or other transient condition. Retry the operation.
+ case 35216:
+ // SQL Error Code: 33123
+ // Cannot drop or alter the database encryption key since it is currently in use on a mirror or secondary availability replica.
+ // Retry the command after all the previous reencryption scans have propagated to the mirror or secondary availability replicas
+ // or after availability relationship has been disabled.
+ case 33123:
+ // SQL Error Code: 30085
+ // A stoplist cache cannot be generated while processing a full-text query or performing full-text indexing. There is
+ // not enough memory to load the stoplist cache. Rerun the query or indexing command when more resources are available.
+ case 30085:
+ // SQL Error Code: 30080
+ // The full-text population on table '%ls' cannot be started because the full-text catalog is importing data from
+ // existing catalogs. After the import operation finishes, rerun the command.
+ case 30080:
+ // SQL Error Code: 25740
+ // Unable to start event session '%.*ls' because system is busy. Please try again later.
+ case 25740:
+ // SQL Error Code: 25738
+ // Event session '%.*ls' could not be started because system is currently busy. Please try again later.
+ case 25738:
+ // SQL Error Code: 25003
+ // Upgrade of the distribution database MSmerge_subscriptions table failed. Rerun the upgrade procedure in order
+ // to upgrade the distribution database.
+ case 25003:
+ // SQL Error Code: 22984
+ // An error occurred while waiting on the log reader history cache event. This error is reported by the internal task
+ // scheduling and might be transient. Retry the operation.
+ case 22984:
+ // SQL Error Code: 22760
+ // Aborting Synapse Link Publish task for partition %ld timed out. Retry this operation later.
+ case 22760:
+ // SQL Error Code: 22759
+ // Aborting Synapse Link Snapshot task for table %ld timed out. Retry this operation later.
+ case 22759:
+ // SQL Error Code: 22758
+ // Aborting Synapse Link Commit task for table group '%s' timed out. Retry this operation later.
+ case 22758:
+ // SQL Error Code: 22754
+ // Aborting Synapse Link Capture task for this database timed out. Retry this operation later.
+ case 22754:
+ // SQL Error Code: 22498
+ // There is not enough resources to perform the operation. Please retry your operation later.
+ case 22498:
+ // SQL Error Code: 22493
+ // The database '%.*ls' failed to sync. Please retry the operation again. If the problem persists contact
+ // Microsoft Azure Customer Support.
+ case 22493:
+ // SQL Error Code: 22491
+ // The DDL statement failed due to an internal error. Please retry the operation again. If the problem persists contact
+ // Microsoft Azure Customer Support.
+ case 22491:
+ // SQL Error Code: 22430
+ // Operation failed as the Database '%.*ls' is shutting down. Please retry the operation again. If the problem persists
+ // contact Microsoft Azure Customer Support.
+ case 22430:
+ // SQL Error Code: 22427
+ // Operation failed due to an error in a background task. Please retry the operation again. If the problem persists
+ // contact Microsoft Azure Customer Support.
+ case 22427:
+ // SQL Error Code: 22358
+ // The Database Controller required for this operation was not found. Please retry the operation again. If the problem
+ // persists contact Microsoft Azure Customer Support.
+ case 22358:
+ // SQL Error Code: 22355
+ // Lock manager does not exist. Please retry the operation again. If the problem persists contact
+ // Microsoft Azure Customer Support.
+ case 22355:
+ // SQL Error Code: 22353
+ // The SQL instances has not been correctly setup to allow this operation. Please retry the operation again.
+ // If the problem persists contact Microsoft Azure Customer Support.
+ case 22353:
+ // SQL Error Code: 22335
+ // Cannot obtain a LOCK resource at this time due to internal error. Rerun your statement when there are fewer active users.
+ case 22335:
+ // SQL Error Code: 22226
+ // An internal error (%d, %d) occured. Please retry the operation again. If the problem persists contact
+ // Microsoft Azure Customer Support.
+ case 22226:
+ // SQL Error Code: 22225
+ // An internal error (%d, %d) occured. Please retry the operation again. If the problem persists contact
+ // Microsoft Azure Customer Support.
+ case 22225:
+ // SQL Error Code: 21503
+ // Cleanup of merge meta data cannot be performed while merge processes are running. Retry this operation after
+ // the merge processes have completed.
+ case 21503:
// SQL Error Code: 20041
// Transaction rolled back. Could not execute trigger. Retry your transaction.
case 20041:
+ // SQL Error Code: 19494
+ // Automatic seeding of availability database '%ls' in availability group '%.*ls' failed with a transient error.
+ // The operation will be retried.
+ case 19494:
+ // SQL Error Code: 19416
+ // One or more databases in availability group '%.*ls' are not synchronized. On a synchronous-commit availability
+ // replica, ALTER AVAILABILITY GROUP OFFLINE is not allowed when one or more databases are not
+ // synchronized. Wait for all databases to reach the SYNCHRONIZED state, and retry the command.
+ case 19416:
+ // SQL Error Code: 19413
+ // An attempt to switch Always On Availability Groups to the local Windows Server Failover Clustering (WSFC) cluster
+ // context failed. This attempt failed because switching the cluster context back to the local cluster at this time
+ // might cause data loss because one or more secondary databases on synchronous-commit replicas are not in the
+ // SYNCHRONIZED state. Wait until all synchronous-commit secondary databases are synchronized, and then retry the
+ // ALTER SERVER CONFIGURATION SET HADR CLUSTER LOCAL command.
+ case 19413:
+ // SQL Error Code: 18858
+ // Could not read data from replication table '%s'. If retrying does not fix the issue, drop and reconfigure replication.
+ case 18858:
+ // SQL Error Code: 18401
+ // Login failed for user '%s'. Reason: Server is in script upgrade mode. Only administrator can connect at this time.
+ // Devnote: this can happen when SQL is going through recovery (e.g. after failover)
+ case 18401:
+ // SQL Error Code: 17889
+ // A new connection was rejected because the maximum number of connections on session ID %d has been reached.
+ // Close an existing connection on this session and retry.%.*ls
+ case 17889:
// SQL Error Code: 17197
// Login failed due to timeout; the connection has been closed. This error may indicate heavy server load.
// Reduce the load on the server and retry login.
case 17197:
+ // SQL Error Code: 17067
+ // SQL Server Assertion: File: <%s>, line = %d %s. This error may be timing-related. If the error persists after
+ // rerunning the statement, use DBCC CHECKDB to check the database for structural integrity, or restart the server
+ // to ensure in-memory data structures are not corrupted.
+ case 17067:
+ // SQL Error Code: 17066
+ // SQL Server Assertion: File: <%s>, line=%d Failed Assertion = '%s'. This error may be timing-related. If the error
+ // persists after rerunning the statement, use DBCC CHECKDB to check the database for structural integrity, or restart
+ // the server to ensure in-memory data structures are not corrupted.
+ case 17066:
+ // SQL Error Code: 17065
+ // SQL Server Assertion: File: <%s>, line = %d Failed Assertion = '%s' %s. This error may be timing-related.
+ // If the error persists after rerunning the statement, use DBCC CHECKDB to check the database for structural integrity,
+ // or restart the server to ensure in-memory data structures are not corrupted.
+ case 17065:
+ // SQL Error Code: 16555
+ // Operation failed due to an error while processing rejected rows. Intermediate results, if any, should be discarded
+ // as such results may not be complete. Please retry the operation. If the problem persists, contact
+ // Microsoft Azure Customer Support.
+ case 16555:
+ // SQL Error Code: 16554
+ // Operation failed due to an error in a background task. Please retry the operation again. If the problem persists
+ // contact Microsoft Azure Customer Support.
+ case 16554:
+ // SQL Error Code: 16528
+ // Operation '%ls %ls' failed. Retry the operation later.
+ case 16528:
+ // SQL Error Code: 14906
+ // The database '%s' is not accessible. Ensure that the remote database exists. If you believe that your database should
+ // be accessible please retry the command.
+ case 14906:
+ // SQL Error Code: 14868
+ // Inbound migration is in progress or paused. Migration direction outbound cannot be set at this time. Please retry
+ // after inbound migration is complete.
+ case 14868:
+ // SQL Error Code: 14817
+ // The server '%s' is not accessible. Ensure that the remote server exists and the Azure SQL DB Firewall Rules permit
+ // access to the server. If you believe that your server should be accessible please retry the command.
+ case 14817:
// SQL Error Code: 14355
// The MSSQLServerADHelper service is busy. Retry this operation later.
case 14355:
+ // SQL Error Code: 11539
+ // One of the types specified in WITH RESULT SETS clause has been modified after the EXECUTE statement started running.
+ // Please rerun the statement.
+ case 11539:
+ // SQL Error Code: 11001
+ // An error has occurred while establishing a connection to the server. When connecting to SQL Server,
+ // this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections.
+ // (provider: TCP Provider, error: 0 - No such host is known.) (.Net SqlClient Data Provider)
+ case 11001:
// SQL Error Code: 10936
// Resource ID : %d. The request limit for the elastic pool is %d and has been reached.
// See 'https://go.microsoft.com/fwlink/?LinkId=267637' for assistance.
case 10936:
+ // SQL Error Code: 10930
+ // The service is currently too busy. Please try again later.
+ case 10930:
// SQL Error Code: 10929
// Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d and the current usage for the database is %d.
// However, the server is currently too busy to support requests greater than %d for this database.
@@ -107,9 +443,15 @@ public static bool ShouldRetryOn(Exception? ex)
// A transport-level error has occurred when receiving results from the server.
// An established connection was aborted by the software in your host machine.
case 10053:
+ // SQL Error Code: 9985
+ // There is not enough memory to generate a search property list cache. Rerun your full-text indexing statement when more resources are available.
+ case 9985:
// SQL Error Code: 9515
// An XML schema has been altered or dropped, and the query plan is no longer valid. Please rerun the query batch.
case 9515:
+ // SQL Error Code: 9020
+ // The log for database '%ls' failed to grow while shrink in progress. Please retry.
+ case 9020:
// SQL Error Code: 8651
// Could not perform the operation because the requested memory grant was not available in resource pool '%ls' (%ld).
// Rerun the query, reduce the query load, or check resource governor configuration setting.
@@ -120,12 +462,42 @@ public static bool ShouldRetryOn(Exception? ex)
// SQL Error Code: 8628
// A time out occurred while waiting to optimize the query. Rerun the query.
case 8628:
+ // SQL Error Code: 7951
+ // Warning: Could not complete filestream consistency checks due to an operating system error. Any consistency errors
+ // found in the filestream subsystem will be silenced. Please refer to other errors for more information.
+ // This condition is likely transient; try rerunning the command.
+ case 7951:
+ // SQL Error Code: 6292
+ // The transaction that is associated with this operation has been committed or rolled back. Retry with a different transaction.
+ case 6292:
+ // SQL Error Code: 5529
+ // Failed to remove a FILESTREAM file. The database is a primary database in an availability group. Wait for the
+ // FILESTREAM data files to be hardened on every secondary availability replica. Then retry the drop file operation.
+ case 5529:
+ // SQL Error Code: 5280
+ // An unexpected protocol element was recevied during the execution of a consistency check command. Retry the operation.
+ case 5280:
// SQL Error Code: 4221
// Login to read-secondary failed due to long wait on 'HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING'.
// The replica is not available for login because row versions are missing for transactions that were in-flight
// when the replica was recycled. The issue can be resolved by rolling back or committing the active transactions
// on the primary replica. Occurrences of this condition can be minimized by avoiding long write transactions on the primary.
case 4221:
+ // SQL Error Code: 3980
+ // The request failed to run because the batch is aborted, this can be caused by abort signal sent from client,
+ // or another request is running in the same session, which makes the session busy.
+ case 3980:
+ // SQL Error Code: 4184
+ // Cannot retrieve table data for the query operation because the table ""%.*ls"" schema is being altered too frequently.
+ // Because the table ""%.*ls"" contains a filtered index or filtered statistics, changes to the table schema require
+ // a refresh of all table data. Retry the query operation, and if the problem persists, use SQL Server Profiler to identify
+ // what schema-altering operations are occurring.
+ case 4184:
+ // SQL Error Code: 4117
+ // Cannot retrieve table data for the query operation because the table ""%.*ls"" schema is being altered too frequently.
+ // Because the table ""%.*ls"" contains a computed column, changes to the table schema require a refresh of all table data.
+ // Retry the query operation, and if the problem persists, use SQL Server Profiler to identify what schema-altering operations are occurring.
+ case 4117:
// SQL Error Code: 4060
// Cannot open database "%.*ls" requested by the login. The login failed.
case 4060:
@@ -139,16 +511,99 @@ public static bool ShouldRetryOn(Exception? ex)
// directly or indirectly in database '%.*ls' to update, delete, or insert the row that has been modified or deleted
// by another transaction. Retry the transaction or change the isolation level for the update/delete statement.
case 3960:
+ // SQL Error Code: 3957
+ // Snapshot isolation transaction failed in database '%.*ls' because the database did not allow snapshot isolation when
+ // the current transaction started. It may help to retry the transaction.
+ case 3957:
+ // SQL Error Code: 3953
+ // Snapshot isolation transaction failed in database '%.*ls' because the database was not recovered when the current
+ // transaction was started. Retry the transaction after the database has recovered.
+ case 3953:
+ // SQL Error Code: 3950
+ // Version store scan timed out when attempting to read the next row. Please try the statement again later when the system is not as busy.
+ case 3950:
+ // SQL Error Code: 3948
+ // The transaction was terminated because of the availability replica config/state change or because ghost records
+ // are being deleted on the primary and the secondary availability replica that might be needed by queries running under
+ // snapshot isolation. Retry the transaction.
+ case 3948:
+ // SQL Error Code: 3947
+ // The transaction was aborted because the secondary compute failed to catch up redo. Retry the transaction.
+ case 3947:
+ // SQL Error Code: 3941
+ // The transaction cannot modify an object that is published for replication or has Change Data Capture enabled
+ // because the transaction started before replication or Change Data Capture was enabled on the database. Retry the transaction.
+ case 3941:
// SQL Error Code: 3935
// A FILESTREAM transaction context could not be initialized. This might be caused by a resource shortage. Retry the operation.
case 3935:
+ // SQL Error Code: 3635
+ // An error occurred while processing '%ls' metadata for database id %d, file id %d, and transaction='%.*ls'.
+ // Additional Context='%ls'. Location='%hs'(%d). Retry the operation; if the problem persists,
+ // contact the database administrator to review locking and memory configurations.
+ // Review the application for possible deadlock conflicts.
+ case 3635:
+ // SQL Error Code: 3429
+ // Recovery could not determine the outcome of a cross-database transaction %S_XID, named '%.*ls',
+ // in database '%.*ls' (database ID %d:%d). The coordinating database (database ID %d:%d) was unavailable.
+ // The transaction was assumed to be committed. If the transaction was not committed, you can retry recovery
+ // when the coordinating database is available.
+ case 3429:
+ // SQL Error Code: 2816
+ // The metadata for object with id %d has changed. Retry the statement.
+ case 2816:
+ // SQL Error Code: 2021
+ // The referenced entity '%.*ls' was modified during DDL execution. Please retry the operation.
+ case 2021:
// SQL Error Code: 1807
// Could not obtain exclusive lock on database 'model'. Retry the operation later.
case 1807:
+ // SQL Error Code: 1535
+ // Cannot share extent %S_PGID. Shared extent directory is full. Retry the transaction. If the problem persists, contact Technical Support.
+ case 1535:
+ // SQL Error Code: 1534
+ // Extent %S_PGID not found in shared extent directory. Retry the transaction. If the problem persists, contact Technical Support.
+ case 1534:
+ // SQL Error Code: 1533
+ // Cannot share extent %S_PGID. The correct extents could not be identified. Retry the transaction.
+ case 1533:
+ // SQL Error Code: 1532
+ // New sort run starting on page %S_PGID found an extent not marked as shared. Retry the transaction.
+ // If the problem persists, contact Technical Support.
+ case 1532:
+ // SQL Error Code: 1438
+ // The server instance %ls rejected configure request; read its error log file for more information.
+ // The reason %u, and state %u, can be of use for diagnostics by Microsoft.
+ // This is a transient error hence retrying the request is likely to succeed. Correct the cause if any and retry.
+ case 1438:
+ // SQL Error Code: 1421
+ // Communications to the remote server instance '%.*ls' failed to complete before its timeout.
+ // The ALTER DATABASE command may have not completed. Retry the command.
+ case 1421:
+ // SQL Error Code: 1413
+ // Communications to the remote server instance '%.*ls' failed before database mirroring was fully started.
+ // The ALTER DATABASE command failed. Retry the command when the remote database is started.
+ case 1413:
+ // SQL Error Code: 1404
+ // The command failed because the database mirror is busy. Reissue the command later.
+ case 1404:
+ // SQL Error Code: 1232
+ // Failed to acquire lock with lock manager service, it could be due to many reasons including transient service failure.
+ case 1232:
+ // SQL Error Code: 1222
+ // Lock request time out period exceeded.
+ case 1222:
// SQL Error Code: 1221
// The Database Engine is attempting to release a group of locks that are not currently held by the transaction.
// Retry the transaction. If the problem persists, contact your support provider.
case 1221:
+ // SQL Error Code: 1216
+ // The DDL statement with ABORT_AFTER_WAIT = BLOCKERS option cannot be completed due to a conflicting system task. The request can abort only user transactions. Please wait for the system task to complete and retry.
+ case 1216:
+ // SQL Error Code: 1215
+ // A conflicting ABORT_AFTER_WAIT = BLOCKERS request is waiting for existing transactions to rollback.
+ // This request cannot be executed. Please retry when the previous request is completed.
+ case 1215:
// SQL Error Code: 1205
// Deadlock
case 1205:
@@ -165,6 +620,26 @@ public static bool ShouldRetryOn(Exception? ex)
// A connection was successfully established with the server, but then an error occurred during the login process.
// (provider: Named Pipes Provider, error: 0 - Overlapped I/O operation is in progress)
case 997:
+ // SQL Error Code: 988
+ // Unable to access database '%.*ls' because it lacks a quorum of nodes for high availability. Try the operation again later.
+ case 988:
+ // SQL Error Code: 982
+ // Unable to access the '%.*ls' database because no online secondary replicas are enabled for read-only access.
+ // Check the availability group configuration to verify that at least one secondary replica is configured for read-only access.
+ // Wait for an enabled replica to come online, and retry your read-only operation.
+ case 982:
+ // SQL Error Code: 952
+ // Database '%.*ls' is in transition. Try the statement later.
+ case 952:
+ // SQL Error Code: 941
+ // Database '%.*ls' cannot be opened because it is not started. Retry when the database is started.
+ case 941:
+ // SQL Error Code: 927
+ // Database '%.*ls' cannot be opened. It is in the middle of a restore.
+ case 927:
+ // SQL Error Code: 926
+ // Database '%.*ls' cannot be opened. It has been marked SUSPECT by recovery. See the SQL Server errorlog for more information.
+ case 926:
// SQL Error Code: 921
// Database '%.*ls' has not been recovered yet. Wait and try again.
case 921:
@@ -175,9 +650,15 @@ public static bool ShouldRetryOn(Exception? ex)
// Descriptor for object ID %ld in database ID %d not found in the hash table during attempt to un-hash it.
// A work table is missing an entry. Rerun the query. If a cursor is involved, close and reopen the cursor.
case 617:
+ // SQL Error Code: 615
+ // Could not find database ID %d, name '%.*ls'. The database may be offline. Wait a few minutes and try again.
+ case 615:
// SQL Error Code: 601
// Could not continue scan with NOLOCK due to data movement.
case 601:
+ // SQL Error Code: 539
+ // Schema changed after the target table was created. Rerun the Select Into query.
+ case 539:
// SQL Error Code: 233
// The client was unable to establish a connection because of an error during connection initialization process before login.
// Possible causes include the following: the client tried to connect to an unsupported version of SQL Server;
diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs
index d9362c84df3..f05557997c9 100644
--- a/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs
+++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs
@@ -220,8 +220,7 @@ static SqlServerTypeMappingSource()
///
public SqlServerTypeMappingSource(
TypeMappingSourceDependencies dependencies,
- RelationalTypeMappingSourceDependencies relationalDependencies,
- ISqlServerSingletonOptions sqlServerSingletonOptions)
+ RelationalTypeMappingSourceDependencies relationalDependencies)
: base(dependencies, relationalDependencies)
{
}
@@ -234,7 +233,7 @@ public SqlServerTypeMappingSource(
///
protected override RelationalTypeMapping? FindMapping(in RelationalTypeMappingInfo mappingInfo)
=> base.FindMapping(mappingInfo)
- ?? FindRawMapping(mappingInfo)?.Clone(mappingInfo);
+ ?? FindRawMapping(mappingInfo)?.WithTypeMappingInfo(mappingInfo);
private RelationalTypeMapping? FindRawMapping(RelationalTypeMappingInfo mappingInfo)
{
@@ -350,20 +349,23 @@ public SqlServerTypeMappingSource(
return Rowversion;
}
- var isFixedLength = mappingInfo.IsFixedLength == true;
-
- var size = mappingInfo.Size ?? (mappingInfo.IsKeyOrIndex ? 900 : null);
- if (size is < 0 or > 8000)
+ if (mappingInfo.ElementTypeMapping == null)
{
- size = isFixedLength ? 8000 : null;
- }
+ var isFixedLength = mappingInfo.IsFixedLength == true;
- return size == null
- ? VariableLengthMaxBinary
- : new SqlServerByteArrayTypeMapping(
- size: size,
- fixedLength: isFixedLength,
- storeTypePostfix: storeTypeName == null ? StoreTypePostfix.Size : StoreTypePostfix.None);
+ var size = mappingInfo.Size ?? (mappingInfo.IsKeyOrIndex ? 900 : null);
+ if (size is < 0 or > 8000)
+ {
+ size = isFixedLength ? 8000 : null;
+ }
+
+ return size == null
+ ? VariableLengthMaxBinary
+ : new SqlServerByteArrayTypeMapping(
+ size: size,
+ fixedLength: isFixedLength,
+ storeTypePostfix: storeTypeName == null ? StoreTypePostfix.Size : StoreTypePostfix.None);
+ }
}
}
diff --git a/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs b/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs
index 49d230adbfc..9cef4d8619d 100644
--- a/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs
+++ b/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs
@@ -152,8 +152,7 @@ protected override void AppendUpdateColumnValue(
stringBuilder.Append(columnModification.JsonPath);
stringBuilder.Append("', ");
- if (columnModification.Property != null
- && columnModification.Property.GetTypeMapping().ElementTypeMapping == null)
+ if (columnModification.Property is { IsPrimitiveCollection: false })
{
base.AppendUpdateColumnValue(updateSqlGeneratorHelper, columnModification, stringBuilder, name, schema);
}
diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteComplexTypePrimitiveCollectionBuilderExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteComplexTypePrimitiveCollectionBuilderExtensions.cs
deleted file mode 100644
index 19fd5c79297..00000000000
--- a/src/EFCore.Sqlite.Core/Extensions/SqliteComplexTypePrimitiveCollectionBuilderExtensions.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore;
-
-///
-/// SQLite-specific extension methods for .
-///
-///
-/// See Modeling entity types and relationships, and
-/// Accessing SQLite databases with EF Core for more information and examples.
-///
-public static class SqliteComplexTypePrimitiveCollectionBuilderExtensions
-{
- ///
- /// Configures the SRID of the column that the property maps to when targeting SQLite.
- ///
- ///
- /// See Spatial data, and
- /// Accessing SQLite databases with EF Core for more information and examples.
- ///
- /// The builder for the property being configured.
- /// The SRID.
- /// The same builder instance so that multiple calls can be chained.
- public static ComplexTypePrimitiveCollectionBuilder HasSrid(
- this ComplexTypePrimitiveCollectionBuilder primitiveCollectionBuilder,
- int srid)
- {
- primitiveCollectionBuilder.Metadata.SetSrid(srid);
-
- return primitiveCollectionBuilder;
- }
-
- ///
- /// Configures the SRID of the column that the property maps to when targeting SQLite.
- ///
- ///
- /// See Spatial data, and
- /// Accessing SQLite databases with EF Core for more information and examples.
- ///
- /// The builder for the property being configured.
- /// The SRID.
- /// The same builder instance so that multiple calls can be chained.
- public static ComplexTypePrimitiveCollectionBuilder HasSrid(
- this ComplexTypePrimitiveCollectionBuilder primitiveCollectionBuilder,
- int srid)
- => (ComplexTypePrimitiveCollectionBuilder)HasSrid(
- (ComplexTypePrimitiveCollectionBuilder)primitiveCollectionBuilder, srid);
-}
diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteDbFunctionsExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteDbFunctionsExtensions.cs
index 585a0936030..f52da2ec8f4 100644
--- a/src/EFCore.Sqlite.Core/Extensions/SqliteDbFunctionsExtensions.cs
+++ b/src/EFCore.Sqlite.Core/Extensions/SqliteDbFunctionsExtensions.cs
@@ -43,6 +43,33 @@ public static bool Glob(this DbFunctions _, string matchExpression, string patte
public static string Hex(this DbFunctions _, byte[] bytes)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(Hex)));
+ ///
+ /// Maps to the SQLite unhex function which returns a BLOB representing decoding of the hexadecimal string.
+ ///
+ ///
+ /// See Database functions, and
+ /// Accessing SQLite databases with EF Core for more information and examples.
+ ///
+ /// The instance.
+ /// The hexadecimal string.
+ /// Decoded hexadecimal string as binary value.
+ public static byte[] Unhex(this DbFunctions _, string value)
+ => throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(Unhex)));
+
+ ///
+ /// Maps to the SQLite unhex function which returns a BLOB representing decoding of the hexadecimal string.
+ ///
+ ///
+ /// See Database functions, and
+ /// Accessing SQLite databases with EF Core for more information and examples.
+ ///
+ /// The instance.
+ /// The hexadecimal string.
+ /// Characters that are ignored in .
+ /// Decoded hexadecimal string as binary value.
+ public static byte[] Unhex(this DbFunctions _, string value, string ignoreChars)
+ => throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(Unhex)));
+
///
/// Maps to the SQLite substr function which returns a subarray of the specified value. The subarray starts
/// at and continues to the end of the value.
diff --git a/src/EFCore.Sqlite.Core/Extensions/SqlitePrimitiveCollectionBuilderExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqlitePrimitiveCollectionBuilderExtensions.cs
deleted file mode 100644
index 0a675c038ff..00000000000
--- a/src/EFCore.Sqlite.Core/Extensions/SqlitePrimitiveCollectionBuilderExtensions.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore;
-
-///
-/// SQLite-specific extension methods for .
-///
-///
-/// See Modeling entity types and relationships, and
-/// Accessing SQLite databases with EF Core for more information and examples.
-///
-public static class SqlitePrimitiveCollectionBuilderExtensions
-{
- ///
- /// Configures the SRID of the column that the property maps to when targeting SQLite.
- ///
- ///
- /// See Spatial data, and
- /// Accessing SQLite databases with EF Core for more information and examples.
- ///
- /// The builder for the property being configured.
- /// The SRID.
- /// The same builder instance so that multiple calls can be chained.
- public static PrimitiveCollectionBuilder HasSrid(this PrimitiveCollectionBuilder primitiveCollectionBuilder, int srid)
- {
- primitiveCollectionBuilder.Metadata.SetSrid(srid);
-
- return primitiveCollectionBuilder;
- }
-
- ///
- /// Configures the SRID of the column that the property maps to when targeting SQLite.
- ///
- ///
- /// See Spatial data, and
- /// Accessing SQLite databases with EF Core for more information and examples.
- ///
- /// The builder for the property being configured.
- /// The SRID.
- /// The same builder instance so that multiple calls can be chained.
- public static PrimitiveCollectionBuilder HasSrid(
- this PrimitiveCollectionBuilder primitiveCollectionBuilder,
- int srid)
- => (PrimitiveCollectionBuilder)HasSrid((PrimitiveCollectionBuilder)primitiveCollectionBuilder, srid);
-}
diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteHexMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteHexMethodTranslator.cs
index 68e759f7a85..ede730114ed 100644
--- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteHexMethodTranslator.cs
+++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteHexMethodTranslator.cs
@@ -13,9 +13,15 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal;
///
public class SqliteHexMethodTranslator : IMethodCallTranslator
{
- private static readonly MethodInfo MethodInfo = typeof(SqliteDbFunctionsExtensions)
+ private static readonly MethodInfo HexMethodInfo = typeof(SqliteDbFunctionsExtensions)
.GetMethod(nameof(SqliteDbFunctionsExtensions.Hex), new[] { typeof(DbFunctions), typeof(byte[]) })!;
+ private static readonly MethodInfo UnhexMethodInfo = typeof(SqliteDbFunctionsExtensions)
+ .GetMethod(nameof(SqliteDbFunctionsExtensions.Unhex), new[] { typeof(DbFunctions), typeof(string) })!;
+
+ private static readonly MethodInfo UnhexWithIgnoreCharsMethodInfo = typeof(SqliteDbFunctionsExtensions)
+ .GetMethod(nameof(SqliteDbFunctionsExtensions.Unhex), new[] { typeof(DbFunctions), typeof(string), typeof(string) })!;
+
private readonly ISqlExpressionFactory _sqlExpressionFactory;
///
@@ -41,7 +47,7 @@ public SqliteHexMethodTranslator(ISqlExpressionFactory sqlExpressionFactory)
IReadOnlyList arguments,
IDiagnosticsLogger logger)
{
- if (method.Equals(MethodInfo))
+ if (method.Equals(HexMethodInfo))
{
return _sqlExpressionFactory.Function(
"hex",
@@ -51,6 +57,17 @@ public SqliteHexMethodTranslator(ISqlExpressionFactory sqlExpressionFactory)
typeof(string));
}
+ if (method.Equals(UnhexMethodInfo)
+ || method.Equals(UnhexWithIgnoreCharsMethodInfo))
+ {
+ return _sqlExpressionFactory.Function(
+ "unhex",
+ arguments.Skip(1),
+ nullable: true,
+ arguments.Skip(1).Select(_ => true).ToArray(),
+ typeof(byte[]));
+ }
+
return null;
}
}
diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs
index 656d144b856..4e3d4fd6ffa 100644
--- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs
+++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs
@@ -313,6 +313,27 @@ protected override Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpressio
{
switch (sqlUnaryExpression.OperatorType)
{
+ case ExpressionType.Convert:
+ if (sqlUnaryExpression.Operand.Type == typeof(char)
+ && sqlUnaryExpression.Type.IsInteger())
+ {
+ Sql.Append("unicode(");
+ Visit(sqlUnaryExpression.Operand);
+ Sql.Append(")");
+
+ return sqlUnaryExpression;
+ }
+ else if (sqlUnaryExpression.Operand.Type.IsInteger()
+ && sqlUnaryExpression.Type == typeof(char))
+ {
+ Sql.Append("char(");
+ Visit(sqlUnaryExpression.Operand);
+ Sql.Append(")");
+
+ return sqlUnaryExpression;
+ }
+ goto default;
+
case ExpressionType.Not when sqlUnaryExpression.Type == typeof(bool):
switch (sqlUnaryExpression.Operand)
{
diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs
index 807a17034b5..fae33b1871c 100644
--- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs
@@ -223,10 +223,7 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis
// which case we only have the CLR type (note that we cannot produce different SQLs based on the nullability of an *element* in
// a parameter collection - our caching mechanism only supports varying by the nullability of the parameter itself (i.e. the
// collection).
- // TODO: if property is non-null, GetElementType() should never be null, but we have #31469 for shadow properties
- var isElementNullable = property?.GetElementType() is null
- ? elementClrType.IsNullableType()
- : property.GetElementType()!.IsNullable;
+ var isElementNullable = property?.GetElementType()!.IsNullable;
#pragma warning disable EF1001 // Internal EF Core API usage.
var selectExpression = new SelectExpression(
diff --git a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs
index f4c85a07c64..fce854a835e 100644
--- a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs
+++ b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteTypeMappingSource.cs
@@ -129,13 +129,18 @@ public static bool IsSpatialiteType(string columnType)
return mapping != null
&& mappingInfo.StoreTypeName != null
- ? mapping.Clone(mappingInfo.StoreTypeName, null)
+ ? mapping.WithStoreTypeAndSize(mappingInfo.StoreTypeName, null)
: mapping;
}
private RelationalTypeMapping? FindRawMapping(RelationalTypeMappingInfo mappingInfo)
{
var clrType = mappingInfo.ClrType;
+ if (clrType == typeof(byte[]) && mappingInfo.ElementTypeMapping != null)
+ {
+ return null;
+ }
+
if (clrType != null
&& _clrTypeMappings.TryGetValue(clrType, out var mapping))
{
diff --git a/src/EFCore.Sqlite.Core/Update/Internal/SqliteUpdateSqlGenerator.cs b/src/EFCore.Sqlite.Core/Update/Internal/SqliteUpdateSqlGenerator.cs
index d5a51861e72..626a9a0ce68 100644
--- a/src/EFCore.Sqlite.Core/Update/Internal/SqliteUpdateSqlGenerator.cs
+++ b/src/EFCore.Sqlite.Core/Update/Internal/SqliteUpdateSqlGenerator.cs
@@ -159,8 +159,7 @@ protected override void AppendUpdateColumnValue(
stringBuilder.Append(columnModification.JsonPath);
stringBuilder.Append("', ");
- if (columnModification.Property != null
- && columnModification.Property.GetTypeMapping().ElementTypeMapping == null)
+ if (columnModification.Property is { IsPrimitiveCollection: false })
{
var providerClrType = (columnModification.Property.GetTypeMapping().Converter?.ProviderClrType
?? columnModification.Property.ClrType).UnwrapNullableType();
diff --git a/src/EFCore.Sqlite/EFCore.Sqlite.csproj b/src/EFCore.Sqlite/EFCore.Sqlite.csproj
index b7abc5d9684..f728029ae0c 100644
--- a/src/EFCore.Sqlite/EFCore.Sqlite.csproj
+++ b/src/EFCore.Sqlite/EFCore.Sqlite.csproj
@@ -47,7 +47,7 @@
-
+
diff --git a/src/EFCore.Tools/README.md b/src/EFCore.Tools/README.md
new file mode 100644
index 00000000000..a82cd1c5ef2
--- /dev/null
+++ b/src/EFCore.Tools/README.md
@@ -0,0 +1,41 @@
+The Entity Framework Core tools help with design-time development tasks. They're primarily used to manage Migrations and to scaffold a DbContext and entity types by reverse engineering the schema of a database.
+Microsoft.EntityFrameworkCore.Tools is for PowerShell tooling that works in the Visual Studio Package Manager Console.
+
+## Getting started
+
+The Package Manager Console (PMC) tools for Entity Framework Core perform design-time development tasks. For example, they create migrations, apply migrations, and generate code for a model based on an existing database. The commands run inside of Visual Studio using the Package Manager Console. These tools work with both .NET Framework and .NET Core projects.
+
+### Prerequisites
+
+Before using the tools:
+
+- [Understand the difference between target and startup project](https://learn.microsoft.com/en-us/ef/core/cli/powershell#target-and-startup-project).
+- [Learn how to use the tools with .NET Standard class libraries](https://learn.microsoft.com/en-us/ef/core/cli/powershell#other-target-frameworks).
+- [For ASP.NET Core projects, set the environment](https://learn.microsoft.com/en-us/ef/core/cli/powershell#aspnet-core-environment).
+
+## Usage
+
+PMC Command | Usage
+-- | --
+Get-Help entityframework |Displays information about entity framework commands.
+[Add-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#add-migration) | Creates a migration by adding a migration snapshot.
+[Bundle-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#bundle-migration) | Creates an executable to update the database.
+[Get-DbContext](https://learn.microsoft.com/en-us/ef/core/cli/powershell#get-dbcontext) | Gets information about a DbContext type.
+[Drop-Database](https://learn.microsoft.com/en-us/ef/core/cli/powershell#drop-database) | Drops the database.
+[Get-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#get-migration) | Lists available migrations.
+[Optimize-DbContext](https://learn.microsoft.com/en-us/ef/core/cli/powershell#optimize-dbcontext) | Generates a compiled version of the model used by the `DbContext`.
+[Remove-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#remove-migration) | Removes the last migration snapshot.
+[Scaffold-DbContext](https://learn.microsoft.com/en-us/ef/core/cli/powershell#scaffold-dbcontext) | Generates a DbContext and entity type classes for a specified database. This is called reverse engineering.
+[Script-DbContext](https://learn.microsoft.com/en-us/ef/core/cli/powershell#script-dbcontext) | Generates a SQL script from the DbContext. Bypasses any migrations.
+[Script-Migration](https://learn.microsoft.com/en-us/ef/core/cli/powershell#script-migration) | Generates a SQL script using all the migration snapshots.
+[Update-Database](https://learn.microsoft.com/en-us/ef/core/cli/powershell#update-database) | Updates the database schema based on the last migration snapshot.
+
+## Additional documentation
+
+- [Migrations](https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/)
+- [Reverse Engineering](https://learn.microsoft.com/en-us/ef/core/managing-schemas/scaffolding/?tabs=dotnet-core-cli)
+- [Compiled models](https://learn.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-di%2Cwith-constant#compiled-models)
+
+## Feedback
+
+If you encounter a bug or issues with this package,you can [open an Github issue](https://github.com/dotnet/efcore/issues/new/choose). For more details, see [getting support](https://github.com/dotnet/efcore/blob/main/.github/SUPPORT.md).
\ No newline at end of file
diff --git a/src/EFCore/ChangeTracking/Internal/ArrayPropertyValues.cs b/src/EFCore/ChangeTracking/Internal/ArrayPropertyValues.cs
index c8c54fcc2d6..9ee9cc38daa 100644
--- a/src/EFCore/ChangeTracking/Internal/ArrayPropertyValues.cs
+++ b/src/EFCore/ChangeTracking/Internal/ArrayPropertyValues.cs
@@ -56,7 +56,7 @@ public override void SetValues(object obj)
{
if (!Properties[i].IsShadowProperty())
{
- SetValue(i, Properties[i].GetGetter().GetClrValue(obj));
+ SetValue(i, Properties[i].GetGetter().GetClrValueUsingContainingEntity(obj));
}
}
}
diff --git a/src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs b/src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs
index 0ee834c9b62..927f2e1c678 100644
--- a/src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs
+++ b/src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs
@@ -49,7 +49,7 @@ public override void SetValues(object obj)
{
foreach (var property in Properties.Where(p => !p.IsShadowProperty()))
{
- SetValueInternal(property, property.GetGetter().GetClrValue(obj));
+ SetValueInternal(property, property.GetGetter().GetClrValueUsingContainingEntity(obj));
}
}
else
diff --git a/src/EFCore/ChangeTracking/Internal/IInternalEntry.cs b/src/EFCore/ChangeTracking/Internal/IInternalEntry.cs
index bd973bb81df..69944659dc7 100644
--- a/src/EFCore/ChangeTracking/Internal/IInternalEntry.cs
+++ b/src/EFCore/ChangeTracking/Internal/IInternalEntry.cs
@@ -1,322 +1,322 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
-
-namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
-
-///
-/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
-/// the same compatibility standards as public APIs. It may be changed or removed without notice in
-/// any release. You should only use it directly in your code with extreme caution and knowing that
-/// doing so can result in application failures when updating to a new Entity Framework Core release.
-///
-public interface IInternalEntry
-{
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- object? this[IPropertyBase propertyBase] { get; set; }
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- IRuntimeEntityType EntityType { get; }
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- bool HasConceptualNull { get; }
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- IStateManager StateManager { get; }
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void AcceptChanges();
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void DiscardStoreGeneratedValues();
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- object? GetCurrentValue(IPropertyBase propertyBase);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- TProperty GetCurrentValue(IPropertyBase propertyBase);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- object? GetOriginalValue(IPropertyBase propertyBase);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- TProperty GetOriginalValue(IProperty property);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- object? GetPreStoreGeneratedCurrentValue(IPropertyBase propertyBase);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- bool HasExplicitValue(IProperty property);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- bool HasTemporaryValue(IProperty property);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- bool IsConceptualNull(IProperty property);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- bool IsModified(IProperty property);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- bool FlaggedAsStoreGenerated(int propertyIndex);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- bool FlaggedAsTemporary(int propertyIndex);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- bool IsStoreGenerated(IProperty property);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- bool IsUnknown(IProperty property);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void MarkAsTemporary(IProperty property, bool temporary);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void MarkUnchangedFromQuery();
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void MarkUnknown(IProperty property);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- IInternalEntry PrepareToSave();
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- public object Object { get; } // This won't work for value types
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- public void HandleConceptualNulls(bool sensitiveLoggingEnabled, bool force, bool isCascadeDelete);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void PropagateValue(InternalEntityEntry principalEntry, IProperty principalProperty, IProperty dependentProperty, bool isMaterialization = false, bool setModified = true);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- T ReadOriginalValue(IProperty property, int originalValueIndex);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- object? ReadPropertyValue(IPropertyBase propertyBase);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- T ReadStoreGeneratedValue(int storeGeneratedIndex);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- T ReadTemporaryValue(int storeGeneratedIndex);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- T ReadShadowValue(int shadowIndex);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void SetOriginalValue(IPropertyBase propertyBase, object? value, int index = -1);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void SetProperty(IPropertyBase propertyBase, object? value, bool isMaterialization, bool setModified = true, bool isCascadeDelete = false);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void SetPropertyModified(IProperty property, bool changeState = true, bool isModified = true, bool isConceptualNull = false, bool acceptChanges = false);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void SetEntityState(
- EntityState entityState,
- bool acceptChanges = false,
- bool modifyProperties = true);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void OnComplexPropertyModified(IComplexProperty property, bool isModified = true);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void SetStoreGeneratedValue(IProperty property, object? value, bool setModified = true);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- void SetTemporaryValue(IProperty property, object? value, bool setModified = true);
-}
+// using Microsoft.EntityFrameworkCore.Metadata.Internal;
+//
+// namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// public interface IInternalEntry
+// {
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// object? this[IPropertyBase propertyBase] { get; set; }
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// IRuntimeEntityType EntityType { get; }
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// bool HasConceptualNull { get; }
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// IStateManager StateManager { get; }
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void AcceptChanges();
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void DiscardStoreGeneratedValues();
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// object? GetCurrentValue(IPropertyBase propertyBase);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// TProperty GetCurrentValue(IPropertyBase propertyBase);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// object? GetOriginalValue(IPropertyBase propertyBase);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// TProperty GetOriginalValue(IProperty property);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// object? GetPreStoreGeneratedCurrentValue(IPropertyBase propertyBase);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// bool HasExplicitValue(IProperty property);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// bool HasTemporaryValue(IProperty property);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// bool IsConceptualNull(IProperty property);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// bool IsModified(IProperty property);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// bool FlaggedAsStoreGenerated(int propertyIndex);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// bool FlaggedAsTemporary(int propertyIndex);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// bool IsStoreGenerated(IProperty property);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// bool IsUnknown(IProperty property);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void MarkAsTemporary(IProperty property, bool temporary);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void MarkUnchangedFromQuery();
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void MarkUnknown(IProperty property);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// IInternalEntry PrepareToSave();
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// public object Object { get; } // This won't work for value types
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// public void HandleConceptualNulls(bool sensitiveLoggingEnabled, bool force, bool isCascadeDelete);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void PropagateValue(InternalEntityEntry principalEntry, IProperty principalProperty, IProperty dependentProperty, bool isMaterialization = false, bool setModified = true);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// T ReadOriginalValue(IProperty property, int originalValueIndex);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// object? ReadPropertyValue(IPropertyBase propertyBase);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// T ReadStoreGeneratedValue(int storeGeneratedIndex);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// T ReadTemporaryValue(int storeGeneratedIndex);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// T ReadShadowValue(int shadowIndex);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void SetOriginalValue(IPropertyBase propertyBase, object? value, int index = -1);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void SetProperty(IPropertyBase propertyBase, object? value, bool isMaterialization, bool setModified = true, bool isCascadeDelete = false);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void SetPropertyModified(IProperty property, bool changeState = true, bool isModified = true, bool isConceptualNull = false, bool acceptChanges = false);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void SetEntityState(
+// EntityState entityState,
+// bool acceptChanges = false,
+// bool modifyProperties = true);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void OnComplexPropertyModified(IComplexProperty property, bool isModified = true);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void SetStoreGeneratedValue(IProperty property, object? value, bool setModified = true);
+//
+// ///
+// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+// /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+// /// any release. You should only use it directly in your code with extreme caution and knowing that
+// /// doing so can result in application failures when updating to a new Entity Framework Core release.
+// ///
+// void SetTemporaryValue(IProperty property, object? value, bool setModified = true);
+// }
diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.OriginalValues.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.OriginalValues.cs
index fd3b1581ea5..6e7b552b3fc 100644
--- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.OriginalValues.cs
+++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.OriginalValues.cs
@@ -11,12 +11,12 @@ private readonly struct OriginalValues
{
private readonly ISnapshot _values;
- public OriginalValues(IInternalEntry entry)
+ public OriginalValues(InternalEntityEntry entry)
{
_values = entry.EntityType.OriginalValuesFactory(entry);
}
- public object? GetValue(IInternalEntry entry, IProperty property)
+ public object? GetValue(InternalEntityEntry entry, IProperty property)
{
var index = property.GetOriginalValueIndex();
if (index == -1)
@@ -28,7 +28,7 @@ public OriginalValues(IInternalEntry entry)
return IsEmpty ? entry[property] : _values[index];
}
- public T GetValue(IInternalEntry entry, IProperty property, int index)
+ public T GetValue(InternalEntityEntry entry, IProperty property, int index)
{
if (index == -1)
{
@@ -65,7 +65,7 @@ public void SetValue(IProperty property, object? value, int index)
_values[index] = SnapshotValue(property, value);
}
- public void RejectChanges(IInternalEntry entry)
+ public void RejectChanges(InternalEntityEntry entry)
{
if (IsEmpty)
{
@@ -82,7 +82,7 @@ public void RejectChanges(IInternalEntry entry)
}
}
- public void AcceptChanges(IInternalEntry entry)
+ public void AcceptChanges(InternalEntityEntry entry)
{
if (IsEmpty)
{
diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
index b13479b77c2..8daa35ecbb2 100644
--- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
+++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
@@ -16,7 +16,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
-public sealed partial class InternalEntityEntry : IUpdateEntry, IInternalEntry
+public sealed partial class InternalEntityEntry : IUpdateEntry
{
private readonly StateData _stateData;
private OriginalValues _originalValues;
@@ -420,7 +420,7 @@ private void HandleSharedIdentityEntry(EntityState newState)
throw new InvalidOperationException(
CoreStrings.IdentityConflictSensitive(
EntityType.DisplayName(),
- BuildCurrentValuesString(EntityType.FindPrimaryKey()!.Properties)));
+ this.BuildCurrentValuesString(EntityType.FindPrimaryKey()!.Properties)));
}
throw new InvalidOperationException(
@@ -793,7 +793,7 @@ public void MarkAsTemporary(IProperty property, bool temporary)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public static readonly MethodInfo FlaggedAsTemporaryMethod
- = typeof(IInternalEntry).GetMethod(nameof(IInternalEntry.FlaggedAsTemporary))!;
+ = typeof(InternalEntityEntry).GetMethod(nameof(InternalEntityEntry.FlaggedAsTemporary))!;
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -802,7 +802,7 @@ public static readonly MethodInfo FlaggedAsTemporaryMethod
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public static readonly MethodInfo FlaggedAsStoreGeneratedMethod
- = typeof(IInternalEntry).GetMethod(nameof(IInternalEntry.FlaggedAsStoreGenerated))!;
+ = typeof(InternalEntityEntry).GetMethod(nameof(InternalEntityEntry.FlaggedAsStoreGenerated))!;
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -837,7 +837,7 @@ public void MarkUnknown(IProperty property)
=> _stateData.FlagProperty(property.GetIndex(), PropertyFlag.Unknown, true);
internal static MethodInfo MakeReadShadowValueMethod(Type type)
- => typeof(IInternalEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadShadowValue))!
+ => typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadShadowValue))!
.MakeGenericMethod(type);
///
@@ -850,7 +850,7 @@ public T ReadShadowValue(int shadowIndex)
=> _shadowValues.GetValue(shadowIndex);
private static readonly MethodInfo ReadOriginalValueMethod
- = typeof(IInternalEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadOriginalValue))!;
+ = typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadOriginalValue))!;
[UnconditionalSuppressMessage(
"ReflectionAnalysis", "IL2060",
@@ -892,7 +892,7 @@ internal static MethodInfo MakeReadStoreGeneratedValueMethod(Type type)
=> ReadStoreGeneratedValueMethod.MakeGenericMethod(type);
private static readonly MethodInfo ReadStoreGeneratedValueMethod
- = typeof(IInternalEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadStoreGeneratedValue))!;
+ = typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadStoreGeneratedValue))!;
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -904,7 +904,7 @@ public T ReadStoreGeneratedValue(int storeGeneratedIndex)
=> _storeGeneratedValues.GetValue(storeGeneratedIndex);
private static readonly MethodInfo ReadTemporaryValueMethod
- = typeof(IInternalEntry).GetMethod(nameof(ReadTemporaryValue))!;
+ = typeof(InternalEntityEntry).GetMethod(nameof(ReadTemporaryValue))!;
[UnconditionalSuppressMessage(
"ReflectionAnalysis", "IL2060",
@@ -922,7 +922,7 @@ public T ReadTemporaryValue(int storeGeneratedIndex)
=> _temporaryValues.GetValue(storeGeneratedIndex);
private static readonly MethodInfo GetCurrentValueMethod
- = typeof(IInternalEntry).GetTypeInfo().GetDeclaredMethods(nameof(GetCurrentValue)).Single(
+ = typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethods(nameof(GetCurrentValue)).Single(
m => m.IsGenericMethod);
[UnconditionalSuppressMessage(
@@ -938,7 +938,7 @@ internal static MethodInfo MakeGetCurrentValueMethod(Type type)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public TProperty GetCurrentValue(IPropertyBase propertyBase)
- => ((Func)propertyBase.GetPropertyAccessors().CurrentValueGetter)(this);
+ => ((Func)propertyBase.GetPropertyAccessors().CurrentValueGetter)(this);
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -947,7 +947,7 @@ public TProperty GetCurrentValue(IPropertyBase propertyBase)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public TProperty GetOriginalValue(IProperty property)
- => ((Func)property.GetPropertyAccessors().OriginalValueGetter!)(this);
+ => ((Func)property.GetPropertyAccessors().OriginalValueGetter!)(this);
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -968,7 +968,7 @@ public TProperty GetRelationshipSnapshotValue(IPropertyBase propertyB
public object? ReadPropertyValue(IPropertyBase propertyBase)
=> propertyBase.IsShadowProperty()
? _shadowValues[propertyBase.GetShadowIndex()]
- : propertyBase.GetGetter().GetClrValue(Entity);
+ : propertyBase.GetGetter().GetClrValueUsingContainingEntity(Entity);
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -1572,14 +1572,9 @@ public InternalEntityEntry PrepareToSave()
throw new InvalidOperationException(CoreStrings.UnknownKeyValue(entityType.DisplayName(), property.Name));
}
- if (property.GetElementType() != null
- && !property.IsNullable
- && GetCurrentValue(property) == null)
- {
- throw new InvalidOperationException(
- CoreStrings.NullRequiredPrimitiveCollection(EntityType.DisplayName(), property.Name));
- }
+ CheckForNullCollection(property);
}
+ CheckForNullComplexProperties();
}
else if (EntityState == EntityState.Modified)
{
@@ -1594,8 +1589,10 @@ public InternalEntityEntry PrepareToSave()
EntityType.DisplayName()));
}
+ CheckForNullCollection(property);
CheckForUnknownKey(property);
}
+ CheckForNullComplexProperties();
}
else if (EntityState == EntityState.Deleted)
{
@@ -1617,6 +1614,31 @@ void CheckForUnknownKey(IProperty property)
throw new InvalidOperationException(CoreStrings.UnknownShadowKeyValue(entityType.DisplayName(), property.Name));
}
}
+
+ void CheckForNullCollection(IProperty property)
+ {
+ if (property.GetElementType() != null
+ && !property.IsNullable
+ && GetCurrentValue(property) == null)
+ {
+ throw new InvalidOperationException(
+ CoreStrings.NullRequiredPrimitiveCollection(EntityType.DisplayName(), property.Name));
+ }
+ }
+
+ void CheckForNullComplexProperties()
+ {
+ foreach (var complexProperty in entityType.GetFlattenedComplexProperties())
+ {
+ if (!complexProperty.IsNullable
+ && this[complexProperty] == null)
+ {
+ throw new InvalidOperationException(
+ CoreStrings.NullRequiredComplexProperty(
+ complexProperty.DeclaringType.ClrType.ShortDisplayName(), complexProperty.Name));
+ }
+ }
+ }
}
///
@@ -1695,7 +1717,7 @@ public void HandleConceptualNulls(bool sensitiveLoggingEnabled, bool force, bool
CoreStrings.RelationshipConceptualNullSensitive(
foreignKey.PrincipalEntityType.DisplayName(),
EntityType.DisplayName(),
- BuildOriginalValuesString(foreignKey.Properties)));
+ this.BuildOriginalValuesString(foreignKey.Properties)));
}
throw new InvalidOperationException(
@@ -1718,7 +1740,7 @@ public void HandleConceptualNulls(bool sensitiveLoggingEnabled, bool force, bool
CoreStrings.PropertyConceptualNullSensitive(
property.Name,
EntityType.DisplayName(),
- BuildOriginalValuesString(new[] { property })));
+ this.BuildOriginalValuesString(new[] { property })));
}
throw new InvalidOperationException(
@@ -1776,7 +1798,7 @@ public bool HasExplicitValue(IProperty property)
private bool HasSentinel(IProperty property)
=> property.IsShadowProperty()
? AreEqual(_shadowValues[property.GetShadowIndex()], property.Sentinel, property)
- : property.GetGetter().HasSentinel(Entity);
+ : property.GetGetter().HasSentinelUsingContainingEntity(Entity);
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -2024,24 +2046,6 @@ public bool IsLoaded(INavigationBase navigation)
return lazyLoaderProperty != null ? (ILazyLoader?)this[lazyLoaderProperty] : null;
}
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- public string BuildCurrentValuesString(IEnumerable properties)
- => ((IInternalEntry)this).BuildCurrentValuesString(properties);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- public string BuildOriginalValuesString(IEnumerable properties)
- => ((IInternalEntry)this).BuildOriginalValuesString(properties);
-
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@@ -2068,18 +2072,6 @@ public DebugView DebugView
IEntityType IUpdateEntry.EntityType
=> EntityType;
- IRuntimeEntityType IInternalEntry.EntityType
- => EntityType;
-
- object IInternalEntry.Object
- => Entity;
-
- IInternalEntry IInternalEntry.PrepareToSave()
- => PrepareToSave();
-
- void IInternalEntry.SetEntityState(EntityState entityState, bool acceptChanges, bool modifyProperties)
- => SetEntityState(entityState, acceptChanges, modifyProperties);
-
private enum CurrentValueType
{
Normal,
diff --git a/src/EFCore/ChangeTracking/Internal/OriginalValuesFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/OriginalValuesFactoryFactory.cs
index ebc0663ccdc..cb38d9f6878 100644
--- a/src/EFCore/ChangeTracking/Internal/OriginalValuesFactoryFactory.cs
+++ b/src/EFCore/ChangeTracking/Internal/OriginalValuesFactoryFactory.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
-public class OriginalValuesFactoryFactory : SnapshotFactoryFactory
+public class OriginalValuesFactoryFactory : SnapshotFactoryFactory
{
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
diff --git a/src/EFCore/ChangeTracking/Internal/SidecarValuesFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/SidecarValuesFactoryFactory.cs
index e0f758c815e..c66736bdad9 100644
--- a/src/EFCore/ChangeTracking/Internal/SidecarValuesFactoryFactory.cs
+++ b/src/EFCore/ChangeTracking/Internal/SidecarValuesFactoryFactory.cs
@@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
-public class SidecarValuesFactoryFactory : SnapshotFactoryFactory
+public class SidecarValuesFactoryFactory : SnapshotFactoryFactory
{
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
diff --git a/src/EFCore/ChangeTracking/Internal/SimpleFullyNullableDependentKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/SimpleFullyNullableDependentKeyValueFactory.cs
index 3f4334aa65b..7ac738c4966 100644
--- a/src/EFCore/ChangeTracking/Internal/SimpleFullyNullableDependentKeyValueFactory.cs
+++ b/src/EFCore/ChangeTracking/Internal/SimpleFullyNullableDependentKeyValueFactory.cs
@@ -61,7 +61,7 @@ public virtual bool TryCreateFromBuffer(in ValueBuffer valueBuffer, [NotNullWhen
///
public override bool TryCreateFromCurrentValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey? key)
{
- key = ((Func)_propertyAccessors.CurrentValueGetter)((IInternalEntry)entry);
+ key = ((Func)_propertyAccessors.CurrentValueGetter)((InternalEntityEntry)entry);
return key != null;
}
@@ -73,7 +73,7 @@ public override bool TryCreateFromCurrentValues(IUpdateEntry entry, [NotNullWhen
///
public virtual bool TryCreateFromPreStoreGeneratedCurrentValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey? key)
{
- key = ((Func)_propertyAccessors.PreStoreGeneratedCurrentValueGetter)((IInternalEntry)entry);
+ key = ((Func)_propertyAccessors.PreStoreGeneratedCurrentValueGetter)((InternalEntityEntry)entry);
return key != null;
}
@@ -85,7 +85,7 @@ public virtual bool TryCreateFromPreStoreGeneratedCurrentValues(IUpdateEntry ent
///
public override bool TryCreateFromOriginalValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey? key)
{
- key = ((Func)_propertyAccessors.OriginalValueGetter!)((IInternalEntry)entry);
+ key = ((Func)_propertyAccessors.OriginalValueGetter!)((InternalEntityEntry)entry);
return key != null;
}
diff --git a/src/EFCore/ChangeTracking/Internal/SimpleNonNullableDependentKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/SimpleNonNullableDependentKeyValueFactory.cs
index c41962e0e35..2c9162b6ab5 100644
--- a/src/EFCore/ChangeTracking/Internal/SimpleNonNullableDependentKeyValueFactory.cs
+++ b/src/EFCore/ChangeTracking/Internal/SimpleNonNullableDependentKeyValueFactory.cs
@@ -68,7 +68,7 @@ public virtual bool TryCreateFromBuffer(in ValueBuffer valueBuffer, [NotNullWhen
///
public override bool TryCreateFromCurrentValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey? key)
{
- key = ((Func)_propertyAccessors.CurrentValueGetter)((IInternalEntry)entry)!;
+ key = ((Func)_propertyAccessors.CurrentValueGetter)((InternalEntityEntry)entry)!;
return true;
}
@@ -80,7 +80,7 @@ public override bool TryCreateFromCurrentValues(IUpdateEntry entry, [NotNullWhen
///
public virtual bool TryCreateFromPreStoreGeneratedCurrentValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey? key)
{
- key = ((Func)_propertyAccessors.PreStoreGeneratedCurrentValueGetter)((IInternalEntry)entry)!;
+ key = ((Func)_propertyAccessors.PreStoreGeneratedCurrentValueGetter)((InternalEntityEntry)entry)!;
return true;
}
@@ -92,7 +92,7 @@ public virtual bool TryCreateFromPreStoreGeneratedCurrentValues(IUpdateEntry ent
///
public override bool TryCreateFromOriginalValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey? key)
{
- key = ((Func)_propertyAccessors.OriginalValueGetter!)((IInternalEntry)entry)!;
+ key = ((Func)_propertyAccessors.OriginalValueGetter!)((InternalEntityEntry)entry)!;
return true;
}
diff --git a/src/EFCore/ChangeTracking/Internal/SimpleNullableDependentKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/SimpleNullableDependentKeyValueFactory.cs
index 85b357c0e13..ce52fb1cd8d 100644
--- a/src/EFCore/ChangeTracking/Internal/SimpleNullableDependentKeyValueFactory.cs
+++ b/src/EFCore/ChangeTracking/Internal/SimpleNullableDependentKeyValueFactory.cs
@@ -66,7 +66,7 @@ public virtual bool TryCreateFromBuffer(in ValueBuffer valueBuffer, out TKey key
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public override bool TryCreateFromCurrentValues(IUpdateEntry entry, out TKey key)
- => HandleNullableValue(((Func)_propertyAccessors.CurrentValueGetter)((IInternalEntry)entry), out key);
+ => HandleNullableValue(((Func)_propertyAccessors.CurrentValueGetter)((InternalEntityEntry)entry), out key);
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -76,7 +76,7 @@ public override bool TryCreateFromCurrentValues(IUpdateEntry entry, out TKey key
///
public virtual bool TryCreateFromPreStoreGeneratedCurrentValues(IUpdateEntry entry, out TKey key)
=> HandleNullableValue(
- ((Func)_propertyAccessors.PreStoreGeneratedCurrentValueGetter)((IInternalEntry)entry), out key);
+ ((Func)_propertyAccessors.PreStoreGeneratedCurrentValueGetter)((InternalEntityEntry)entry), out key);
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -85,7 +85,7 @@ public virtual bool TryCreateFromPreStoreGeneratedCurrentValues(IUpdateEntry ent
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public override bool TryCreateFromOriginalValues(IUpdateEntry entry, out TKey key)
- => HandleNullableValue(((Func)_propertyAccessors.OriginalValueGetter!)((InternalEntityEntry)entry), out key);
+ => HandleNullableValue(((Func)_propertyAccessors.OriginalValueGetter!)((InternalEntityEntry)entry), out key);
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
diff --git a/src/EFCore/ChangeTracking/Internal/SimpleNullablePrincipalDependentKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/SimpleNullablePrincipalDependentKeyValueFactory.cs
index a32ed396555..b350bec9434 100644
--- a/src/EFCore/ChangeTracking/Internal/SimpleNullablePrincipalDependentKeyValueFactory.cs
+++ b/src/EFCore/ChangeTracking/Internal/SimpleNullablePrincipalDependentKeyValueFactory.cs
@@ -72,7 +72,7 @@ public virtual bool TryCreateFromBuffer(in ValueBuffer valueBuffer, [NotNullWhen
///
public override bool TryCreateFromCurrentValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey? key)
{
- key = (TKey)(object)((Func)_propertyAccessors.CurrentValueGetter)((IInternalEntry)entry)!;
+ key = (TKey)(object)((Func)_propertyAccessors.CurrentValueGetter)((InternalEntityEntry)entry)!;
return true;
}
@@ -84,7 +84,7 @@ public override bool TryCreateFromCurrentValues(IUpdateEntry entry, [NotNullWhen
///
public virtual bool TryCreateFromPreStoreGeneratedCurrentValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey? key)
{
- key = (TKey)(object)((Func)_propertyAccessors.PreStoreGeneratedCurrentValueGetter)((IInternalEntry)entry)!;
+ key = (TKey)(object)((Func)_propertyAccessors.PreStoreGeneratedCurrentValueGetter)((InternalEntityEntry)entry)!;
return true;
}
@@ -96,7 +96,7 @@ public virtual bool TryCreateFromPreStoreGeneratedCurrentValues(IUpdateEntry ent
///
public override bool TryCreateFromOriginalValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey? key)
{
- key = (TKey)(object)((Func)_propertyAccessors.OriginalValueGetter!)((IInternalEntry)entry)!;
+ key = (TKey)(object)((Func)_propertyAccessors.OriginalValueGetter!)((InternalEntityEntry)entry)!;
return true;
}
diff --git a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs
index 8ac652f44a1..aba7539759d 100644
--- a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs
+++ b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs
@@ -171,9 +171,7 @@ protected virtual Expression CreateSnapshotExpression(
Expression.Assign(
entityVariable,
Expression.Convert(
- Expression.Property(parameter!, parameter!.Type == typeof(InternalEntityEntry)
- ? nameof(InternalEntityEntry.Entity)
- : nameof(IInternalEntry.Object)),
+ Expression.Property(parameter!, nameof(InternalEntityEntry.Entity)),
entityType!)),
constructorExpression
})
diff --git a/src/EFCore/ChangeTracking/ListComparer.cs b/src/EFCore/ChangeTracking/ListComparer.cs
index 2f9220722b0..af6eea0fe6b 100644
--- a/src/EFCore/ChangeTracking/ListComparer.cs
+++ b/src/EFCore/ChangeTracking/ListComparer.cs
@@ -23,15 +23,28 @@ public sealed class ListComparer : ValueComparer
/// Creates a new instance of the list comparer.
///
/// The comparer to use for comparing elements.
- public ListComparer(ValueComparer elementComparer)
+ public ListComparer(ValueComparer elementComparer)
: base(
- (a, b) => Compare(a, b, elementComparer),
- o => GetHashCode(o, elementComparer),
- source => Snapshot(source, elementComparer))
+ (a, b) => Compare(a, b, (ValueComparer)elementComparer),
+ o => GetHashCode(o, (ValueComparer)elementComparer),
+ source => Snapshot(source, (ValueComparer)elementComparer))
{
+ ElementComparer = elementComparer;
}
- private static bool Compare(IEnumerable? a, IEnumerable? b, ValueComparer elementComparer)
+ ///
+ /// The comparer to use for comparing elements.
+ ///
+ public ValueComparer ElementComparer { get; }
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ [EntityFrameworkInternal]
+ public static bool Compare(IEnumerable? a, IEnumerable? b, ValueComparer elementComparer)
{
if (ReferenceEquals(a, b))
{
@@ -85,11 +98,17 @@ private static bool Compare(IEnumerable? a, IEnumerable? b,
throw new InvalidOperationException(
CoreStrings.BadListType(
(a is IList ? b : a).GetType().ShortDisplayName(),
- typeof(ListComparer).ShortDisplayName(),
typeof(IList<>).MakeGenericType(elementComparer.Type).ShortDisplayName()));
}
- private static int GetHashCode(IEnumerable source, ValueComparer elementComparer)
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ [EntityFrameworkInternal]
+ public static int GetHashCode(IEnumerable source, ValueComparer elementComparer)
{
var hash = new HashCode();
@@ -101,14 +120,20 @@ private static int GetHashCode(IEnumerable source, ValueComparer Snapshot(IEnumerable source, ValueComparer elementComparer)
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ [EntityFrameworkInternal]
+ public static IList Snapshot(IEnumerable source, ValueComparer elementComparer)
{
- if (!(source is IList sourceList))
+ if (source is not IList sourceList)
{
throw new InvalidOperationException(
CoreStrings.BadListType(
source.GetType().ShortDisplayName(),
- typeof(ListComparer).ShortDisplayName(),
typeof(IList<>).MakeGenericType(elementComparer.Type).ShortDisplayName()));
}
diff --git a/src/EFCore/ChangeTracking/NullableValueTypeListComparer.cs b/src/EFCore/ChangeTracking/NullableValueTypeListComparer.cs
index d2e8ac223ee..58914950734 100644
--- a/src/EFCore/ChangeTracking/NullableValueTypeListComparer.cs
+++ b/src/EFCore/ChangeTracking/NullableValueTypeListComparer.cs
@@ -24,15 +24,28 @@ public sealed class NullableValueTypeListComparer : ValueComparer
/// The comparer to use for comparing elements.
- public NullableValueTypeListComparer(ValueComparer elementComparer)
+ public NullableValueTypeListComparer(ValueComparer elementComparer)
: base(
- (a, b) => Compare(a, b, elementComparer),
- o => GetHashCode(o, elementComparer),
- source => Snapshot(source, elementComparer))
+ (a, b) => Compare(a, b, (ValueComparer)elementComparer),
+ o => GetHashCode(o, (ValueComparer)elementComparer),
+ source => Snapshot(source, (ValueComparer)elementComparer))
{
+ ElementComparer = elementComparer;
}
- private static bool Compare(IEnumerable? a, IEnumerable? b, ValueComparer elementComparer)
+ ///
+ /// The comparer to use for comparing elements.
+ ///
+ public ValueComparer ElementComparer { get; }
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ [EntityFrameworkInternal]
+ public static bool Compare(IEnumerable? a, IEnumerable? b, ValueComparer elementComparer)
{
if (ReferenceEquals(a, b))
{
@@ -86,11 +99,17 @@ private static bool Compare(IEnumerable? a, IEnumerable? b
throw new InvalidOperationException(
CoreStrings.BadListType(
(a is IList ? b : a).GetType().ShortDisplayName(),
- typeof(NullableValueTypeListComparer).ShortDisplayName(),
typeof(IList<>).MakeGenericType(elementComparer.Type.MakeNullable()).ShortDisplayName()));
}
- private static int GetHashCode(IEnumerable source, ValueComparer elementComparer)
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ [EntityFrameworkInternal]
+ public static int GetHashCode(IEnumerable source, ValueComparer elementComparer)
{
var hash = new HashCode();
@@ -102,14 +121,20 @@ private static int GetHashCode(IEnumerable source, ValueComparer Snapshot(IEnumerable source, ValueComparer elementComparer)
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ [EntityFrameworkInternal]
+ public static IList Snapshot(IEnumerable source, ValueComparer elementComparer)
{
- if (!(source is IList sourceList))
+ if (source is not IList sourceList)
{
throw new InvalidOperationException(
CoreStrings.BadListType(
source.GetType().ShortDisplayName(),
- typeof(NullableValueTypeListComparer).ShortDisplayName(),
typeof(IList<>).MakeGenericType(elementComparer.Type.MakeNullable()).ShortDisplayName()));
}
@@ -120,7 +145,7 @@ private static int GetHashCode(IEnumerable source, ValueComparer source, ValueComparer
+/// A for lists of primitive items. The list can be typed as ,
+/// but can only be used with instances that implement .
+///
+///
+///
+/// This comparer should be used when the element of the comparer is typed as .
+///
+///
+/// See EF Core value comparers for more information and examples.
+///
+///
+/// The element type.
+public sealed class ObjectListComparer : ValueComparer>
+{
+ ///
+ /// Creates a new instance of the list comparer.
+ ///
+ /// The comparer to use for comparing elements.
+ public ObjectListComparer(ValueComparer elementComparer)
+ : base(
+ (a, b) => Compare(a, b, elementComparer),
+ o => GetHashCode(o, elementComparer),
+ source => Snapshot(source, elementComparer))
+ {
+ ElementComparer = elementComparer;
+ }
+
+ ///
+ /// The comparer to use for comparing elements.
+ ///
+ public ValueComparer ElementComparer { get; }
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ [EntityFrameworkInternal]
+ public static bool Compare(IEnumerable? a, IEnumerable? b, ValueComparer elementComparer)
+ {
+ if (ReferenceEquals(a, b))
+ {
+ return true;
+ }
+
+ if (a is null)
+ {
+ return b is null;
+ }
+
+ if (b is null)
+ {
+ return false;
+ }
+
+ if (a is IList
-
+
diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
index 228845c0d18..bd368b2370a 100644
--- a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
+++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
@@ -7,7 +7,9 @@
using System.Data.Common;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.IO;
using System.Reflection;
+using System.Runtime.InteropServices;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
using static SQLitePCL.raw;
@@ -52,38 +54,50 @@ static SqliteConnection()
?.GetRuntimeMethod("Init", Type.EmptyTypes)
?.Invoke(null, null);
- var appDataType = Type.GetType("Windows.Storage.ApplicationData, Windows, ContentType=WindowsRuntime")
- ?? Type.GetType("Windows.Storage.ApplicationData, Microsoft.Windows.SDK.NET");
-
- var storageFolderType = Type.GetType("Windows.Storage.StorageFolder, Windows, ContentType=WindowsRuntime")
- ?? Type.GetType("Windows.Storage.StorageFolder, Microsoft.Windows.SDK.NET");
-
- object? currentAppData = null;
- try
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
- currentAppData = appDataType?.GetRuntimeProperty("Current")?.GetValue(null);
- }
- catch (TargetInvocationException)
- {
- // Ignore "The process has no package identity."
- }
+ Type? appDataType = null;
+ Type? storageFolderType = null;
+ try
+ {
+ appDataType = Type.GetType("Windows.Storage.ApplicationData, Windows, ContentType=WindowsRuntime")
+ ?? Type.GetType("Windows.Storage.ApplicationData, Microsoft.Windows.SDK.NET");
- if (currentAppData != null)
- {
- var localFolder = appDataType?.GetRuntimeProperty("LocalFolder")?.GetValue(currentAppData);
- var localFolderPath = (string?)storageFolderType?.GetRuntimeProperty("Path")?.GetValue(localFolder);
- if (localFolderPath != null)
+ storageFolderType = Type.GetType("Windows.Storage.StorageFolder, Windows, ContentType=WindowsRuntime")
+ ?? Type.GetType("Windows.Storage.StorageFolder, Microsoft.Windows.SDK.NET");
+ }
+ catch (FileLoadException)
{
- var rc = sqlite3_win32_set_directory(SQLITE_WIN32_DATA_DIRECTORY_TYPE, localFolderPath);
- Debug.Assert(rc == SQLITE_OK);
+ // Ignore "Could not load assembly."
}
- var tempFolder = appDataType?.GetRuntimeProperty("TemporaryFolder")?.GetValue(currentAppData);
- var tempFolderPath = (string?)storageFolderType?.GetRuntimeProperty("Path")?.GetValue(tempFolder);
- if (tempFolderPath != null)
+ object? currentAppData = null;
+ try
+ {
+ currentAppData = appDataType?.GetRuntimeProperty("Current")?.GetValue(null);
+ }
+ catch (TargetInvocationException)
{
- var rc = sqlite3_win32_set_directory(SQLITE_WIN32_TEMP_DIRECTORY_TYPE, tempFolderPath);
- Debug.Assert(rc == SQLITE_OK);
+ // Ignore "The process has no package identity."
+ }
+
+ if (currentAppData != null)
+ {
+ var localFolder = appDataType?.GetRuntimeProperty("LocalFolder")?.GetValue(currentAppData);
+ var localFolderPath = (string?)storageFolderType?.GetRuntimeProperty("Path")?.GetValue(localFolder);
+ if (localFolderPath != null)
+ {
+ var rc = sqlite3_win32_set_directory(SQLITE_WIN32_DATA_DIRECTORY_TYPE, localFolderPath);
+ Debug.Assert(rc == SQLITE_OK);
+ }
+
+ var tempFolder = appDataType?.GetRuntimeProperty("TemporaryFolder")?.GetValue(currentAppData);
+ var tempFolderPath = (string?)storageFolderType?.GetRuntimeProperty("Path")?.GetValue(tempFolder);
+ if (tempFolderPath != null)
+ {
+ var rc = sqlite3_win32_set_directory(SQLITE_WIN32_TEMP_DIRECTORY_TYPE, tempFolderPath);
+ Debug.Assert(rc == SQLITE_OK);
+ }
}
}
}
@@ -821,22 +835,24 @@ private void CreateAggregateCore(
delegate_function_aggregate_step? func_step = null;
if (func != null)
{
- func_step = (ctx, user_data, args) =>
+ func_step = static (ctx, user_data, args) =>
{
- var context = (AggregateContext)user_data;
+ var definition = (AggregateDefinition)user_data;
+ ctx.state ??= new AggregateContext(definition.Seed);
+
+ var context = (AggregateContext)ctx.state;
if (context.Exception != null)
{
return;
}
// TODO: Avoid allocation when niladic
- var reader = new SqliteParameterReader(name, args);
+ var reader = new SqliteParameterReader(definition.Name, args);
try
{
- // TODO: Avoid closure by passing func via user_data
// NB: No need to set ctx.state since we just mutate the instance
- context.Accumulate = func(context.Accumulate, reader);
+ context.Accumulate = definition.Func!(context.Accumulate, reader);
}
catch (Exception ex)
{
@@ -848,16 +864,18 @@ private void CreateAggregateCore(
delegate_function_aggregate_final? func_final = null;
if (resultSelector != null)
{
- func_final = (ctx, user_data) =>
+ func_final = static (ctx, user_data) =>
{
- var context = (AggregateContext)user_data;
+ var definition = (AggregateDefinition)user_data;
+ ctx.state ??= new AggregateContext(definition.Seed);
+
+ var context = (AggregateContext)ctx.state;
if (context.Exception == null)
{
try
{
- // TODO: Avoid closure by passing resultSelector via user_data
- var result = resultSelector(context.Accumulate);
+ var result = definition.ResultSelector!(context.Accumulate);
new SqliteResultBinder(ctx, result).Bind();
}
@@ -881,7 +899,7 @@ private void CreateAggregateCore(
}
var flags = isDeterministic ? SQLITE_DETERMINISTIC : 0;
- var state = new AggregateContext(seed);
+ var state = new AggregateDefinition(name, seed, func, resultSelector);
if (State == ConnectionState.Open)
{
@@ -915,6 +933,22 @@ private void CreateAggregateCore(
return values;
}
+ private sealed class AggregateDefinition
+ {
+ public AggregateDefinition(string name, TAccumulate seed, Func? func, Func? resultSelector)
+ {
+ Name = name;
+ Seed = seed;
+ Func = func;
+ ResultSelector = resultSelector;
+ }
+
+ public string Name { get; }
+ public TAccumulate Seed { get; }
+ public Func? Func { get; }
+ public Func? ResultSelector { get; }
+ }
+
private sealed class AggregateContext
{
public AggregateContext(T seed)
diff --git a/src/Microsoft.Data.Sqlite/Microsoft.Data.Sqlite.csproj b/src/Microsoft.Data.Sqlite/Microsoft.Data.Sqlite.csproj
index 1b00ec7bae8..34cd41f43ec 100644
--- a/src/Microsoft.Data.Sqlite/Microsoft.Data.Sqlite.csproj
+++ b/src/Microsoft.Data.Sqlite/Microsoft.Data.Sqlite.csproj
@@ -24,7 +24,7 @@ Microsoft.Data.Sqlite.SqliteTransaction
-
+
diff --git a/src/ef/Commands/MigrationsHasPendingModelChangesCommand.cs b/src/ef/Commands/MigrationsHasPendingModelChangesCommand.cs
index bdbd2db8b6a..f552a82ce37 100644
--- a/src/ef/Commands/MigrationsHasPendingModelChangesCommand.cs
+++ b/src/ef/Commands/MigrationsHasPendingModelChangesCommand.cs
@@ -1,12 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using Microsoft.EntityFrameworkCore.Internal;
+using Microsoft.EntityFrameworkCore.Tools.Properties;
+
namespace Microsoft.EntityFrameworkCore.Tools.Commands;
internal partial class MigrationsHasPendingModelChangesCommand
{
protected override int Execute(string[] args)
{
+ if (new SemanticVersionComparer().Compare(EFCoreVersion, "8.0.0") < 0)
+ {
+ throw new CommandException(Resources.VersionRequired("8.0.0"));
+ }
+
using var executor = CreateExecutor(args);
executor.HasPendingModelChanges(Context!.Value());
diff --git a/test/EFCore.Cosmos.FunctionalTests/ConfigPatternsCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/ConfigPatternsCosmosTest.cs
index 95601921d87..daaa5d8b6fb 100644
--- a/test/EFCore.Cosmos.FunctionalTests/ConfigPatternsCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/ConfigPatternsCosmosTest.cs
@@ -88,7 +88,7 @@ public async Task Should_throw_if_specified_region_is_wrong()
exception.Message);
}
- [ConditionalFact(Skip = "Issue #runtime/issues/89118")]
+ [ConditionalFact]
public async Task Should_not_throw_if_specified_connection_mode_is_right()
{
var connectionMode = ConnectionMode.Direct;
diff --git a/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs
index b2b9d76b638..3f26733c3b2 100644
--- a/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs
@@ -1256,7 +1256,7 @@ public async Task Can_read_with_find_with_PK_partition_key()
{
var options = Fixture.CreateOptions();
- var customer = new Customer { Id = 42, Name = "Theon" };
+ var customer = new CustomerGuid { Id = Guid.NewGuid(), Name = "Theon" };
await using (var context = new PartitionKeyContextPrimaryKey(options))
{
@@ -1269,11 +1269,11 @@ public async Task Can_read_with_find_with_PK_partition_key()
await using (var context = new PartitionKeyContextPrimaryKey(options))
{
- var customerFromStore = context.Set().Find(42);
+ var customerFromStore = context.Set().Find(customer.Id);
- Assert.Equal(42, customerFromStore.Id);
+ Assert.Equal(customer.Id, customerFromStore.Id);
Assert.Equal("Theon", customerFromStore.Name);
- AssertSql(context, @"ReadItem(42, 42)");
+ AssertSql(context, @$"ReadItem({customer.Id}, {customer.Id})");
}
}
@@ -1400,11 +1400,10 @@ public PartitionKeyContextPrimaryKey(DbContextOptions dbContextOptions)
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
- => modelBuilder.Entity(
+ => modelBuilder.Entity(
cb =>
{
- cb.HasNoDiscriminator();
- cb.Property(c => c.Id).HasConversion();
+ cb.Property(c => c.Id).ToJsonProperty("id");
cb.HasPartitionKey(c => c.Id);
});
}
diff --git a/test/EFCore.Cosmos.FunctionalTests/MaterializationInterceptionCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/MaterializationInterceptionCosmosTest.cs
index b98e8456eea..9ef9d4e4be1 100644
--- a/test/EFCore.Cosmos.FunctionalTests/MaterializationInterceptionCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/MaterializationInterceptionCosmosTest.cs
@@ -11,6 +11,9 @@ public MaterializationInterceptionCosmosTest(MaterializationInterceptionCosmosFi
{
}
+ public override Task Intercept_query_materialization_with_owned_types_projecting_collection(bool async)
+ => Task.CompletedTask;
+
public class CosmosLibraryContext : LibraryContext
{
public CosmosLibraryContext(DbContextOptions options)
diff --git a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosTestStore.cs b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosTestStore.cs
index 6544f0744e3..d738654b5d6 100644
--- a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosTestStore.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosTestStore.cs
@@ -715,6 +715,9 @@ public IEnumerable GetSnapshottableMembers()
public IEnumerable GetFlattenedProperties()
=> throw new NotImplementedException();
+ public IEnumerable GetFlattenedComplexProperties()
+ => throw new NotImplementedException();
+
public IEnumerable GetFlattenedDeclaredProperties()
=> throw new NotImplementedException();
diff --git a/test/EFCore.Cosmos.Tests/Extensions/CosmosDbContextOptionsExtensionsTests.cs b/test/EFCore.Cosmos.Tests/Extensions/CosmosDbContextOptionsExtensionsTests.cs
index 963951c2409..708056c3270 100644
--- a/test/EFCore.Cosmos.Tests/Extensions/CosmosDbContextOptionsExtensionsTests.cs
+++ b/test/EFCore.Cosmos.Tests/Extensions/CosmosDbContextOptionsExtensionsTests.cs
@@ -71,6 +71,8 @@ public void Can_create_options_with_valid_values()
Test(o => o.Region(Regions.EastAsia), o => Assert.Equal(Regions.EastAsia, o.Region));
// The region will be validated by the Cosmos SDK, because the region list is not constant
Test(o => o.Region("FakeRegion"), o => Assert.Equal("FakeRegion", o.Region));
+ Test(o => o.PreferredRegions(new[] { Regions.AustraliaCentral, Regions.EastAsia }),
+ o => Assert.Equal(new[] { Regions.AustraliaCentral, Regions.EastAsia }, o.PreferredRegions));
Test(o => o.ConnectionMode(ConnectionMode.Direct), o => Assert.Equal(ConnectionMode.Direct, o.ConnectionMode));
Test(o => o.GatewayModeMaxConnectionLimit(3), o => Assert.Equal(3, o.GatewayModeMaxConnectionLimit));
Test(o => o.MaxRequestsPerTcpConnection(3), o => Assert.Equal(3, o.MaxRequestsPerTcpConnection));
diff --git a/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs b/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs
index 4b04a27d661..1f32b625230 100644
--- a/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs
+++ b/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs
@@ -333,6 +333,35 @@ protected override TestModelBuilder CreateModelBuilder(Action()
+ .Entity()
+ .ComplexProperty(e => e.Customer)
+ .HasTypeAnnotation("foo", "bar")
+ .HasPropertyAnnotation("foo2", "bar2")
+ .Ignore(c => c.Details)
+ .Ignore(c => c.Orders);
+
+ var model = modelBuilder.FinalizeModel();
+ var complexProperty = model.FindEntityType(typeof(ComplexProperties)).GetComplexProperties().Single();
+
+ Assert.Equal("bar", complexProperty.ComplexType["foo"]);
+ Assert.Equal("bar2", complexProperty["foo2"]);
+ Assert.Equal(typeof(Customer).Name, complexProperty.Name);
+ Assert.Equal(
+ @"Customer (Customer) Required
+ ComplexType: ComplexProperties.Customer#Customer
+ Properties: " + @"
+ AlternateKey (Guid) Required
+ Id (int) Required
+ Name (string)
+ Notes (List)", complexProperty.ToDebugString(), ignoreLineEndingDifferences: true);
+ }
+
public override void Properties_can_have_provider_type_set_for_type()
{
var modelBuilder = CreateModelBuilder(c => c.Properties().HaveConversion());
diff --git a/test/EFCore.Design.Tests/Design/Internal/CSharpHelperTest.cs b/test/EFCore.Design.Tests/Design/Internal/CSharpHelperTest.cs
index 24ddf62a94b..4c29fc5b471 100644
--- a/test/EFCore.Design.Tests/Design/Internal/CSharpHelperTest.cs
+++ b/test/EFCore.Design.Tests/Design/Internal/CSharpHelperTest.cs
@@ -827,8 +827,7 @@ private static SqlServerTypeMappingSource CreateTypeMappingSource(
params IRelationalTypeMappingSourcePlugin[] plugins)
=> new(
TestServiceFactory.Instance.Create(),
- new RelationalTypeMappingSourceDependencies(plugins),
- new SqlServerSingletonOptions());
+ new RelationalTypeMappingSourceDependencies(plugins));
private class TestTypeMappingPlugin : IRelationalTypeMappingSourcePlugin
{
diff --git a/test/EFCore.Design.Tests/EFCore.Design.Tests.csproj b/test/EFCore.Design.Tests/EFCore.Design.Tests.csproj
index e594b843934..9029f099eb5 100644
--- a/test/EFCore.Design.Tests/EFCore.Design.Tests.csproj
+++ b/test/EFCore.Design.Tests/EFCore.Design.Tests.csproj
@@ -57,7 +57,7 @@
-
+
diff --git a/test/EFCore.Design.Tests/Extensions/MethodCallCodeFragmentExtensionsTest.cs b/test/EFCore.Design.Tests/Extensions/MethodCallCodeFragmentExtensionsTest.cs
new file mode 100644
index 00000000000..87f6a27819b
--- /dev/null
+++ b/test/EFCore.Design.Tests/Extensions/MethodCallCodeFragmentExtensionsTest.cs
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.EntityFrameworkCore.Extensions
+{
+ public class MethodCallCodeFragmentExtensionsTest
+ {
+ [ConditionalFact]
+ public void GetRequiredUsings_works()
+ {
+ var methodCall = new MethodCallCodeFragment(
+ typeof(Namespace1.TestExtensions1)
+ .GetRuntimeMethod(
+ nameof(Namespace1.TestExtensions1.Extension1),
+ new[]
+ {
+ typeof(MethodCallCodeFragmentExtensionsTest),
+ typeof(Action)
+ }),
+ new NestedClosureCodeFragment(
+ "x",
+ new MethodCallCodeFragment(
+ typeof(Namespace2.TestExtensions2)
+ .GetRuntimeMethod(
+ nameof(Namespace2.TestExtensions2.Extension2),
+ new[]
+ {
+ typeof(MethodCallCodeFragmentExtensionsTest),
+ typeof(Namespace3.TestArgument)
+ }),
+ new Namespace3.TestArgument())));
+
+
+ var usings = methodCall.GetRequiredUsings();
+
+ Assert.Equal(
+ new[]
+ {
+ "Microsoft.EntityFrameworkCore.Extensions.Namespace1",
+ "Microsoft.EntityFrameworkCore.Extensions.Namespace2",
+ "Microsoft.EntityFrameworkCore.Extensions.Namespace3"
+ },
+ usings);
+ }
+ }
+
+ namespace Namespace1
+ {
+ internal static class TestExtensions1
+ {
+ public static void Extension1(
+ this MethodCallCodeFragmentExtensionsTest extendedObject,
+ Action closure)
+ => throw new NotImplementedException();
+ }
+ }
+
+ namespace Namespace2
+ {
+ internal static class TestExtensions2
+ {
+ public static void Extension2(
+ this MethodCallCodeFragmentExtensionsTest extendedObject,
+ Namespace3.TestArgument argument)
+ => throw new NotImplementedException();
+ }
+ }
+
+ namespace Namespace3
+ {
+ internal class TestArgument
+ {
+ }
+ }
+}
diff --git a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs
index ff59d0d87d8..765ff612e6a 100644
--- a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs
+++ b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs
@@ -20,8 +20,7 @@ public void Generate_separates_operations_by_a_blank_line()
new CSharpHelper(
new SqlServerTypeMappingSource(
TestServiceFactory.Instance.Create(),
- TestServiceFactory.Instance.Create(),
- new SqlServerSingletonOptions()))));
+ TestServiceFactory.Instance.Create()))));
var builder = new IndentedStringBuilder();
@@ -3160,8 +3159,7 @@ private void Test(T operation, string expectedCode, Action assert)
new IRelationalTypeMappingSourcePlugin[]
{
new SqlServerNetTopologySuiteTypeMappingSourcePlugin(NtsGeometryServices.Instance)
- }),
- new SqlServerSingletonOptions()))));
+ })))));
var builder = new IndentedStringBuilder();
generator.Generate("mb", new[] { operation }, builder);
diff --git a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.cs b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.cs
index d798e071d2a..3153973338f 100644
--- a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.cs
+++ b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.cs
@@ -349,8 +349,7 @@ private static void MissingAnnotationCheck(
{
var sqlServerTypeMappingSource = new SqlServerTypeMappingSource(
TestServiceFactory.Instance.Create(),
- TestServiceFactory.Instance.Create(),
- new SqlServerSingletonOptions());
+ TestServiceFactory.Instance.Create());
var sqlServerAnnotationCodeGenerator = new SqlServerAnnotationCodeGenerator(
new AnnotationCodeGeneratorDependencies(sqlServerTypeMappingSource));
@@ -452,8 +451,7 @@ public void Snapshot_with_enum_discriminator_uses_converted_values()
{
var sqlServerTypeMappingSource = new SqlServerTypeMappingSource(
TestServiceFactory.Instance.Create(),
- TestServiceFactory.Instance.Create(),
- new SqlServerSingletonOptions());
+ TestServiceFactory.Instance.Create());
var codeHelper = new CSharpHelper(
sqlServerTypeMappingSource);
@@ -510,8 +508,7 @@ private static void AssertConverter(ValueConverter valueConverter, string expect
var sqlServerTypeMappingSource = new SqlServerTypeMappingSource(
TestServiceFactory.Instance.Create(),
- TestServiceFactory.Instance.Create(),
- new SqlServerSingletonOptions());
+ TestServiceFactory.Instance.Create());
var codeHelper = new CSharpHelper(sqlServerTypeMappingSource);
diff --git a/test/EFCore.Design.Tests/Migrations/Design/MigrationScaffolderTest.cs b/test/EFCore.Design.Tests/Migrations/Design/MigrationScaffolderTest.cs
index efc9abacced..18c50430198 100644
--- a/test/EFCore.Design.Tests/Migrations/Design/MigrationScaffolderTest.cs
+++ b/test/EFCore.Design.Tests/Migrations/Design/MigrationScaffolderTest.cs
@@ -58,8 +58,7 @@ private IMigrationsScaffolder CreateMigrationScaffolder()
var idGenerator = new MigrationsIdGenerator();
var sqlServerTypeMappingSource = new SqlServerTypeMappingSource(
TestServiceFactory.Instance.Create(),
- TestServiceFactory.Instance.Create(),
- new SqlServerSingletonOptions());
+ TestServiceFactory.Instance.Create());
var sqlServerAnnotationCodeGenerator = new SqlServerAnnotationCodeGenerator(
new AnnotationCodeGeneratorDependencies(sqlServerTypeMappingSource));
var code = new CSharpHelper(sqlServerTypeMappingSource);
diff --git a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs
index 381b4adbb79..3a8caf1b3fe 100644
--- a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs
+++ b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs
@@ -7,7 +7,6 @@
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Migrations.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Design.Internal;
-using Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal;
using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal;
using NetTopologySuite;
@@ -66,6 +65,12 @@ private class EntityWithManyProperties
public MultiPolygon SpatialCMultiPolygon { get; set; }
public Point SpatialCPoint { get; set; }
public Polygon SpatialCPolygon { get; set; }
+ public int[] Int32Collection { get; set; }
+ public double[] DoubleCollection { get; set; }
+ public string[] StringCollection { get; set; }
+ public DateTime[] DateTimeCollection { get; set; }
+ public bool[] BoolCollection { get; set; }
+ public byte[][] BytesCollection { get; set; }
}
private enum Enum64 : long
@@ -5452,8 +5457,11 @@ public virtual void Complex_properties_are_stored_in_snapshot()
{
b.ComplexProperty(eo => eo.EntityWithTwoProperties, eb =>
{
+ eb.IsRequired();
eb.Property(e => e.AlternateId).HasColumnOrder(1);
- eb.ComplexProperty(e => e.EntityWithStringKey);
+ eb.ComplexProperty(e => e.EntityWithStringKey).IsRequired();
+ eb.HasPropertyAnnotation("PropertyAnnotation", 1);
+ eb.HasTypeAnnotation("TypeAnnotation", 2);
});
});
},
@@ -5470,6 +5478,8 @@ public virtual void Complex_properties_are_stored_in_snapshot()
b.ComplexProperty>("EntityWithTwoProperties", "Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithOneProperty.EntityWithTwoProperties#EntityWithTwoProperties", b1 =>
{
+ b1.IsRequired();
+
b1.Property("AlternateId")
.HasColumnType("int")
.HasColumnOrder(1);
@@ -5479,9 +5489,15 @@ public virtual void Complex_properties_are_stored_in_snapshot()
b1.ComplexProperty>("EntityWithStringKey", "Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithOneProperty.EntityWithTwoProperties#EntityWithTwoProperties.EntityWithStringKey#EntityWithStringKey", b2 =>
{
+ b2.IsRequired();
+
b2.Property("Id")
.HasColumnType("nvarchar(max)");
});
+
+ b1.HasPropertyAnnotation("PropertyAnnotation", 1);
+
+ b1.HasTypeAnnotation("TypeAnnotation", 2);
});
b.HasKey("Id");
@@ -5496,17 +5512,19 @@ public virtual void Complex_properties_are_stored_in_snapshot()
var complexProperty = entityWithOneProperty.FindComplexProperty(nameof(EntityWithOneProperty.EntityWithTwoProperties));
Assert.False(complexProperty.IsCollection);
- Assert.True(complexProperty.IsNullable);
+ Assert.False(complexProperty.IsNullable);
var complexType = complexProperty.ComplexType;
Assert.Equal("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithOneProperty.EntityWithTwoProperties#EntityWithTwoProperties", complexType.Name);
Assert.Equal("EntityWithOneProperty.EntityWithTwoProperties#EntityWithTwoProperties", complexType.DisplayName());
Assert.Equal(nameof(EntityWithOneProperty), complexType.GetTableName());
var alternateIdProperty = complexType.FindProperty(nameof(EntityWithTwoProperties.AlternateId));
Assert.Equal(1, alternateIdProperty.GetColumnOrder());
+ Assert.Equal(1, complexProperty["PropertyAnnotation"]);
+ Assert.Equal(2, complexProperty.ComplexType["TypeAnnotation"]);
var nestedComplexProperty = complexType.FindComplexProperty(nameof(EntityWithTwoProperties.EntityWithStringKey));
Assert.False(nestedComplexProperty.IsCollection);
- Assert.True(nestedComplexProperty.IsNullable);
+ Assert.False(nestedComplexProperty.IsNullable);
var nestedComplexType = nestedComplexProperty.ComplexType;
Assert.Equal("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithOneProperty.EntityWithTwoProperties#EntityWithTwoProperties.EntityWithStringKey#EntityWithStringKey", nestedComplexType.Name);
Assert.Equal("EntityWithOneProperty.EntityWithTwoProperties#EntityWithTwoProperties.EntityWithStringKey#EntityWithStringKey", nestedComplexType.DisplayName());
@@ -6191,6 +6209,117 @@ public virtual void IndexAttribute_IncludeProperties_generated_without_fluent_ap
Assert.Equal("Name", Assert.Single(index.GetIncludeProperties()));
});
+ [ConditionalFact]
+ public virtual void IndexAttribute_HasFillFactor_is_stored_in_snapshot()
+ => Test(
+ builder => builder.Entity(
+ x =>
+ {
+ x.HasIndex(e => e.Id).HasFillFactor(29);
+ }),
+ AddBoilerPlate(
+ GetHeading() +
+"""
+ modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringProperty", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Id");
+
+ SqlServerIndexBuilderExtensions.HasFillFactor(b.HasIndex("Id"), 29);
+
+ b.ToTable("EntityWithStringProperty", "DefaultSchema");
+ });
+"""),
+ model =>
+ {
+ var index = model.GetEntityTypes().First().GetIndexes().First();
+ Assert.Equal(29, index.GetFillFactor());
+ });
+
+ [ConditionalFact]
+ public virtual void IndexAttribute_UseDataCompression_is_stored_in_snapshot()
+ => Test(
+ builder => builder.Entity(
+ x =>
+ {
+ x.HasIndex(e => e.Id).UseDataCompression(DataCompressionType.Row);
+ }),
+ AddBoilerPlate(
+ GetHeading() +
+"""
+ modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringProperty", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Id");
+
+ SqlServerIndexBuilderExtensions.UseDataCompression(b.HasIndex("Id"), DataCompressionType.Row);
+
+ b.ToTable("EntityWithStringProperty", "DefaultSchema");
+ });
+"""),
+ model =>
+ {
+ var index = model.GetEntityTypes().First().GetIndexes().First();
+ Assert.Equal(DataCompressionType.Row, index.GetDataCompression());
+ });
+
+ [ConditionalFact]
+ public virtual void IndexAttribute_SortInTempDb_is_stored_in_snapshot()
+ => Test(
+ builder => builder.Entity(
+ x =>
+ {
+ x.HasIndex(e => e.Id).SortInTempDb(true);
+ }),
+ AddBoilerPlate(
+ GetHeading() +
+"""
+ modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithStringProperty", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Id");
+
+ SqlServerIndexBuilderExtensions.SortInTempDb(b.HasIndex("Id"), true);
+
+ b.ToTable("EntityWithStringProperty", "DefaultSchema");
+ });
+"""),
+ model =>
+ {
+ var index = model.GetEntityTypes().First().GetIndexes().First();
+ Assert.True(index.GetSortInTempDb());
+ });
+
#endregion
#region ForeignKey
@@ -7220,7 +7349,13 @@ static List getAllProperties(IModel model)
SpatialCMultiPoint = multiPoint,
SpatialCMultiPolygon = multiPolygon,
SpatialCPoint = point1,
- SpatialCPolygon = polygon1
+ SpatialCPolygon = polygon1,
+ Int32Collection = new[] { 1, 2, 3, 4 },
+ DoubleCollection = new[] { 1.2, 3.4 },
+ StringCollection = new[] { "AB", "CD" },
+ DateTimeCollection = new[] { new DateTime(2023, 9, 7), new DateTime(2023, 11, 14) },
+ BoolCollection = new[] { true, false },
+ BytesCollection = new[] { new byte[] { 1, 2 }, new byte[] { 3, 4 } }
},
new
{
@@ -7288,6 +7423,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+ b.Property("BoolCollection")
+ .HasColumnType("nvarchar(max)");
+
b.Property("Boolean")
.HasColumnType("bit");
@@ -7297,6 +7435,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("Bytes")
.HasColumnType("varbinary(max)");
+ b.Property("BytesCollection")
+ .HasColumnType("nvarchar(max)");
+
b.Property("Character")
.IsRequired()
.HasColumnType("nvarchar(1)");
@@ -7304,6 +7445,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("DateTime")
.HasColumnType("datetime2");
+ b.Property("DateTimeCollection")
+ .HasColumnType("nvarchar(max)");
+
b.Property("DateTimeOffset")
.HasColumnType("datetimeoffset");
@@ -7313,6 +7457,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("Double")
.HasColumnType("float");
+ b.Property("DoubleCollection")
+ .HasColumnType("nvarchar(max)");
+
b.Property("Enum16")
.HasColumnType("smallint");
@@ -7343,6 +7490,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("Int32")
.HasColumnType("int");
+ b.Property("Int32Collection")
+ .HasColumnType("nvarchar(max)");
+
b.Property("Int64")
.HasColumnType("bigint");
@@ -7400,6 +7550,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("String")
.HasColumnType("nvarchar(max)");
+ b.Property("StringCollection")
+ .HasColumnType("nvarchar(max)");
+
b.Property("TimeSpan")
.HasColumnType("time");
@@ -7420,14 +7573,18 @@ protected override void BuildModel(ModelBuilder modelBuilder)
new
{
Id = 42,
+ BoolCollection = "[true,false]",
Boolean = true,
Byte = (byte)55,
Bytes = new byte[] { 44, 45 },
+ BytesCollection = "[\"AQI=\",\"AwQ=\"]",
Character = "9",
DateTime = new DateTime(1973, 9, 3, 12, 10, 42, 344, DateTimeKind.Utc),
+ DateTimeCollection = "[\"2023-09-07T00:00:00\",\"2023-11-14T00:00:00\"]",
DateTimeOffset = new DateTimeOffset(new DateTime(1973, 9, 3, 12, 10, 42, 344, DateTimeKind.Unspecified), new TimeSpan(0, 1, 0, 0, 0)),
Decimal = 50.0m,
Double = 49.0,
+ DoubleCollection = "[1.2,3.4]",
Enum16 = (short)1,
Enum32 = 1,
Enum64 = 1L,
@@ -7438,6 +7595,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
EnumU64 = 1234567890123456789m,
Int16 = (short)46,
Int32 = 47,
+ Int32Collection = "[1,2,3,4]",
Int64 = 48L,
SignedByte = (short)60,
Single = 54f,
@@ -7456,6 +7614,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
SpatialCPoint = (NetTopologySuite.Geometries.Point)new NetTopologySuite.IO.WKTReader().Read("SRID=4326;POINT Z(1.1 2.2 3.3)"),
SpatialCPolygon = (NetTopologySuite.Geometries.Polygon)new NetTopologySuite.IO.WKTReader().Read("SRID=4326;POLYGON ((1.1 2.2, 2.2 2.2, 2.2 1.1, 1.1 2.2))"),
String = "FortyThree",
+ StringCollection = "[\"AB\",\"CD\"]",
TimeSpan = new TimeSpan(2, 3, 52, 53, 0),
UnsignedInt16 = 56,
UnsignedInt32 = 57L,
@@ -7583,6 +7742,13 @@ protected override void BuildModel(ModelBuilder modelBuilder)
Assert.Equal(4326, ((Geometry)seed["SpatialCMultiPolygon"]).SRID);
Assert.Equal(4326, ((Geometry)seed["SpatialCPoint"]).SRID);
Assert.Equal(4326, ((Geometry)seed["SpatialCPolygon"]).SRID);
+
+ Assert.Equal("[1,2,3,4]", seed["Int32Collection"]);
+ Assert.Equal("[1.2,3.4]", seed["DoubleCollection"]);
+ Assert.Equal("[\"AB\",\"CD\"]", seed["StringCollection"]);
+ Assert.Equal("[\"2023-09-07T00:00:00\",\"2023-11-14T00:00:00\"]", seed["DateTimeCollection"]);
+ Assert.Equal("[true,false]", seed["BoolCollection"]);
+ Assert.Equal("[\"AQI=\",\"AwQ=\"]", seed["BytesCollection"]);
},
seed =>
{
@@ -7769,8 +7935,7 @@ protected CSharpMigrationsGenerator CreateMigrationsGenerator()
new IRelationalTypeMappingSourcePlugin[]
{
new SqlServerNetTopologySuiteTypeMappingSourcePlugin(NtsGeometryServices.Instance)
- }),
- new SqlServerSingletonOptions());
+ }));
var codeHelper = new CSharpHelper(sqlServerTypeMappingSource);
diff --git a/test/EFCore.Design.Tests/Query/LinqToCSharpTranslatorTest.cs b/test/EFCore.Design.Tests/Query/LinqToCSharpTranslatorTest.cs
index e517ac61147..f814818f942 100644
--- a/test/EFCore.Design.Tests/Query/LinqToCSharpTranslatorTest.cs
+++ b/test/EFCore.Design.Tests/Query/LinqToCSharpTranslatorTest.cs
@@ -1835,8 +1835,7 @@ private void AssertCore(Expression expression, bool isStatement, string expected
{
var typeMappingSource = new SqlServerTypeMappingSource(
TestServiceFactory.Instance.Create(),
- new RelationalTypeMappingSourceDependencies(new IRelationalTypeMappingSourcePlugin[0]),
- new SqlServerSingletonOptions());
+ new RelationalTypeMappingSourceDependencies(new IRelationalTypeMappingSourcePlugin[0]));
var translator = new CSharpHelper(typeMappingSource);
var namespaces = new HashSet();
diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs
index 64a4194747a..a4449fc1e31 100644
--- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs
+++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs
@@ -5,6 +5,7 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
+using System.Net;
using System.Text.Json;
using Microsoft.EntityFrameworkCore.Cosmos.ValueGeneration.Internal;
using Microsoft.EntityFrameworkCore.Design.Internal;
@@ -2280,6 +2281,46 @@ private IRelationalModel CreateRelationalModel()
IsNullable = true
};
microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.Columns.Add("Point", pointColumnBase);
+ var refTypeArrayColumnBase = new ColumnBase("RefTypeArray", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.Columns.Add("RefTypeArray", refTypeArrayColumnBase);
+ var refTypeEnumerableColumnBase = new ColumnBase("RefTypeEnumerable", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.Columns.Add("RefTypeEnumerable", refTypeEnumerableColumnBase);
+ var refTypeIListColumnBase = new ColumnBase("RefTypeIList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.Columns.Add("RefTypeIList", refTypeIListColumnBase);
+ var refTypeListColumnBase = new ColumnBase("RefTypeList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.Columns.Add("RefTypeList", refTypeListColumnBase);
+ var valueTypeArrayColumnBase = new ColumnBase("ValueTypeArray", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.Columns.Add("ValueTypeArray", valueTypeArrayColumnBase);
+ var valueTypeEnumerableColumnBase = new ColumnBase("ValueTypeEnumerable", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.Columns.Add("ValueTypeEnumerable", valueTypeEnumerableColumnBase);
+ var valueTypeIListColumnBase = new ColumnBase("ValueTypeIList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.Columns.Add("ValueTypeIList", valueTypeIListColumnBase);
+ var valueTypeListColumnBase = new ColumnBase("ValueTypeList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.Columns.Add("ValueTypeList", valueTypeListColumnBase);
relationalModel.DefaultTables.Add("Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGeneratorTest+PrincipalBase", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase);
var microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase = new TableMappingBase(principalBase, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase, true);
microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseTableBase.AddTypeMapping(microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase, false);
@@ -2291,6 +2332,14 @@ private IRelationalModel CreateRelationalModel()
RelationalModel.CreateColumnMapping((ColumnBase)flagsEnum1ColumnBase, principalBase.FindProperty("FlagsEnum1")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
RelationalModel.CreateColumnMapping((ColumnBase)flagsEnum2ColumnBase, principalBase.FindProperty("FlagsEnum2")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
RelationalModel.CreateColumnMapping((ColumnBase)pointColumnBase, principalBase.FindProperty("Point")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeArrayColumnBase, principalBase.FindProperty("RefTypeArray")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeEnumerableColumnBase, principalBase.FindProperty("RefTypeEnumerable")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeIListColumnBase, principalBase.FindProperty("RefTypeIList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeListColumnBase, principalBase.FindProperty("RefTypeList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeArrayColumnBase, principalBase.FindProperty("ValueTypeArray")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeEnumerableColumnBase, principalBase.FindProperty("ValueTypeEnumerable")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeIListColumnBase, principalBase.FindProperty("ValueTypeIList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeListColumnBase, principalBase.FindProperty("ValueTypeList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase);
var tableMappings1 = new List();
principalBase.SetRuntimeAnnotation("Relational:TableMappings", tableMappings1);
@@ -2312,11 +2361,91 @@ private IRelationalModel CreateRelationalModel()
principalBaseTable.Columns.Add("FlagsEnum2", flagsEnum2Column);
var owned_NumberColumn = new Column("Owned_Number", "int", principalBaseTable);
principalBaseTable.Columns.Add("Owned_Number", owned_NumberColumn);
+ var owned_RefTypeArrayColumn = new Column("Owned_RefTypeArray", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("Owned_RefTypeArray", owned_RefTypeArrayColumn);
+ var owned_RefTypeEnumerableColumn = new Column("Owned_RefTypeEnumerable", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("Owned_RefTypeEnumerable", owned_RefTypeEnumerableColumn);
+ var owned_RefTypeIListColumn = new Column("Owned_RefTypeIList", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("Owned_RefTypeIList", owned_RefTypeIListColumn);
+ var owned_RefTypeListColumn = new Column("Owned_RefTypeList", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("Owned_RefTypeList", owned_RefTypeListColumn);
+ var owned_ValueTypeArrayColumn = new Column("Owned_ValueTypeArray", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("Owned_ValueTypeArray", owned_ValueTypeArrayColumn);
+ var owned_ValueTypeEnumerableColumn = new Column("Owned_ValueTypeEnumerable", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("Owned_ValueTypeEnumerable", owned_ValueTypeEnumerableColumn);
+ var owned_ValueTypeIListColumn = new Column("Owned_ValueTypeIList", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("Owned_ValueTypeIList", owned_ValueTypeIListColumn);
+ var owned_ValueTypeListColumn = new Column("Owned_ValueTypeList", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("Owned_ValueTypeList", owned_ValueTypeListColumn);
var pointColumn = new Column("Point", "geometry", principalBaseTable)
{
IsNullable = true
};
principalBaseTable.Columns.Add("Point", pointColumn);
+ var refTypeArrayColumn = new Column("RefTypeArray", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("RefTypeArray", refTypeArrayColumn);
+ var refTypeEnumerableColumn = new Column("RefTypeEnumerable", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("RefTypeEnumerable", refTypeEnumerableColumn);
+ var refTypeIListColumn = new Column("RefTypeIList", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("RefTypeIList", refTypeIListColumn);
+ var refTypeListColumn = new Column("RefTypeList", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("RefTypeList", refTypeListColumn);
+ var valueTypeArrayColumn = new Column("ValueTypeArray", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("ValueTypeArray", valueTypeArrayColumn);
+ var valueTypeEnumerableColumn = new Column("ValueTypeEnumerable", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("ValueTypeEnumerable", valueTypeEnumerableColumn);
+ var valueTypeIListColumn = new Column("ValueTypeIList", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("ValueTypeIList", valueTypeIListColumn);
+ var valueTypeListColumn = new Column("ValueTypeList", "nvarchar(max)", principalBaseTable)
+ {
+ IsNullable = true
+ };
+ principalBaseTable.Columns.Add("ValueTypeList", valueTypeListColumn);
var aK_PrincipalBase_Id = new UniqueConstraint("AK_PrincipalBase_Id", principalBaseTable, new[] { idColumn0 });
var aK_PrincipalBase_IdUc = RelationalModel.GetKey(this,
"Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGeneratorTest+PrincipalBase",
@@ -2359,6 +2488,14 @@ private IRelationalModel CreateRelationalModel()
RelationalModel.CreateColumnMapping(flagsEnum1Column, principalBase.FindProperty("FlagsEnum1")!, principalBaseTableMapping);
RelationalModel.CreateColumnMapping(flagsEnum2Column, principalBase.FindProperty("FlagsEnum2")!, principalBaseTableMapping);
RelationalModel.CreateColumnMapping(pointColumn, principalBase.FindProperty("Point")!, principalBaseTableMapping);
+ RelationalModel.CreateColumnMapping(refTypeArrayColumn, principalBase.FindProperty("RefTypeArray")!, principalBaseTableMapping);
+ RelationalModel.CreateColumnMapping(refTypeEnumerableColumn, principalBase.FindProperty("RefTypeEnumerable")!, principalBaseTableMapping);
+ RelationalModel.CreateColumnMapping(refTypeIListColumn, principalBase.FindProperty("RefTypeIList")!, principalBaseTableMapping);
+ RelationalModel.CreateColumnMapping(refTypeListColumn, principalBase.FindProperty("RefTypeList")!, principalBaseTableMapping);
+ RelationalModel.CreateColumnMapping(valueTypeArrayColumn, principalBase.FindProperty("ValueTypeArray")!, principalBaseTableMapping);
+ RelationalModel.CreateColumnMapping(valueTypeEnumerableColumn, principalBase.FindProperty("ValueTypeEnumerable")!, principalBaseTableMapping);
+ RelationalModel.CreateColumnMapping(valueTypeIListColumn, principalBase.FindProperty("ValueTypeIList")!, principalBaseTableMapping);
+ RelationalModel.CreateColumnMapping(valueTypeListColumn, principalBase.FindProperty("ValueTypeList")!, principalBaseTableMapping);
var ownedType = FindEntityType("Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGeneratorTest+PrincipalBase.Owned#OwnedType")!;
@@ -2376,6 +2513,46 @@ private IRelationalModel CreateRelationalModel()
microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("PrincipalBaseAlternateId", principalBaseAlternateIdColumnBase);
var principalBaseIdColumnBase = new ColumnBase("PrincipalBaseId", "bigint", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase);
microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("PrincipalBaseId", principalBaseIdColumnBase);
+ var refTypeArrayColumnBase0 = new ColumnBase("RefTypeArray", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("RefTypeArray", refTypeArrayColumnBase0);
+ var refTypeEnumerableColumnBase0 = new ColumnBase("RefTypeEnumerable", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("RefTypeEnumerable", refTypeEnumerableColumnBase0);
+ var refTypeIListColumnBase0 = new ColumnBase("RefTypeIList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("RefTypeIList", refTypeIListColumnBase0);
+ var refTypeListColumnBase0 = new ColumnBase("RefTypeList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("RefTypeList", refTypeListColumnBase0);
+ var valueTypeArrayColumnBase0 = new ColumnBase("ValueTypeArray", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("ValueTypeArray", valueTypeArrayColumnBase0);
+ var valueTypeEnumerableColumnBase0 = new ColumnBase("ValueTypeEnumerable", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("ValueTypeEnumerable", valueTypeEnumerableColumnBase0);
+ var valueTypeIListColumnBase0 = new ColumnBase("ValueTypeIList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("ValueTypeIList", valueTypeIListColumnBase0);
+ var valueTypeListColumnBase0 = new ColumnBase("ValueTypeList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.Columns.Add("ValueTypeList", valueTypeListColumnBase0);
relationalModel.DefaultTables.Add("Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGeneratorTest+PrincipalBase.Owned#OwnedType", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase);
var microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase = new TableMappingBase(ownedType, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase, true);
microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeTableBase.AddTypeMapping(microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase, false);
@@ -2384,6 +2561,14 @@ private IRelationalModel CreateRelationalModel()
RelationalModel.CreateColumnMapping((ColumnBase)principalBaseIdColumnBase, ownedType.FindProperty("PrincipalBaseId")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
RelationalModel.CreateColumnMapping((ColumnBase)detailsColumnBase, ownedType.FindProperty("Details")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
RelationalModel.CreateColumnMapping((ColumnBase)numberColumnBase, ownedType.FindProperty("Number")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeArrayColumnBase0, ownedType.FindProperty("RefTypeArray")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeEnumerableColumnBase0, ownedType.FindProperty("RefTypeEnumerable")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeIListColumnBase0, ownedType.FindProperty("RefTypeIList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeListColumnBase0, ownedType.FindProperty("RefTypeList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeArrayColumnBase0, ownedType.FindProperty("ValueTypeArray")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeEnumerableColumnBase0, ownedType.FindProperty("ValueTypeEnumerable")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeIListColumnBase0, ownedType.FindProperty("ValueTypeIList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeListColumnBase0, ownedType.FindProperty("ValueTypeList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseOwnedOwnedTypeMappingBase);
var tableMappings2 = new List();
ownedType.SetRuntimeAnnotation("Relational:TableMappings", tableMappings2);
@@ -2402,6 +2587,14 @@ private IRelationalModel CreateRelationalModel()
RelationalModel.CreateColumnMapping(alternateIdColumn, ownedType.FindProperty("PrincipalBaseAlternateId")!, principalBaseTableMapping0);
RelationalModel.CreateColumnMapping(idColumn0, ownedType.FindProperty("PrincipalBaseId")!, principalBaseTableMapping0);
RelationalModel.CreateColumnMapping(owned_NumberColumn, ownedType.FindProperty("Number")!, principalBaseTableMapping0);
+ RelationalModel.CreateColumnMapping(owned_RefTypeArrayColumn, ownedType.FindProperty("RefTypeArray")!, principalBaseTableMapping0);
+ RelationalModel.CreateColumnMapping(owned_RefTypeEnumerableColumn, ownedType.FindProperty("RefTypeEnumerable")!, principalBaseTableMapping0);
+ RelationalModel.CreateColumnMapping(owned_RefTypeIListColumn, ownedType.FindProperty("RefTypeIList")!, principalBaseTableMapping0);
+ RelationalModel.CreateColumnMapping(owned_RefTypeListColumn, ownedType.FindProperty("RefTypeList")!, principalBaseTableMapping0);
+ RelationalModel.CreateColumnMapping(owned_ValueTypeArrayColumn, ownedType.FindProperty("ValueTypeArray")!, principalBaseTableMapping0);
+ RelationalModel.CreateColumnMapping(owned_ValueTypeEnumerableColumn, ownedType.FindProperty("ValueTypeEnumerable")!, principalBaseTableMapping0);
+ RelationalModel.CreateColumnMapping(owned_ValueTypeIListColumn, ownedType.FindProperty("ValueTypeIList")!, principalBaseTableMapping0);
+ RelationalModel.CreateColumnMapping(owned_ValueTypeListColumn, ownedType.FindProperty("ValueTypeList")!, principalBaseTableMapping0);
var detailsTable = new Table("Details", null, relationalModel);
var principalBaseIdColumn = new Column("PrincipalBaseId", "bigint", detailsTable);
detailsTable.Columns.Add("PrincipalBaseId", principalBaseIdColumn);
@@ -2445,6 +2638,14 @@ private IRelationalModel CreateRelationalModel()
RelationalModel.CreateColumnMapping((ColumnBase)flagsEnum1ColumnBase, principalDerived.FindProperty("FlagsEnum1")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
RelationalModel.CreateColumnMapping((ColumnBase)flagsEnum2ColumnBase, principalDerived.FindProperty("FlagsEnum2")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
RelationalModel.CreateColumnMapping((ColumnBase)pointColumnBase, principalDerived.FindProperty("Point")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeArrayColumnBase, principalDerived.FindProperty("RefTypeArray")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeEnumerableColumnBase, principalDerived.FindProperty("RefTypeEnumerable")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeIListColumnBase, principalDerived.FindProperty("RefTypeIList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeListColumnBase, principalDerived.FindProperty("RefTypeList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeArrayColumnBase, principalDerived.FindProperty("ValueTypeArray")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeEnumerableColumnBase, principalDerived.FindProperty("ValueTypeEnumerable")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeIListColumnBase, principalDerived.FindProperty("ValueTypeIList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeListColumnBase, principalDerived.FindProperty("ValueTypeList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalBaseMappingBase0);
var defaultTableMappings4 = new List>();
principalDerived.SetRuntimeAnnotation("Relational:DefaultMappings", defaultTableMappings4);
@@ -2475,6 +2676,14 @@ private IRelationalModel CreateRelationalModel()
RelationalModel.CreateColumnMapping(flagsEnum1Column, principalDerived.FindProperty("FlagsEnum1")!, principalBaseTableMapping1);
RelationalModel.CreateColumnMapping(flagsEnum2Column, principalDerived.FindProperty("FlagsEnum2")!, principalBaseTableMapping1);
RelationalModel.CreateColumnMapping(pointColumn, principalDerived.FindProperty("Point")!, principalBaseTableMapping1);
+ RelationalModel.CreateColumnMapping(refTypeArrayColumn, principalDerived.FindProperty("RefTypeArray")!, principalBaseTableMapping1);
+ RelationalModel.CreateColumnMapping(refTypeEnumerableColumn, principalDerived.FindProperty("RefTypeEnumerable")!, principalBaseTableMapping1);
+ RelationalModel.CreateColumnMapping(refTypeIListColumn, principalDerived.FindProperty("RefTypeIList")!, principalBaseTableMapping1);
+ RelationalModel.CreateColumnMapping(refTypeListColumn, principalDerived.FindProperty("RefTypeList")!, principalBaseTableMapping1);
+ RelationalModel.CreateColumnMapping(valueTypeArrayColumn, principalDerived.FindProperty("ValueTypeArray")!, principalBaseTableMapping1);
+ RelationalModel.CreateColumnMapping(valueTypeEnumerableColumn, principalDerived.FindProperty("ValueTypeEnumerable")!, principalBaseTableMapping1);
+ RelationalModel.CreateColumnMapping(valueTypeIListColumn, principalDerived.FindProperty("ValueTypeIList")!, principalBaseTableMapping1);
+ RelationalModel.CreateColumnMapping(valueTypeListColumn, principalDerived.FindProperty("ValueTypeList")!, principalBaseTableMapping1);
var principalDerivedTable = new Table("PrincipalDerived", null, relationalModel);
var derivedIdColumn = new Column("DerivedId", "bigint", principalDerivedTable);
principalDerivedTable.Columns.Add("DerivedId", derivedIdColumn);
@@ -2528,6 +2737,46 @@ private IRelationalModel CreateRelationalModel()
microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("PrincipalDerived>AlternateId", principalDerivedDependentBasebyteAlternateIdColumnBase);
var principalDerivedDependentBasebyteIdColumnBase = new ColumnBase("PrincipalDerived>Id", "bigint", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase);
microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("PrincipalDerived>Id", principalDerivedDependentBasebyteIdColumnBase);
+ var refTypeArrayColumnBase1 = new ColumnBase("RefTypeArray", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("RefTypeArray", refTypeArrayColumnBase1);
+ var refTypeEnumerableColumnBase1 = new ColumnBase("RefTypeEnumerable", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("RefTypeEnumerable", refTypeEnumerableColumnBase1);
+ var refTypeIListColumnBase1 = new ColumnBase("RefTypeIList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("RefTypeIList", refTypeIListColumnBase1);
+ var refTypeListColumnBase1 = new ColumnBase("RefTypeList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("RefTypeList", refTypeListColumnBase1);
+ var valueTypeArrayColumnBase1 = new ColumnBase("ValueTypeArray", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("ValueTypeArray", valueTypeArrayColumnBase1);
+ var valueTypeEnumerableColumnBase1 = new ColumnBase("ValueTypeEnumerable", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("ValueTypeEnumerable", valueTypeEnumerableColumnBase1);
+ var valueTypeIListColumnBase1 = new ColumnBase("ValueTypeIList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("ValueTypeIList", valueTypeIListColumnBase1);
+ var valueTypeListColumnBase1 = new ColumnBase("ValueTypeList", "nvarchar(max)", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase)
+ {
+ IsNullable = true
+ };
+ microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.Columns.Add("ValueTypeList", valueTypeListColumnBase1);
relationalModel.DefaultTables.Add("Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGeneratorTest+PrincipalDerived>.ManyOwned#OwnedType", microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase);
var microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase = new TableMappingBase(ownedType0, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase, true);
microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeTableBase.AddTypeMapping(microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase, false);
@@ -2537,6 +2786,14 @@ private IRelationalModel CreateRelationalModel()
RelationalModel.CreateColumnMapping((ColumnBase)principalDerivedDependentBasebyteIdColumnBase, ownedType0.FindProperty("PrincipalDerivedId")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
RelationalModel.CreateColumnMapping((ColumnBase)detailsColumnBase0, ownedType0.FindProperty("Details")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
RelationalModel.CreateColumnMapping((ColumnBase)numberColumnBase0, ownedType0.FindProperty("Number")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeArrayColumnBase1, ownedType0.FindProperty("RefTypeArray")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeEnumerableColumnBase1, ownedType0.FindProperty("RefTypeEnumerable")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeIListColumnBase1, ownedType0.FindProperty("RefTypeIList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)refTypeListColumnBase1, ownedType0.FindProperty("RefTypeList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeArrayColumnBase1, ownedType0.FindProperty("ValueTypeArray")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeEnumerableColumnBase1, ownedType0.FindProperty("ValueTypeEnumerable")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeIListColumnBase1, ownedType0.FindProperty("ValueTypeIList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
+ RelationalModel.CreateColumnMapping((ColumnBase)valueTypeListColumnBase1, ownedType0.FindProperty("ValueTypeList")!, microsoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestPrincipalDerivedMicrosoftEntityFrameworkCoreScaffoldingInternalCSharpRuntimeModelCodeGeneratorTestDependentBasebyteManyOwnedOwnedTypeMappingBase);
var tableMappings4 = new List();
ownedType0.SetRuntimeAnnotation("Relational:TableMappings", tableMappings4);
@@ -2554,6 +2811,46 @@ private IRelationalModel CreateRelationalModel()
manyOwnedTable.Columns.Add("Details", detailsColumn0);
var numberColumn = new Column("Number", "int", manyOwnedTable);
manyOwnedTable.Columns.Add("Number", numberColumn);
+ var refTypeArrayColumn0 = new Column("RefTypeArray", "nvarchar(max)", manyOwnedTable)
+ {
+ IsNullable = true
+ };
+ manyOwnedTable.Columns.Add("RefTypeArray", refTypeArrayColumn0);
+ var refTypeEnumerableColumn0 = new Column("RefTypeEnumerable", "nvarchar(max)", manyOwnedTable)
+ {
+ IsNullable = true
+ };
+ manyOwnedTable.Columns.Add("RefTypeEnumerable", refTypeEnumerableColumn0);
+ var refTypeIListColumn0 = new Column("RefTypeIList", "nvarchar(max)", manyOwnedTable)
+ {
+ IsNullable = true
+ };
+ manyOwnedTable.Columns.Add("RefTypeIList", refTypeIListColumn0);
+ var refTypeListColumn0 = new Column("RefTypeList", "nvarchar(max)", manyOwnedTable)
+ {
+ IsNullable = true
+ };
+ manyOwnedTable.Columns.Add("RefTypeList", refTypeListColumn0);
+ var valueTypeArrayColumn0 = new Column("ValueTypeArray", "nvarchar(max)", manyOwnedTable)
+ {
+ IsNullable = true
+ };
+ manyOwnedTable.Columns.Add("ValueTypeArray", valueTypeArrayColumn0);
+ var valueTypeEnumerableColumn0 = new Column("ValueTypeEnumerable", "nvarchar(max)", manyOwnedTable)
+ {
+ IsNullable = true
+ };
+ manyOwnedTable.Columns.Add("ValueTypeEnumerable", valueTypeEnumerableColumn0);
+ var valueTypeIListColumn0 = new Column("ValueTypeIList", "nvarchar(max)", manyOwnedTable)
+ {
+ IsNullable = true
+ };
+ manyOwnedTable.Columns.Add("ValueTypeIList", valueTypeIListColumn0);
+ var valueTypeListColumn0 = new Column("ValueTypeList", "nvarchar(max)", manyOwnedTable)
+ {
+ IsNullable = true
+ };
+ manyOwnedTable.Columns.Add("ValueTypeList", valueTypeListColumn0);
var pK_ManyOwned = new UniqueConstraint("PK_ManyOwned", manyOwnedTable, new[] { principalDerivedDependentBasebyteIdColumn, principalDerivedDependentBasebyteAlternateIdColumn, idColumn1 });
manyOwnedTable.PrimaryKey = pK_ManyOwned;
var pK_ManyOwnedUc = RelationalModel.GetKey(this,
@@ -2571,6 +2868,14 @@ private IRelationalModel CreateRelationalModel()
RelationalModel.CreateColumnMapping(principalDerivedDependentBasebyteIdColumn, ownedType0.FindProperty("PrincipalDerivedId")!, manyOwnedTableMapping);
RelationalModel.CreateColumnMapping(detailsColumn0, ownedType0.FindProperty("Details")!, manyOwnedTableMapping);
RelationalModel.CreateColumnMapping(numberColumn, ownedType0.FindProperty("Number")!, manyOwnedTableMapping);
+ RelationalModel.CreateColumnMapping(refTypeArrayColumn0, ownedType0.FindProperty("RefTypeArray")!, manyOwnedTableMapping);
+ RelationalModel.CreateColumnMapping(refTypeEnumerableColumn0, ownedType0.FindProperty("RefTypeEnumerable")!, manyOwnedTableMapping);
+ RelationalModel.CreateColumnMapping(refTypeIListColumn0, ownedType0.FindProperty("RefTypeIList")!, manyOwnedTableMapping);
+ RelationalModel.CreateColumnMapping(refTypeListColumn0, ownedType0.FindProperty("RefTypeList")!, manyOwnedTableMapping);
+ RelationalModel.CreateColumnMapping(valueTypeArrayColumn0, ownedType0.FindProperty("ValueTypeArray")!, manyOwnedTableMapping);
+ RelationalModel.CreateColumnMapping(valueTypeEnumerableColumn0, ownedType0.FindProperty("ValueTypeEnumerable")!, manyOwnedTableMapping);
+ RelationalModel.CreateColumnMapping(valueTypeIListColumn0, ownedType0.FindProperty("ValueTypeIList")!, manyOwnedTableMapping);
+ RelationalModel.CreateColumnMapping(valueTypeListColumn0, ownedType0.FindProperty("ValueTypeList")!, manyOwnedTableMapping);
var principalBasePrincipalDerivedDependentBasebyte = FindEntityType("PrincipalBasePrincipalDerived>")!;
@@ -2937,6 +3242,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
//
using System;
using System.Collections.Generic;
+using System.Net;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
@@ -3149,60 +3455,444 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas
point.AddAnnotation("Relational:DefaultValue", (NetTopologySuite.Geometries.Point)new NetTopologySuite.IO.WKTReader().Read("SRID=0;POINT Z(0 0 0)"));
point.AddAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.None);
- var key = runtimeEntityType.AddKey(
- new[] { id });
-
- var key0 = runtimeEntityType.AddKey(
- new[] { id, alternateId });
- runtimeEntityType.SetPrimaryKey(key0);
- key0.AddAnnotation("Relational:Name", "PK");
-
- var index = runtimeEntityType.AddIndex(
- new[] { alternateId, id });
-
- return runtimeEntityType;
- }
-
- public static RuntimeSkipNavigation CreateSkipNavigation1(RuntimeEntityType declaringEntityType, RuntimeEntityType targetEntityType, RuntimeEntityType joinEntityType)
- {
- var skipNavigation = declaringEntityType.AddSkipNavigation(
- "Deriveds",
- targetEntityType,
- joinEntityType.FindForeignKey(
- new[] { joinEntityType.FindProperty("PrincipalsId"), joinEntityType.FindProperty("PrincipalsAlternateId") },
- declaringEntityType.FindKey(new[] { declaringEntityType.FindProperty("Id"), declaringEntityType.FindProperty("AlternateId") }),
- declaringEntityType),
- true,
- false,
- typeof(ICollection),
- propertyInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetProperty("Deriveds", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
- fieldInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
-
- var inverse = targetEntityType.FindSkipNavigation("Principals");
- if (inverse != null)
- {
- skipNavigation.Inverse = inverse;
- inverse.Inverse = skipNavigation;
- }
+ var refTypeArray = runtimeEntityType.AddProperty(
+ "RefTypeArray",
+ typeof(IPAddress[]),
+ propertyInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetProperty("RefTypeArray", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+ refTypeArray.TypeMapping = SqlServerStringTypeMapping.Default.Clone(
+ comparer: new ListComparer(new ValueComparer(
+ (IPAddress v1, IPAddress v2) => v1 == null && v2 == null || v1 != null && v2 != null && v1.Equals(v2),
+ (IPAddress v) => v.GetHashCode(),
+ (IPAddress v) => v)),
+ keyComparer: new ListComparer(new ValueComparer(
+ (IPAddress v1, IPAddress v2) => v1 == null && v2 == null || v1 != null && v2 != null && v1.Equals(v2),
+ (IPAddress v) => v.GetHashCode(),
+ (IPAddress v) => v)),
+ providerValueComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+ mappingInfo: new RelationalTypeMappingInfo(
+ storeTypeName: "nvarchar(max)",
+ dbType: System.Data.DbType.String),
+ converter: new CollectionToJsonStringConverter(new JsonCollectionReaderWriter(
+ new JsonConvertedValueReaderWriter(
+ JsonStringReaderWriter.Instance,
+ new ValueConverter(
+ (IPAddress v) => v.ToString(),
+ (string v) => IPAddress.Parse(v))))),
+ storeTypePostfix: StoreTypePostfix.None,
+ jsonValueReaderWriter: new JsonCollectionReaderWriter(
+ new JsonConvertedValueReaderWriter(
+ JsonStringReaderWriter.Instance,
+ new ValueConverter(
+ (IPAddress v) => v.ToString(),
+ (string v) => IPAddress.Parse(v)))),
+ elementMapping: SqlServerStringTypeMapping.Default.Clone(
+ comparer: new ValueComparer(
+ (IPAddress v1, IPAddress v2) => v1 == null && v2 == null || v1 != null && v2 != null && v1.Equals(v2),
+ (IPAddress v) => v.GetHashCode(),
+ (IPAddress v) => v),
+ keyComparer: new ValueComparer(
+ (IPAddress v1, IPAddress v2) => v1 == null && v2 == null || v1 != null && v2 != null && v1.Equals(v2),
+ (IPAddress v) => v.GetHashCode(),
+ (IPAddress v) => v),
+ providerValueComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+ mappingInfo: new RelationalTypeMappingInfo(
+ storeTypeName: "nvarchar(45)",
+ size: 45,
+ dbType: System.Data.DbType.String),
+ converter: new ValueConverter(
+ (IPAddress v) => v.ToString(),
+ (string v) => IPAddress.Parse(v)),
+ jsonValueReaderWriter: new JsonConvertedValueReaderWriter(
+ JsonStringReaderWriter.Instance,
+ new ValueConverter(
+ (IPAddress v) => v.ToString(),
+ (string v) => IPAddress.Parse(v)))));
+refTypeArray.AddAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.None);
+
+var refTypeEnumerable = runtimeEntityType.AddProperty(
+ "RefTypeEnumerable",
+ typeof(IEnumerable),
+ propertyInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetProperty("RefTypeEnumerable", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+refTypeEnumerable.TypeMapping = SqlServerStringTypeMapping.Default.Clone(
+ comparer: new ListComparer(new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v)),
+keyComparer: new ListComparer(new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v)),
+providerValueComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+mappingInfo: new RelationalTypeMappingInfo(
+ storeTypeName: "nvarchar(max)",
+ dbType: System.Data.DbType.String),
+converter: new CollectionToJsonStringConverter(new JsonCollectionReaderWriter, List, string>(
+ JsonStringReaderWriter.Instance)),
+storeTypePostfix: StoreTypePostfix.None,
+jsonValueReaderWriter: new JsonCollectionReaderWriter, List, string>(
+ JsonStringReaderWriter.Instance),
+elementMapping: SqlServerStringTypeMapping.Default.Clone(
+ comparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+ keyComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+ providerValueComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+ mappingInfo: new RelationalTypeMappingInfo(
+ storeTypeName: "nvarchar(max)",
+ dbType: System.Data.DbType.String),
+ storeTypePostfix: StoreTypePostfix.None));
+refTypeEnumerable.AddAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.None);
+
+var refTypeIList = runtimeEntityType.AddProperty(
+ "RefTypeIList",
+ typeof(IList),
+ propertyInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetProperty("RefTypeIList", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+refTypeIList.TypeMapping = SqlServerStringTypeMapping.Default.Clone(
+ comparer: new ListComparer(new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v)),
+keyComparer: new ListComparer(new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v)),
+providerValueComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+mappingInfo: new RelationalTypeMappingInfo(
+ storeTypeName: "nvarchar(max)",
+ dbType: System.Data.DbType.String),
+converter: new CollectionToJsonStringConverter(new JsonCollectionReaderWriter, List, string>(
+ JsonStringReaderWriter.Instance)),
+storeTypePostfix: StoreTypePostfix.None,
+jsonValueReaderWriter: new JsonCollectionReaderWriter, List, string>(
+ JsonStringReaderWriter.Instance),
+elementMapping: SqlServerStringTypeMapping.Default.Clone(
+ comparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+ keyComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+ providerValueComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+ mappingInfo: new RelationalTypeMappingInfo(
+ storeTypeName: "nvarchar(max)",
+ dbType: System.Data.DbType.String),
+ storeTypePostfix: StoreTypePostfix.None));
+refTypeIList.AddAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.None);
+
+var refTypeList = runtimeEntityType.AddProperty(
+ "RefTypeList",
+ typeof(List),
+ propertyInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetProperty("RefTypeList", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+refTypeList.TypeMapping = SqlServerStringTypeMapping.Default.Clone(
+ comparer: new ListComparer(new ValueComparer(
+ (IPAddress v1, IPAddress v2) => v1 == null && v2 == null || v1 != null && v2 != null && v1.Equals(v2),
+ (IPAddress v) => v.GetHashCode(),
+ (IPAddress v) => v)),
+keyComparer: new ListComparer(new ValueComparer(
+ (IPAddress v1, IPAddress v2) => v1 == null && v2 == null || v1 != null && v2 != null && v1.Equals(v2),
+ (IPAddress v) => v.GetHashCode(),
+ (IPAddress v) => v)),
+providerValueComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+mappingInfo: new RelationalTypeMappingInfo(
+ storeTypeName: "nvarchar(max)",
+ dbType: System.Data.DbType.String),
+converter: new CollectionToJsonStringConverter(new JsonCollectionReaderWriter, List, IPAddress>(
+ new JsonConvertedValueReaderWriter(
+ JsonStringReaderWriter.Instance,
+ new ValueConverter(
+ (IPAddress v) => v.ToString(),
+ (string v) => IPAddress.Parse(v))))),
+storeTypePostfix: StoreTypePostfix.None,
+jsonValueReaderWriter: new JsonCollectionReaderWriter, List, IPAddress>(
+ new JsonConvertedValueReaderWriter(
+ JsonStringReaderWriter.Instance,
+ new ValueConverter(
+ (IPAddress v) => v.ToString(),
+ (string v) => IPAddress.Parse(v)))),
+elementMapping: SqlServerStringTypeMapping.Default.Clone(
+ comparer: new ValueComparer(
+ (IPAddress v1, IPAddress v2) => v1 == null && v2 == null || v1 != null && v2 != null && v1.Equals(v2),
+ (IPAddress v) => v.GetHashCode(),
+ (IPAddress v) => v),
+ keyComparer: new ValueComparer(
+ (IPAddress v1, IPAddress v2) => v1 == null && v2 == null || v1 != null && v2 != null && v1.Equals(v2),
+ (IPAddress v) => v.GetHashCode(),
+ (IPAddress v) => v),
+ providerValueComparer: new ValueComparer(
+ (string v1, string v2) => v1 == v2,
+ (string v) => v.GetHashCode(),
+ (string v) => v),
+ mappingInfo: new RelationalTypeMappingInfo(
+ storeTypeName: "nvarchar(45)",
+ size: 45,
+ dbType: System.Data.DbType.String),
+ converter: new ValueConverter(
+ (IPAddress v) => v.ToString(),
+ (string v) => IPAddress.Parse(v)),
+ jsonValueReaderWriter: new JsonConvertedValueReaderWriter(
+ JsonStringReaderWriter.Instance,
+ new ValueConverter(
+ (IPAddress v) => v.ToString(),
+ (string v) => IPAddress.Parse(v)))));
+refTypeList.AddAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.None);
+
+var valueTypeArray = runtimeEntityType.AddProperty(
+ "ValueTypeArray",
+ typeof(DateTime[]),
+ propertyInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetProperty("ValueTypeArray", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ fieldInfo: typeof(CSharpRuntimeModelCodeGeneratorTest.PrincipalBase).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
+ nullable: true);
+valueTypeArray.TypeMapping = SqlServerStringTypeMapping.Default.Clone(
+ comparer: new ListComparer(new ValueComparer(
+ (DateTime v1, DateTime v2) => v1.Equals(v2),
+ (DateTime v) => v.GetHashCode(),
+ (DateTime v) => v)),
+keyComparer: new ListComparer(new ValueComparer