From b9e48b8033b33254229450b4d7c6066ba5ee5372 Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Tue, 3 Aug 2021 21:03:44 +0000 Subject: [PATCH 001/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions --- NuGet.config | 5 +- eng/Version.Details.xml | 236 ++++++++++++++++++++-------------------- eng/Versions.props | 14 +-- 3 files changed, 128 insertions(+), 127 deletions(-) diff --git a/NuGet.config b/NuGet.config index a5cc91700ba..7830165582c 100644 --- a/NuGet.config +++ b/NuGet.config @@ -7,7 +7,7 @@ - + @@ -22,13 +22,14 @@ - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b57468623b1..6eab09722d0 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 @@ -122,145 +122,145 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 9130c4bf47c4920f1f3dffb7504119c367b83808 + ac2546e5d35c297cb8380acdca6b872badf1faf7 https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup diff --git a/eng/Versions.props b/eng/Versions.props index 7220f4df354..1dbaaa70c66 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -32,13 +32,13 @@ 1.1.3 - 3.1.18 - 3.1.18 - 3.1.18 - 3.1.18 - 3.1.18 - 3.1.18-servicing.21364.3 - 3.1.18 + 3.1.19 + 3.1.19 + 3.1.19 + 3.1.19 + 3.1.19 + 3.1.19-servicing.21403.4 + 3.1.19 1.1.1 From 7235bfe030ad36a52a2f1925135b549428e2c845 Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Wed, 4 Aug 2021 04:51:04 +0000 Subject: [PATCH 002/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions - Coherency Updates: - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Internal: from 3.1.18-servicing.21364.2 to 3.1.19-servicing.21403.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.18 to 3.1.19 (parent: Microsoft.Extensions.Logging) --- NuGet.config | 7 +- eng/Version.Details.xml | 150 ++++++++++++++++++++-------------------- eng/Versions.props | 6 +- 3 files changed, 82 insertions(+), 81 deletions(-) diff --git a/NuGet.config b/NuGet.config index 7830165582c..4b7a1bb33b9 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,10 +4,10 @@ - + - + @@ -22,12 +22,13 @@ - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 6eab09722d0..1cab5c6350f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a @@ -124,151 +124,151 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ac2546e5d35c297cb8380acdca6b872badf1faf7 + a4a96ed434a2560a5e820c84563b45f541e5a55a - + https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - 5d3919d34e0d8940ee50c36d823ddc28d6b1723c + 99ed3ce6cba19f46c50dbef34c3ef54df2f09bf4 - + https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - 5d3919d34e0d8940ee50c36d823ddc28d6b1723c + 99ed3ce6cba19f46c50dbef34c3ef54df2f09bf4 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx diff --git a/eng/Versions.props b/eng/Versions.props index 1dbaaa70c66..a501e80490e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 3.1.19 3.1.19 3.1.19 - 3.1.19-servicing.21403.4 + 3.1.19-servicing.21403.12 3.1.19 @@ -55,8 +55,8 @@ 3.1.6 3.1.6 3.1.0 - 3.1.18 - 3.1.18-servicing.21364.2 + 3.1.19 + 3.1.19-servicing.21403.19 2.1.0 From 4985f1c96a475be1f62a63594d31bcaf13afd89e Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Tue, 10 Aug 2021 22:16:52 +0000 Subject: [PATCH 003/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions --- NuGet.config | 5 +- eng/Version.Details.xml | 142 ++++++++++++++++++++-------------------- eng/Versions.props | 2 +- 3 files changed, 75 insertions(+), 74 deletions(-) diff --git a/NuGet.config b/NuGet.config index 4b7a1bb33b9..d249b76c1b5 100644 --- a/NuGet.config +++ b/NuGet.config @@ -7,7 +7,7 @@ - + @@ -22,13 +22,14 @@ - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 070606f19a8..dc8af023c1b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 @@ -124,143 +124,143 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - a4a96ed434a2560a5e820c84563b45f541e5a55a + 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup diff --git a/eng/Versions.props b/eng/Versions.props index a501e80490e..96c519197bd 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 3.1.19 3.1.19 3.1.19 - 3.1.19-servicing.21403.12 + 3.1.19-servicing.21410.2 3.1.19 From 94e141207377feb03f5a377a678066b6d8fe6c34 Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Wed, 11 Aug 2021 00:27:09 +0000 Subject: [PATCH 004/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions - Coherency Updates: - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Internal: from 3.1.19-servicing.21403.19 to 3.1.19-servicing.21410.1 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) --- NuGet.config | 7 +- eng/Version.Details.xml | 148 ++++++++++++++++++++-------------------- eng/Versions.props | 4 +- 3 files changed, 80 insertions(+), 79 deletions(-) diff --git a/NuGet.config b/NuGet.config index d249b76c1b5..186a37424a4 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,10 +4,10 @@ - + - + @@ -22,12 +22,13 @@ - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index dc8af023c1b..29f3be4397c 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c @@ -124,151 +124,151 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 8a21c2ff85c0ddf723279fb4ec1de1f3c57f2b27 + 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - 99ed3ce6cba19f46c50dbef34c3ef54df2f09bf4 + 3e99273a3e776c124c764c64946ca962b3928ed0 - + https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - 99ed3ce6cba19f46c50dbef34c3ef54df2f09bf4 + 3e99273a3e776c124c764c64946ca962b3928ed0 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx diff --git a/eng/Versions.props b/eng/Versions.props index 96c519197bd..59d3764790f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 3.1.19 3.1.19 3.1.19 - 3.1.19-servicing.21410.2 + 3.1.19-servicing.21410.5 3.1.19 @@ -56,7 +56,7 @@ 3.1.6 3.1.0 3.1.19 - 3.1.19-servicing.21403.19 + 3.1.19-servicing.21410.1 2.1.0 From 085c7b58d2c6f014cdfdfa5f8df3cc4e477049c3 Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Tue, 17 Aug 2021 01:56:21 +0000 Subject: [PATCH 005/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions - Coherency Updates: - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Internal: from 3.1.19-servicing.21410.1 to 3.1.19-servicing.21416.10 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) --- NuGet.config | 7 +- eng/Version.Details.xml | 148 ++++++++++++++++++++-------------------- eng/Versions.props | 4 +- 3 files changed, 80 insertions(+), 79 deletions(-) diff --git a/NuGet.config b/NuGet.config index 186a37424a4..d285f996aff 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,10 +4,10 @@ - + - + @@ -22,12 +22,13 @@ - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 29f3be4397c..96501f734d4 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 @@ -124,151 +124,151 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 7b5adda864f7cccfed2f8ca2a750ea5e75d7548c + ccfdfb73c194c6cef6916f04251a39324efaf4c7 https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - 3e99273a3e776c124c764c64946ca962b3928ed0 + acb8b2014507b701147440f09325d43f4139ae8d - + https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - 3e99273a3e776c124c764c64946ca962b3928ed0 + acb8b2014507b701147440f09325d43f4139ae8d https://dev.azure.com/dnceng/internal/_git/dotnet-corefx diff --git a/eng/Versions.props b/eng/Versions.props index 59d3764790f..af9679a3ec9 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 3.1.19 3.1.19 3.1.19 - 3.1.19-servicing.21410.5 + 3.1.19-servicing.21416.6 3.1.19 @@ -56,7 +56,7 @@ 3.1.6 3.1.0 3.1.19 - 3.1.19-servicing.21410.1 + 3.1.19-servicing.21416.10 2.1.0 From c1b838037dc69424cf5ff97951c1e916fe5aaefa Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Tue, 17 Aug 2021 17:01:45 +0000 Subject: [PATCH 006/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions - Coherency Updates: - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Internal: from 3.1.19-servicing.21416.10 to 3.1.19-servicing.21416.14 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.19 to 3.1.19 (parent: Microsoft.Extensions.Logging) --- NuGet.config | 7 +- eng/Version.Details.xml | 148 ++++++++++++++++++++-------------------- eng/Versions.props | 4 +- 3 files changed, 80 insertions(+), 79 deletions(-) diff --git a/NuGet.config b/NuGet.config index d285f996aff..af2bce58f31 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,10 +4,10 @@ - + - + @@ -22,12 +22,13 @@ - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 96501f734d4..10f5b0e01a9 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 @@ -124,151 +124,151 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - ccfdfb73c194c6cef6916f04251a39324efaf4c7 + 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - acb8b2014507b701147440f09325d43f4139ae8d + aae002469c4fe298a532e11faa01378048840aa9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - acb8b2014507b701147440f09325d43f4139ae8d + aae002469c4fe298a532e11faa01378048840aa9 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx diff --git a/eng/Versions.props b/eng/Versions.props index af9679a3ec9..a4cb81f3d25 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 3.1.19 3.1.19 3.1.19 - 3.1.19-servicing.21416.6 + 3.1.19-servicing.21417.2 3.1.19 @@ -56,7 +56,7 @@ 3.1.6 3.1.0 3.1.19 - 3.1.19-servicing.21416.10 + 3.1.19-servicing.21416.14 2.1.0 From 0ae7b96ef2eb20ce7cf31513c0c1cb879d941bbb Mon Sep 17 00:00:00 2001 From: hfpt Date: Sun, 22 Aug 2021 22:53:46 -0500 Subject: [PATCH 007/346] Query: add translation for string.IndexOf(string, int) #25396 --- .../SqlServerStringMethodTranslator.cs | 102 +++++++++++------- .../Query/NorthwindFunctionsQueryTestBase.cs | 9 ++ .../NorthwindFunctionsQuerySqlServerTest.cs | 19 +++- 3 files changed, 89 insertions(+), 41 deletions(-) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index 09f1635d443..f5777c77ae7 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -24,6 +24,9 @@ public class SqlServerStringMethodTranslator : IMethodCallTranslator private static readonly MethodInfo _indexOfMethodInfo = typeof(string).GetRequiredRuntimeMethod(nameof(string.IndexOf), new[] { typeof(string) }); + private static readonly MethodInfo _indexOfMethodInfoWithStartingPosition + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IndexOf), new[] { typeof(string), typeof(int) }); + private static readonly MethodInfo _replaceMethodInfo = typeof(string).GetRequiredRuntimeMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) }); @@ -120,46 +123,12 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor { if (_indexOfMethodInfo.Equals(method)) { - var argument = arguments[0]; - var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument)!; - argument = _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping); - - SqlExpression charIndexExpression; - var storeType = stringTypeMapping.StoreType; - if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) - || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) - { - charIndexExpression = _sqlExpressionFactory.Function( - "CHARINDEX", - new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, - nullable: true, - argumentsPropagateNullability: new[] { true, true }, - typeof(long)); - - charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); - } - else - { - charIndexExpression = _sqlExpressionFactory.Function( - "CHARINDEX", - new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, - nullable: true, - argumentsPropagateNullability: new[] { true, true }, - method.ReturnType); - } - - charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); + return TranslateIndexOf(instance, method, arguments[0], null); + } - return _sqlExpressionFactory.Case( - new[] - { - new CaseWhenClause( - _sqlExpressionFactory.Equal( - argument, - _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), - _sqlExpressionFactory.Constant(0)) - }, - charIndexExpression); + if (_indexOfMethodInfoWithStartingPosition.Equals(method)) + { + return TranslateIndexOf(instance, method, arguments[0], arguments[1]); } if (_replaceMethodInfo.Equals(method)) @@ -470,6 +439,61 @@ private SqlExpression TranslateStartsEndsWith(SqlExpression instance, SqlExpress pattern); } + private SqlExpression TranslateIndexOf(SqlExpression instance, MethodInfo method, SqlExpression searchExpression, SqlExpression? startIndex) + { + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, searchExpression)!; + searchExpression = _sqlExpressionFactory.ApplyTypeMapping(searchExpression, stringTypeMapping); + + SqlExpression[] charIndexArguments; + if (startIndex == null) + { + charIndexArguments = new[] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }; + } + else + { + var startIndexSql = _sqlExpressionFactory.Add(startIndex, _sqlExpressionFactory.Constant(1)); + charIndexArguments = new[] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), startIndexSql }; + } + + SqlExpression charIndexExpression; + var storeType = stringTypeMapping.StoreType; + if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) + || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) + { + charIndexExpression = _sqlExpressionFactory.Function( + "CHARINDEX", + charIndexArguments, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + typeof(long)); + + charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); + } + else + { + charIndexExpression = _sqlExpressionFactory.Function( + "CHARINDEX", + charIndexArguments, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + method.ReturnType); + } + + charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); + + return _sqlExpressionFactory.Case( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.Equal( + searchExpression, + _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), + _sqlExpressionFactory.Constant(0)) + }, + charIndexExpression); + } + + // See https://docs.microsoft.com/en-us/sql/t-sql/language-elements/like-transact-sql private bool IsLikeWildChar(char c) => c == '%' || c == '_' || c == '['; diff --git a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs index 319710d4572..c6150057b91 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs @@ -1528,6 +1528,15 @@ public virtual Task Indexof_with_emptystring(bool async) ss => ss.Set().Where(c => c.CustomerID == "ALFKI").Select(c => c.ContactName.IndexOf(string.Empty))); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Indexof_with_one_arg(bool async) + { + return AssertQueryScalar( + async, + ss => ss.Set().Where(c => c.CustomerID == "ALFKI").Select(c => c.ContactName.IndexOf("a"))); + } + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Indexof_with_starting_position(bool async) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs index 1b742e7e9a3..599edb3875b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs @@ -1498,13 +1498,28 @@ FROM [Customers] AS [c] WHERE [c].[CustomerID] = N'ALFKI'"); } - [ConditionalTheory(Skip = "issue #25396")] + public override async Task Indexof_with_one_arg(bool async) + { + await base.Indexof_with_one_arg(async); + + AssertSql( + @"SELECT CASE + WHEN N'a' = N'' THEN 0 + ELSE CAST(CHARINDEX(N'a', [c].[ContactName]) AS int) - 1 +END +FROM [Customers] AS [c] +WHERE [c].[CustomerID] = N'ALFKI'"); + } + public override async Task Indexof_with_starting_position(bool async) { await base.Indexof_with_starting_position(async); AssertSql( - @"SELECT [c].[ContactName] + @"SELECT CASE + WHEN N'a' = N'' THEN 0 + ELSE CAST(CHARINDEX(N'a', [c].[ContactName], 3 + 1) AS int) - 1 +END FROM [Customers] AS [c] WHERE [c].[CustomerID] = N'ALFKI'"); } From 8b4acc4ed642ba9cfca69ed5d7b17ee7c349acb2 Mon Sep 17 00:00:00 2001 From: hfpt Date: Sat, 28 Aug 2021 10:09:52 -0500 Subject: [PATCH 008/346] replace == null with is null --- .../Query/Internal/SqlServerStringMethodTranslator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index f5777c77ae7..56960417fa1 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -445,7 +445,7 @@ private SqlExpression TranslateIndexOf(SqlExpression instance, MethodInfo method searchExpression = _sqlExpressionFactory.ApplyTypeMapping(searchExpression, stringTypeMapping); SqlExpression[] charIndexArguments; - if (startIndex == null) + if (startIndex is null) { charIndexArguments = new[] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }; } From d0b96865813d21bf56eed52c132ac2a6759c1a4a Mon Sep 17 00:00:00 2001 From: maumar Date: Fri, 27 Aug 2021 13:43:47 -0700 Subject: [PATCH 009/346] Adding regression tests for some issues fixed earlier Resolves #13560 Resolves #17364 Resolves #17803 Resolves #21078 Resolves #21828 Resolves #23041 --- .../Query/InheritanceQueryCosmosTest.cs | 5 +- ...NorthwindKeylessEntitiesQueryCosmosTest.cs | 8 ++ ...rthwindKeylessEntitiesQueryInMemoryTest.cs | 9 +- ...dKeylessEntitiesQueryRelationalTestBase.cs | 20 ++++ ...plexNavigationsCollectionsQueryTestBase.cs | 75 ++++++++++++++ ...tionsCollectionsSharedTypeQueryTestBase.cs | 5 +- ...mplexNavigationsSharedTypeQueryTestBase.cs | 50 ++-------- .../Query/InheritanceQueryTestBase.cs | 2 +- .../NorthwindKeylessEntitiesQueryTestBase.cs | 4 +- ...avigationsCollectionsQuerySqlServerTest.cs | 83 ++++++++++++++++ ...tionsCollectionsSplitQuerySqlServerTest.cs | 97 +++++++++++++++++++ .../Query/InheritanceQuerySqlServerTest.cs | 20 ++++ ...thwindKeylessEntitiesQuerySqlServerTest.cs | 15 --- .../Query/TPTInheritanceQuerySqlServerTest.cs | 6 +- ...exNavigationsCollectionsQuerySqliteTest.cs | 12 +++ ...onsCollectionsSharedTypeQuerySqliteTest.cs | 12 +++ ...igationsCollectionsSplitQuerySqliteTest.cs | 12 +++ ...llectionsSplitSharedTypeQuerySqliteTest.cs | 12 +++ 18 files changed, 383 insertions(+), 64 deletions(-) diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs index 5cdc7e0e899..fe6130d1d1a 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs @@ -166,7 +166,10 @@ public override async Task Can_use_backwards_of_type_animal(bool async) { await base.Can_use_backwards_of_type_animal(async); - AssertSql(" "); + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] = ""Kiwi"")"); } public override async Task Can_use_of_type_rose(bool async) diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindKeylessEntitiesQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindKeylessEntitiesQueryCosmosTest.cs index 610c37531da..5d2fefe070d 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindKeylessEntitiesQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindKeylessEntitiesQueryCosmosTest.cs @@ -136,6 +136,14 @@ where ov.Customer.Orders.Any() AssertSql(@""); } + [ConditionalTheory(Skip = "issue#17314")] // left join translation + public override async Task KeylessEntity_with_included_navs_multi_level(bool async) + { + await base.KeylessEntity_with_included_navs_multi_level(async); + + AssertSql(@""); + } + [ConditionalTheory(Skip = "Issue #17246")] public override async Task KeylessEntity_groupby(bool async) { diff --git a/test/EFCore.InMemory.FunctionalTests/Query/NorthwindKeylessEntitiesQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/NorthwindKeylessEntitiesQueryInMemoryTest.cs index 2558ff13cbf..89d9e626c70 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/NorthwindKeylessEntitiesQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/NorthwindKeylessEntitiesQueryInMemoryTest.cs @@ -33,7 +33,14 @@ public override void Entity_mapped_to_view_on_right_side_of_join() public override async Task KeylessEntity_with_included_nav(bool async) { - await Assert.ThrowsAsync(() => base.KeylessEntity_with_included_nav(async)); + await Assert.ThrowsAsync( + () => base.KeylessEntity_with_included_nav(async)); + } + + public override async Task KeylessEntity_with_included_navs_multi_level(bool async) + { + await Assert.ThrowsAsync( + () => base.KeylessEntity_with_included_navs_multi_level(async)); } } } diff --git a/test/EFCore.Relational.Specification.Tests/Query/NorthwindKeylessEntitiesQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NorthwindKeylessEntitiesQueryRelationalTestBase.cs index 5798111865d..df02b4129be 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NorthwindKeylessEntitiesQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NorthwindKeylessEntitiesQueryRelationalTestBase.cs @@ -56,6 +56,26 @@ public virtual async Task Collection_of_entities_projecting_correlated_collectio Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public override async Task KeylessEntity_with_included_navs_multi_level(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.KeylessEntity_with_included_navs_multi_level(async))).Message; + + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public override async Task KeylessEntity_with_defining_query_and_correlated_collection(bool async) + { + var message = (await Assert.ThrowsAsync( + () => base.KeylessEntity_with_defining_query_and_correlated_collection(async))).Message; + + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + } + protected override QueryAsserter CreateQueryAsserter(TFixture fixture) => new RelationalQueryAsserter( fixture, RewriteExpectedQueryExpression, RewriteServerQueryExpression, canExecuteQueryString: CanExecuteQueryString); diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs index 39919b4672c..7cab664011e 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs @@ -2157,6 +2157,47 @@ public virtual Task Filtered_include_Skip_Take_with_another_Skip_Take_on_top_lev new ExpectedInclude(x => x.OneToOne_Optional_FK2, "OneToMany_Optional1"))); } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(bool async) + { + return AssertFirstOrDefault( + async, + ss => ss.Set() + .OrderBy(l1 => l1.Id) + .Include(l1 => l1.OneToMany_Optional1.Take(40)) + .ThenInclude(l2 => l2.OneToOne_Optional_FK2), + asserter: (e, a) => AssertInclude( + e, + a, + new ExpectedFilteredInclude( + x => x.OneToMany_Optional1, + includeFilter: x => x.Take(40)), + new ExpectedInclude(x => x.OneToOne_Optional_FK2, "OneToMany_Optional1"))); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(bool async) + { + return AssertQuery( + async, + ss => ss.Set() + .OrderBy(l1 => l1.Id) + .Include(l1 => l1.OneToMany_Optional1.Take(40)) + .ThenInclude(l2 => l2.OneToOne_Optional_FK2) + .Take(30), + elementSorter: e => e.Id, + elementAsserter: (e, a) => AssertInclude( + e, + a, + new ExpectedFilteredInclude( + x => x.OneToMany_Optional1, + includeFilter: x => x.Take(40)), + new ExpectedInclude(x => x.OneToOne_Optional_FK2, "OneToMany_Optional1"))); + } + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Projecting_collection_with_FirstOrDefault(bool async) @@ -2443,5 +2484,39 @@ public virtual Task Include_partially_added_before_Where_and_then_build_upon_wit .ThenInclude(l3 => l3.OneToOne_Optional_FK3), elementAsserter: (e, a) => AssertInclude(e, a, expectedIncludes)); } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Take_on_correlated_collection_in_projection(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Select(l1 => new { l1.Id, Collection = l1.OneToMany_Optional1.Take(50) }), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertCollection(e.Collection, a.Collection); + }); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FirstOrDefault_with_predicate_on_correlated_collection_in_projection(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Select(l1 => new + { + l1.Id, + Element = l1.OneToMany_Optional1.FirstOrDefault(l2 => l2.Id == l1.Id) + }), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Element, a.Element); + }); + } } } diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryTestBase.cs index 9a7ea602bce..673d140a1ed 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryTestBase.cs @@ -14,12 +14,13 @@ protected ComplexNavigationsCollectionsSharedTypeQueryTestBase(TFixture fixture) { } + // Self-ref not supported public override Task Multiple_complex_includes_self_ref(bool async) => Task.CompletedTask; - [ConditionalTheory(Skip = "issue #13560")] + [ConditionalTheory] public override Task Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(bool async) - => base.Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(async); + => Task.CompletedTask; // include after select is not supported public override Task Include_collection_with_multiple_orderbys_complex(bool async) diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryTestBase.cs index 2fb13a02e89..6965ea7f972 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryTestBase.cs @@ -16,45 +16,25 @@ protected ComplexNavigationsSharedTypeQueryTestBase(TFixture fixture) // Self-ref not supported public override Task Join_navigation_self_ref(bool async) - { - return Task.CompletedTask; - } + => Task.CompletedTask; public override Task Join_condition_optimizations_applied_correctly_when_anonymous_type_with_multiple_properties(bool async) - { - return Task.CompletedTask; - } + => Task.CompletedTask; public override Task Join_condition_optimizations_applied_correctly_when_anonymous_type_with_single_property(bool async) - { - return Task.CompletedTask; - } + => Task.CompletedTask; - [ConditionalTheory(Skip = "issue #13560")] public override Task Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(bool async) - { - return base.Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(async); - } + => Task.CompletedTask; - [ConditionalTheory(Skip = "issue #13560")] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany( - bool async) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(async); - } + public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(bool async) + => Task.CompletedTask; - [ConditionalTheory(Skip = "issue #13560")] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2( - bool async) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(async); - } + public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(bool async) + => Task.CompletedTask; - [ConditionalTheory(Skip = "issue #13560")] public override Task SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(bool async) - { - return base.SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(async); - } + => Task.CompletedTask; [ConditionalTheory(Skip = "Issue#16752")] public override Task Include8(bool async) @@ -68,12 +48,6 @@ public override Task Include9(bool async) return base.Include9(async); } - [ConditionalTheory(Skip = "Issue#17803")] - public override Task Member_pushdown_with_multiple_collections(bool async) - { - return base.Member_pushdown_with_multiple_collections(async); - } - // Cannot create DbSet for Level2 public override void Join_with_navigations_in_the_result_selector2() { @@ -94,12 +68,6 @@ public override void Member_pushdown_with_collection_navigation_in_the_middle() public override Task Union_over_entities_with_different_nullability(bool async) => Task.CompletedTask; - [ConditionalTheory(Skip = "Issue#17803")] - public override Task Multiple_collection_FirstOrDefault_followed_by_member_access_in_projection(bool async) - { - return base.Multiple_collection_FirstOrDefault_followed_by_member_access_in_projection(async); - } - public override Task Project_shadow_properties(bool async) => Task.CompletedTask; } diff --git a/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs index c32f8c2778e..bc959d939a5 100644 --- a/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs @@ -169,7 +169,7 @@ public virtual Task Can_use_of_type_kiwi(bool async) entryCount: 1); } - [ConditionalTheory(Skip = "Issue#17364")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Can_use_backwards_of_type_animal(bool async) { diff --git a/test/EFCore.Specification.Tests/Query/NorthwindKeylessEntitiesQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindKeylessEntitiesQueryTestBase.cs index f4c3fee62e3..1504567391c 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindKeylessEntitiesQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindKeylessEntitiesQueryTestBase.cs @@ -82,7 +82,7 @@ public virtual Task KeylessEntity_with_defining_query(bool async) ss => ss.Set().Where(ov => ov.CustomerID == "ALFKI")); } - [ConditionalTheory(Skip = "Issue#21828")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task KeylessEntity_with_defining_query_and_correlated_collection(bool async) { @@ -122,7 +122,7 @@ public virtual Task KeylessEntity_with_included_nav(bool async) entryCount: 1); } - [ConditionalTheory(Skip = "Issue#21828")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task KeylessEntity_with_included_navs_multi_level(bool async) { diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs index e12f4ad48bc..d3cf8993279 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs @@ -1835,6 +1835,54 @@ OFFSET 2 ROWS FETCH NEXT 4 ROWS ONLY ORDER BY [t].[Id] DESC, [t0].[Name] DESC, [t0].[Id]"); } + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(bool async) + { + await base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(async); + + AssertSql( + @"SELECT [t].[Id], [t].[Date], [t].[Name], [t].[OneToMany_Optional_Self_Inverse1Id], [t].[OneToMany_Required_Self_Inverse1Id], [t].[OneToOne_Optional_Self1Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id] +FROM ( + SELECT TOP(1) [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id] + FROM [LevelOne] AS [l] + ORDER BY [l].[Id] +) AS [t] +OUTER APPLY ( + SELECT [t1].[Id], [t1].[Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Optional_Self_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToMany_Required_Self_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name] AS [Name0], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id] + FROM ( + SELECT TOP(40) [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id] + FROM [LevelTwo] AS [l1] + WHERE [t].[Id] = [l1].[OneToMany_Optional_Inverse2Id] + ) AS [t1] + LEFT JOIN [LevelThree] AS [l0] ON [t1].[Id] = [l0].[Level2_Optional_Id] +) AS [t0] +ORDER BY [t].[Id], [t0].[Id]"); + } + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(bool async) + { + await base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async); + + AssertSql( + @"@__p_0='30' + +SELECT [t].[Id], [t].[Date], [t].[Name], [t].[OneToMany_Optional_Self_Inverse1Id], [t].[OneToMany_Required_Self_Inverse1Id], [t].[OneToOne_Optional_Self1Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id] +FROM ( + SELECT TOP(@__p_0) [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id] + FROM [LevelOne] AS [l] + ORDER BY [l].[Id] +) AS [t] +OUTER APPLY ( + SELECT [t1].[Id], [t1].[Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Optional_Self_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToMany_Required_Self_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name] AS [Name0], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id] + FROM ( + SELECT TOP(40) [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id] + FROM [LevelTwo] AS [l1] + WHERE [t].[Id] = [l1].[OneToMany_Optional_Inverse2Id] + ) AS [t1] + LEFT JOIN [LevelThree] AS [l0] ON [t1].[Id] = [l0].[Level2_Optional_Id] +) AS [t0] +ORDER BY [t].[Id], [t0].[Id]"); + } + public override async Task Skip_on_grouping_element(bool async) { await base.Skip_on_grouping_element(async); @@ -2091,6 +2139,41 @@ FROM [LevelThree] AS [l3] ORDER BY [l].[Id], [l0].[Id], [l1].[Id], [t0].[OneToMany_Optional_Inverse3Id], [t0].[Id], [t1].[Id]"); } + public override async Task Take_on_correlated_collection_in_projection(bool async) + { + await base.Take_on_correlated_collection_in_projection(async); + + AssertSql( + @"SELECT [l].[Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id] +FROM [LevelOne] AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Id]) AS [row] + FROM [LevelTwo] AS [l0] + ) AS [t] + WHERE [t].[row] <= 50 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[Id]"); + } + + public override async Task FirstOrDefault_with_predicate_on_correlated_collection_in_projection(bool async) + { + await base.FirstOrDefault_with_predicate_on_correlated_collection_in_projection(async); + + AssertSql( + @"SELECT [l].[Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id] +FROM [LevelOne] AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id], [l0].[Id] ORDER BY [l0].[Id]) AS [row] + FROM [LevelTwo] AS [l0] + ) AS [t] + WHERE [t].[row] <= 1 +) AS [t0] ON ([l].[Id] = [t0].[OneToMany_Optional_Inverse2Id]) AND ([l].[Id] = [t0].[Id])"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs index cf9ad939db6..8df6a120098 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs @@ -2845,6 +2845,64 @@ OFFSET 2 ROWS FETCH NEXT 4 ROWS ONLY ORDER BY [t].[Id] DESC, [t0].[Name] DESC"); } + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(bool async) + { + await base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(async); + + AssertSql( + @"SELECT TOP(1) [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id] +FROM [LevelOne] AS [l] +ORDER BY [l].[Id]", + // + @"SELECT [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id], [t].[Id] +FROM ( + SELECT TOP(1) [l].[Id] + FROM [LevelOne] AS [l] + ORDER BY [l].[Id] +) AS [t] +CROSS APPLY ( + SELECT [t1].[Id], [t1].[Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Optional_Self_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToMany_Required_Self_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name] AS [Name0], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id] + FROM ( + SELECT TOP(40) [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id] + FROM [LevelTwo] AS [l1] + WHERE [t].[Id] = [l1].[OneToMany_Optional_Inverse2Id] + ) AS [t1] + LEFT JOIN [LevelThree] AS [l0] ON [t1].[Id] = [l0].[Level2_Optional_Id] +) AS [t0] +ORDER BY [t].[Id]"); + } + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(bool async) + { + await base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async); + + AssertSql( + @"@__p_0='30' + +SELECT TOP(@__p_0) [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id] +FROM [LevelOne] AS [l] +ORDER BY [l].[Id]", + // + @"@__p_0='30' + +SELECT [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id], [t].[Id] +FROM ( + SELECT TOP(@__p_0) [l].[Id] + FROM [LevelOne] AS [l] + ORDER BY [l].[Id] +) AS [t] +CROSS APPLY ( + SELECT [t1].[Id], [t1].[Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Optional_Self_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToMany_Required_Self_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name] AS [Name0], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id] + FROM ( + SELECT TOP(40) [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id] + FROM [LevelTwo] AS [l1] + WHERE [t].[Id] = [l1].[OneToMany_Optional_Inverse2Id] + ) AS [t1] + LEFT JOIN [LevelThree] AS [l0] ON [t1].[Id] = [l0].[Level2_Optional_Id] +) AS [t0] +ORDER BY [t].[Id]"); + } + public override async Task Projecting_collection_with_FirstOrDefault(bool async) { await base.Projecting_collection_with_FirstOrDefault(async); @@ -3189,6 +3247,45 @@ FROM [LevelThree] AS [l2] ORDER BY [l].[Id], [l0].[Id], [l1].[Id]"); } + public override async Task Take_on_correlated_collection_in_projection(bool async) + { + await base.Take_on_correlated_collection_in_projection(async); + + AssertSql( + @"SELECT [l].[Id] +FROM [LevelOne] AS [l] +ORDER BY [l].[Id]", + // + @"SELECT [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [l].[Id] +FROM [LevelOne] AS [l] +INNER JOIN ( + SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Id]) AS [row] + FROM [LevelTwo] AS [l0] + ) AS [t] + WHERE [t].[row] <= 50 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id]"); + } + + public override async Task FirstOrDefault_with_predicate_on_correlated_collection_in_projection(bool async) + { + await base.FirstOrDefault_with_predicate_on_correlated_collection_in_projection(async); + + AssertSql( + @"SELECT [l].[Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id] +FROM [LevelOne] AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id], [l0].[Id] ORDER BY [l0].[Id]) AS [row] + FROM [LevelTwo] AS [l0] + ) AS [t] + WHERE [t].[row] <= 1 +) AS [t0] ON ([l].[Id] = [t0].[OneToMany_Optional_Inverse2Id]) AND ([l].[Id] = [t0].[Id])"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/InheritanceQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/InheritanceQuerySqlServerTest.cs index dc4e0e8b465..5d769fb46f0 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/InheritanceQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/InheritanceQuerySqlServerTest.cs @@ -544,6 +544,26 @@ public override async Task Selecting_only_base_properties_on_derived_type(bool a FROM [Animals] AS [a]"); } + public override async Task Can_use_backwards_of_type_animal(bool async) + { + await base.Can_use_backwards_of_type_animal(async); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Discriminator], [a].[Name], [a].[EagleId], [a].[IsFlightless], [a].[FoundOn] +FROM [Animals] AS [a] +WHERE [a].[Discriminator] = N'Kiwi'"); + } + + public override async Task Can_use_backwards_is_animal(bool async) + { + await base.Can_use_backwards_is_animal(async); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Discriminator], [a].[Name], [a].[EagleId], [a].[IsFlightless], [a].[FoundOn] +FROM [Animals] AS [a] +WHERE [a].[Discriminator] = N'Kiwi'"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindKeylessEntitiesQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindKeylessEntitiesQuerySqlServerTest.cs index 2cd790ac8e8..84ac5ce173c 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindKeylessEntitiesQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindKeylessEntitiesQuerySqlServerTest.cs @@ -98,21 +98,6 @@ public override async Task KeylessEntity_with_defining_query(bool async) WHERE [m].[CustomerID] = N'ALFKI'"); } - public override async Task KeylessEntity_with_defining_query_and_correlated_collection(bool async) - { - await base.KeylessEntity_with_defining_query_and_correlated_collection(async); - - AssertSql( - @"SELECT [o].[OrderID], [c].[CustomerID], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] -FROM ( - select * from ""Orders"" -) AS [o] -LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] -LEFT JOIN [Orders] AS [o0] ON [c].[CustomerID] = [o0].[CustomerID] -WHERE [o].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID], [o].[OrderID], [o0].[OrderID]"); - } - public override async Task KeylessEntity_select_where_navigation(bool async) { await base.KeylessEntity_select_where_navigation(async); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTInheritanceQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTInheritanceQuerySqlServerTest.cs index f21798b82e5..d4ae1108a58 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTInheritanceQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTInheritanceQuerySqlServerTest.cs @@ -290,7 +290,11 @@ public override async Task Can_use_backwards_of_type_animal(bool async) { await base.Can_use_backwards_of_type_animal(async); - AssertSql(" "); + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [k].[FoundOn] +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +INNER JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species]"); } public override async Task Can_use_is_kiwi(bool async) diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs index 001f1a8e643..560cca84277 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs @@ -117,5 +117,17 @@ public override async Task Skip_Take_on_grouping_element_with_reference_include( SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Skip_Take_on_grouping_element_with_reference_include(async))).Message); + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(async))).Message); + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs index 759c60b8718..33284ace464 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs @@ -107,5 +107,17 @@ public override async Task Skip_Take_on_grouping_element_with_reference_include( SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Skip_Take_on_grouping_element_with_reference_include(async))).Message); + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(async))).Message); + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs index 75566cc9c65..7cef283c14a 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs @@ -93,5 +93,17 @@ public override async Task Skip_Take_on_grouping_element_with_reference_include( SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Skip_Take_on_grouping_element_with_reference_include(async))).Message); + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(async))).Message); + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs index 5e412ba22d0..b99f5739484 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs @@ -83,5 +83,17 @@ public override async Task Skip_Take_on_grouping_element_with_reference_include( SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Skip_Take_on_grouping_element_with_reference_include(async))).Message); + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(async))).Message); + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async))).Message); } } From 7912a3a05c5184b324f5067378ae3f6b3de9c600 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 2 Sep 2021 18:12:09 +0000 Subject: [PATCH 010/346] Update dependencies from https://github.com/dotnet/runtime build 20210902.10 (#25846) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 8548cef6714..d3b449457b9 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 - + https://github.com/dotnet/runtime - cd631d01bfbb2d66d4e781f5b2929ae4e20f3f15 + 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 diff --git a/eng/Versions.props b/eng/Versions.props index aa56e133bcf..49beee3ffe7 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 - 6.0.0-rc.2.21452.5 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.10 3.7.0 From 636a1e088ed4e8a9ec99eddfae0e3a1e93dbb73d Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 2 Sep 2021 20:13:50 +0000 Subject: [PATCH 011/346] Update dependencies from https://github.com/dotnet/runtime build 20210902.13 (#25850) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d3b449457b9..abf832ed92a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 - + https://github.com/dotnet/runtime - 0e71ebc8ae10aac9e1b2d4dc284d404172a5b9a6 + eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 diff --git a/eng/Versions.props b/eng/Versions.props index 49beee3ffe7..3fd25ae99df 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 - 6.0.0-rc.2.21452.10 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.13 3.7.0 From 9f6a66f48de1b784d08073a4ba58e10b1485037a Mon Sep 17 00:00:00 2001 From: maumar Date: Thu, 2 Sep 2021 01:02:44 -0700 Subject: [PATCH 012/346] Fix to #25834 - Query/Test: northwind tests don't have predefined entity asserters Also minor test fixes that were found as a result of fixing this. Fixes #25834 --- ...nheritanceRelationshipsQueryFixtureBase.cs | 17 ++ .../NorthwindMiscellaneousQueryTestBase.cs | 3 +- .../Query/NorthwindQueryFixtureBase.cs | 146 +++++++++++++++++- .../Query/NorthwindSelectQueryTestBase.cs | 2 +- .../TestUtilities/QueryAsserter.cs | 4 + ...plitIncludeNoTrackingQuerySqlServerTest.cs | 14 ++ .../NorthwindMiscellaneousQuerySqliteTest.cs | 2 + 7 files changed, 185 insertions(+), 3 deletions(-) diff --git a/test/EFCore.Specification.Tests/Query/InheritanceRelationshipsQueryFixtureBase.cs b/test/EFCore.Specification.Tests/Query/InheritanceRelationshipsQueryFixtureBase.cs index d0e1203fa79..bd64035a472 100644 --- a/test/EFCore.Specification.Tests/Query/InheritanceRelationshipsQueryFixtureBase.cs +++ b/test/EFCore.Specification.Tests/Query/InheritanceRelationshipsQueryFixtureBase.cs @@ -338,6 +338,23 @@ public IReadOnlyDictionary GetEntityAsserters() } } }, + { + typeof(NestedReferenceDerived), (e, a) => + { + Assert.Equal(e == null, a == null); + + if (a != null) + { + var ee = (NestedReferenceDerived)e; + var aa = (NestedReferenceDerived)a; + + Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Name, aa.Name); + Assert.Equal(ee.ParentReferenceId, aa.ParentReferenceId); + Assert.Equal(ee.ParentCollectionId, aa.ParentCollectionId); + } + } + }, { typeof(NonEntityBase), (e, a) => { diff --git a/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs index 98e3b21d031..b6b3d9b4e65 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs @@ -4133,7 +4133,8 @@ public virtual Task Select_expression_datetime_add_month(bool async) { return AssertQuery( async, - ss => ss.Set().Where(o => o.OrderDate != null) + ss => ss.Set() + .Where(o => o.OrderDate != null) .Select(o => new Order { OrderDate = o.OrderDate.Value.AddMonths(1) }), e => e.OrderDate); } diff --git a/test/EFCore.Specification.Tests/Query/NorthwindQueryFixtureBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindQueryFixtureBase.cs index 6d0890ac06d..c42f8c5873d 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindQueryFixtureBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindQueryFixtureBase.cs @@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.TestModels.Northwind; using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; namespace Microsoft.EntityFrameworkCore.Query { @@ -90,7 +91,150 @@ public IReadOnlyDictionary GetEntitySorters() }.ToDictionary(e => e.Key, e => (object)e.Value); public IReadOnlyDictionary GetEntityAsserters() - => null; + => new Dictionary> + { + { + typeof(Customer), (e, a) => + { + Assert.Equal(e == null, a == null); + + if (a != null) + { + var ee = (Customer)e; + var aa = (Customer)a; + + Assert.Equal(ee.CustomerID, aa.CustomerID); + Assert.Equal(ee.Address, aa.Address); + Assert.Equal(ee.CompanyName, aa.CompanyName); + Assert.Equal(ee.ContactName, aa.ContactName); + Assert.Equal(ee.ContactTitle, aa.ContactTitle); + Assert.Equal(ee.Country, aa.Country); + Assert.Equal(ee.Fax, aa.Fax); + Assert.Equal(ee.Phone, aa.Phone); + Assert.Equal(ee.PostalCode, aa.PostalCode); + } + } + }, + { + typeof(CustomerQuery), (e, a) => + { + Assert.Equal(e == null, a == null); + + if (a != null) + { + var ee = (CustomerQuery)e; + var aa = (CustomerQuery)a; + + Assert.Equal(ee.CompanyName, aa.CompanyName); + Assert.Equal(ee.Address, aa.Address); + Assert.Equal(ee.City, aa.City); + Assert.Equal(ee.ContactName, aa.ContactName); + Assert.Equal(ee.ContactTitle, aa.ContactTitle); + } + } + }, + { + typeof(Order), (e, a) => + { + Assert.Equal(e == null, a == null); + + if (a != null) + { + var ee = (Order)e; + var aa = (Order)a; + + Assert.Equal(ee.OrderID, aa.OrderID); + Assert.Equal(ee.CustomerID, aa.CustomerID); + Assert.Equal(ee.EmployeeID, aa.EmployeeID); + Assert.Equal(ee.OrderDate, aa.OrderDate); + } + } + }, + { + typeof(OrderQuery), (e, a) => + { + Assert.Equal(e == null, a == null); + + if (a != null) + { + var ee = (OrderQuery)e; + var aa = (OrderQuery)a; + + Assert.Equal(ee.CustomerID, aa.CustomerID); + } + } + }, + { + typeof(Employee), (e, a) => + { + Assert.Equal(e == null, a == null); + + if (a != null) + { + var ee = (Employee)e; + var aa = (Employee)a; + + Assert.Equal(ee.EmployeeID, aa.EmployeeID); + Assert.Equal(ee.Title, aa.Title); + Assert.Equal(ee.City, aa.City); + Assert.Equal(ee.Country, aa.Country); + Assert.Equal(ee.FirstName, aa.FirstName); + } + } + }, + { + typeof(Product), (e, a) => + { + Assert.Equal(e == null, a == null); + + if (a != null) + { + var ee = (Product)e; + var aa = (Product)a; + + Assert.Equal(ee.ProductID, aa.ProductID); + Assert.Equal(ee.ProductName, aa.ProductName); + Assert.Equal(ee.SupplierID, aa.SupplierID); + Assert.Equal(ee.UnitPrice, aa.UnitPrice); + Assert.Equal(ee.UnitsInStock, aa.UnitsInStock); + } + } + }, + { + typeof(ProductQuery), (e, a) => + { + Assert.Equal(e == null, a == null); + + if (a != null) + { + var ee = (ProductQuery)e; + var aa = (ProductQuery)a; + + Assert.Equal(ee.ProductID, aa.ProductID); + Assert.Equal(ee.CategoryName, aa.CategoryName); + Assert.Equal(ee.ProductName, aa.ProductName); + } + } + }, + { + typeof(OrderDetail), (e, a) => + { + Assert.Equal(e == null, a == null); + + if (a != null) + { + var ee = (OrderDetail)e; + var aa = (OrderDetail)a; + + Assert.Equal(ee.OrderID, aa.OrderID); + Assert.Equal(ee.ProductID, aa.ProductID); + Assert.Equal(ee.Quantity, aa.Quantity); + Assert.Equal(ee.UnitPrice, aa.UnitPrice); + Assert.Equal(ee.Discount, aa.Discount); + } + } + }, + }.ToDictionary(e => e.Key, e => (object)e.Value); protected override string StoreName { get; } = "Northwind"; diff --git a/test/EFCore.Specification.Tests/Query/NorthwindSelectQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindSelectQueryTestBase.cs index 6c6a8f8e6ff..a2ed150b078 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindSelectQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindSelectQueryTestBase.cs @@ -2240,7 +2240,7 @@ public virtual Task Collection_include_over_result_of_single_non_scalar(bool asy elementSorter: e => e.c.CustomerID, elementAsserter: (e, a) => { - AssertInclude(e, a, + AssertInclude(e.c, a.c, new ExpectedInclude(c => c.Orders), new ExpectedInclude(o => o.OrderDetails, "Orders")); AssertInclude(e.SingleOrder, a.SingleOrder, new ExpectedInclude(o => o.OrderDetails)); diff --git a/test/EFCore.Specification.Tests/TestUtilities/QueryAsserter.cs b/test/EFCore.Specification.Tests/TestUtilities/QueryAsserter.cs index a4056cdb4c5..151233b2b97 100644 --- a/test/EFCore.Specification.Tests/TestUtilities/QueryAsserter.cs +++ b/test/EFCore.Specification.Tests/TestUtilities/QueryAsserter.cs @@ -1698,6 +1698,10 @@ private void AssertIncludeEntity(TElement expected, TElement actual, I ((Action)asserter)(expected, actual); ProcessIncludes(expected, actual, expectedIncludes); } + else + { + throw new InvalidOperationException($"Couldn't find entity asserter for entity type: '{typeof(TElement).Name}'."); + } } private void AssertIncludeCollection( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSplitIncludeNoTrackingQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSplitIncludeNoTrackingQuerySqlServerTest.cs index 12f9a4e774f..67a4bbcfb28 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSplitIncludeNoTrackingQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSplitIncludeNoTrackingQuerySqlServerTest.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.Threading.Tasks; using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; using Xunit.Abstractions; namespace Microsoft.EntityFrameworkCore.Query @@ -18,5 +20,17 @@ public NorthwindSplitIncludeNoTrackingQuerySqlServerTest( Fixture.TestSqlLoggerFactory.Clear(); //Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); } + + [ConditionalTheory(Skip = "Issue#21202")] + public override async Task Include_collection_skip_take_no_order_by(bool async) + { + await base.Include_collection_skip_take_no_order_by(async); + } + + [ConditionalTheory(Skip = "Issue#21202")] + public override async Task Include_collection_skip_no_order_by(bool async) + { + await base.Include_collection_skip_no_order_by(async); + } } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindMiscellaneousQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindMiscellaneousQuerySqliteTest.cs index 3847562df59..92908221a71 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindMiscellaneousQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindMiscellaneousQuerySqliteTest.cs @@ -90,6 +90,7 @@ public override async Task Select_expression_date_add_year(bool async) WHERE ""o"".""OrderDate"" IS NOT NULL"); } + [ConditionalTheory(Skip = "issue #25851")] public override async Task Select_expression_datetime_add_month(bool async) { await base.Select_expression_datetime_add_month(async); @@ -130,6 +131,7 @@ public override async Task Select_expression_datetime_add_second(bool async) WHERE ""o"".""OrderDate"" IS NOT NULL"); } + [ConditionalTheory(Skip = "issue #25851")] public override async Task Select_expression_datetime_add_ticks(bool async) { await base.Select_expression_datetime_add_ticks(async); From d7392b780cdb23be7c70188a16163ed7c5f9aa8e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 2 Sep 2021 23:36:31 +0000 Subject: [PATCH 013/346] Update dependencies from https://github.com/dotnet/runtime build 20210902.18 (#25856) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index abf832ed92a..3cbc50cefd1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 - + https://github.com/dotnet/runtime - eb0587b90a9fcb7c94fe7c0b95597e8d5e2c6d33 + af90ed66fe7e7bbd14003a775e9834fe699b3781 diff --git a/eng/Versions.props b/eng/Versions.props index 3fd25ae99df..f7e5d33fc58 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 - 6.0.0-rc.2.21452.13 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.18 3.7.0 From 85e064ca9b463b6372fd5afbdd4327281fc32c84 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Thu, 2 Sep 2021 17:55:43 -0700 Subject: [PATCH 014/346] SqlServer: Ignore Fks whose principal table data is not found (#25852) Resolves #23359 --- .../Internal/SqlServerLoggingDefinitions.cs | 8 ++ .../Diagnostics/SqlServerEventId.cs | 10 ++- .../Internal/SqlServerLoggerExtensions.cs | 23 +++++- .../Properties/SqlServerStrings.Designer.cs | 78 +++++++++++++------ .../Properties/SqlServerStrings.resx | 12 ++- .../Internal/SqlServerDatabaseModelFactory.cs | 19 +++-- .../SqlServerDatabaseModelFactoryTest.cs | 2 +- 7 files changed, 115 insertions(+), 37 deletions(-) diff --git a/src/EFCore.SqlServer/Diagnostics/Internal/SqlServerLoggingDefinitions.cs b/src/EFCore.SqlServer/Diagnostics/Internal/SqlServerLoggingDefinitions.cs index 150aee42191..3dfcfbc4b2f 100644 --- a/src/EFCore.SqlServer/Diagnostics/Internal/SqlServerLoggingDefinitions.cs +++ b/src/EFCore.SqlServer/Diagnostics/Internal/SqlServerLoggingDefinitions.cs @@ -165,6 +165,14 @@ public class SqlServerLoggingDefinitions : RelationalLoggingDefinitions /// public EventDefinitionBase? LogDuplicateForeignKeyConstraintIgnored; + /// + /// 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 EventDefinitionBase? LogPrincipalTableInformationNotFound; + /// /// 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/Diagnostics/SqlServerEventId.cs b/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs index 833d790f3df..82f65737858 100644 --- a/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs +++ b/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs @@ -64,7 +64,8 @@ private enum Id ForeignKeyPrincipalColumnMissingWarning, ReflexiveConstraintIgnored, DuplicateForeignKeyConstraintIgnored, - ColumnWithoutTypeWarning + ColumnWithoutTypeWarning, + ForeignKeyReferencesUnknownPrincipalTableWarning } private static readonly string _validationPrefix = DbLoggerCategory.Model.Validation.Name + "."; @@ -184,6 +185,13 @@ private static EventId MakeScaffoldingId(Id id) public static readonly EventId ForeignKeyReferencesMissingPrincipalTableWarning = MakeScaffoldingId(Id.ForeignKeyReferencesMissingPrincipalTableWarning); + /// + /// A foreign key references a unknown table at the principal end. + /// This event is in the category. + /// + public static readonly EventId ForeignKeyReferencesUnknownPrincipalTableWarning = + MakeScaffoldingId(Id.ForeignKeyReferencesUnknownPrincipalTableWarning); + /// /// A table was found. /// This event is in the category. diff --git a/src/EFCore.SqlServer/Extensions/Internal/SqlServerLoggerExtensions.cs b/src/EFCore.SqlServer/Extensions/Internal/SqlServerLoggerExtensions.cs index aab255bb3ab..e6f0965a6b0 100644 --- a/src/EFCore.SqlServer/Extensions/Internal/SqlServerLoggerExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/Internal/SqlServerLoggerExtensions.cs @@ -348,6 +348,27 @@ public static void IndexFound( // No DiagnosticsSource events because these are purely design-time messages } + /// + /// 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 static void ForeignKeyReferencesUnknownPrincipalTableWarning( + this IDiagnosticsLogger diagnostics, + string? foreignKeyName, + string? tableName) + { + var definition = SqlServerResources.LogPrincipalTableInformationNotFound(diagnostics); + + if (diagnostics.ShouldLog(definition)) + { + definition.Log(diagnostics, foreignKeyName, tableName); + } + + // No DiagnosticsSource events because these are purely design-time messages + } + /// /// 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 @@ -544,7 +565,7 @@ public static void DuplicateForeignKeyConstraintIgnored( string tableName, string duplicateForeignKeyName) { - var definition = SqlServerResources.DuplicateForeignKeyConstraintIgnored(diagnostics); + var definition = SqlServerResources.LogDuplicateForeignKeyConstraintIgnored(diagnostics); if (diagnostics.ShouldLog(definition)) { diff --git a/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs b/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs index 4ccab03a1c4..23fd122e7e9 100644 --- a/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs +++ b/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs @@ -1,6 +1,9 @@ // +using System; +using System.Reflection; using System.Resources; +using System.Threading; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.Logging; @@ -485,6 +488,31 @@ public static EventDefinition LogDefaultDecimalTypeColumn(IDiagn return (EventDefinition)definition; } + /// + /// Skipping foreign key '{foreignKeyName}' on table '{tableName}' since it is a duplicate of '{duplicateForeignKeyName}'. + /// + public static EventDefinition LogDuplicateForeignKeyConstraintIgnored(IDiagnosticsLogger logger) + { + var definition = ((Diagnostics.Internal.SqlServerLoggingDefinitions)logger.Definitions).LogDuplicateForeignKeyConstraintIgnored; + if (definition == null) + { + definition = NonCapturingLazyInitializer.EnsureInitialized( + ref ((Diagnostics.Internal.SqlServerLoggingDefinitions)logger.Definitions).LogDuplicateForeignKeyConstraintIgnored, + logger, + static logger => new EventDefinition( + logger.Options, + SqlServerEventId.DuplicateForeignKeyConstraintIgnored, + LogLevel.Warning, + "SqlServerEventId.DuplicateForeignKeyConstraintIgnored", + level => LoggerMessage.Define( + level, + SqlServerEventId.DuplicateForeignKeyConstraintIgnored, + _resourceManager.GetString("LogDuplicateForeignKeyConstraintIgnored")!))); + } + + return (EventDefinition)definition; + } + /// /// Found column with table: {tableName}, column name: {columnName}, ordinal: {ordinal}, data type: {dataType}, maximum length: {maxLength}, precision: {precision}, scale: {scale}, nullable: {nullable}, identity: {identity}, default value: {defaultValue}, computed value: {computedValue}, computed value is stored: {stored}. /// @@ -779,6 +807,31 @@ public static EventDefinition LogPrincipalColumn return (EventDefinition)definition; } + /// + /// Skipping foreign key '{foreignKeyName}' on table '{tableName}' since principal table information is not available. This usually happens when the user doesn't have permission to read data about principal table. + /// + public static EventDefinition LogPrincipalTableInformationNotFound(IDiagnosticsLogger logger) + { + var definition = ((Diagnostics.Internal.SqlServerLoggingDefinitions)logger.Definitions).LogPrincipalTableInformationNotFound; + if (definition == null) + { + definition = NonCapturingLazyInitializer.EnsureInitialized( + ref ((Diagnostics.Internal.SqlServerLoggingDefinitions)logger.Definitions).LogPrincipalTableInformationNotFound, + logger, + static logger => new EventDefinition( + logger.Options, + SqlServerEventId.ForeignKeyReferencesUnknownPrincipalTableWarning, + LogLevel.Warning, + "SqlServerEventId.ForeignKeyReferencesUnknownPrincipalTableWarning", + level => LoggerMessage.Define( + level, + SqlServerEventId.ForeignKeyReferencesUnknownPrincipalTableWarning, + _resourceManager.GetString("LogPrincipalTableInformationNotFound")!))); + } + + return (EventDefinition)definition; + } + /// /// Skipping foreign key '{foreignKeyName}' on table '{tableName}' since principal table '{principalTableName}' was not found in the model. This usually happens when the principal table was not included in the selection set. /// @@ -829,31 +882,6 @@ public static EventDefinition LogReflexiveConstraintIgnored(IDia return (EventDefinition)definition; } - /// - /// Skipping foreign key '{foreignKeyName}' on table '{tableName}' since it is a duplicate of '{duplicateForeignKeyName}'. - /// - public static EventDefinition DuplicateForeignKeyConstraintIgnored(IDiagnosticsLogger logger) - { - var definition = ((Diagnostics.Internal.SqlServerLoggingDefinitions)logger.Definitions).LogDuplicateForeignKeyConstraintIgnored; - if (definition == null) - { - definition = NonCapturingLazyInitializer.EnsureInitialized( - ref ((Diagnostics.Internal.SqlServerLoggingDefinitions)logger.Definitions).LogDuplicateForeignKeyConstraintIgnored, - logger, - static logger => new EventDefinition( - logger.Options, - SqlServerEventId.DuplicateForeignKeyConstraintIgnored, - LogLevel.Warning, - "SqlServerEventId.DuplicateForeignKeyConstraintIgnored", - level => LoggerMessage.Define( - level, - SqlServerEventId.DuplicateForeignKeyConstraintIgnored, - _resourceManager.GetString("DuplicateForeignKeyConstraintIgnored")!))); - } - - return (EventDefinition)definition; - } - /// /// Savepoints are disabled because Multiple Active Result Sets (MARS) is enabled. If 'SaveChanges' fails, then the transaction cannot be automatically rolled back to a known clean state. Instead, the transaction should be rolled back by the application before retrying 'SaveChanges'. See https://go.microsoft.com/fwlink/?linkid=2149338 for more information. To identify the code which triggers this warning, call 'ConfigureWarnings(w => w.Throw(SqlServerEventId.SavepointsDisabledBecauseOfMARS))'. /// diff --git a/src/EFCore.SqlServer/Properties/SqlServerStrings.resx b/src/EFCore.SqlServer/Properties/SqlServerStrings.resx index e626bbedc50..5770c19ea28 100644 --- a/src/EFCore.SqlServer/Properties/SqlServerStrings.resx +++ b/src/EFCore.SqlServer/Properties/SqlServerStrings.resx @@ -200,6 +200,10 @@ No store type was specified for the decimal property '{property}' on entity type '{entityType}'. This will cause values to be silently truncated if they do not fit in the default precision and scale. Explicitly specify the SQL server column type that can accommodate all the values in 'OnModelCreating' using 'HasColumnType', specify precision and scale using 'HasPrecision', or configure a value converter using 'HasConversion'. Warning SqlServerEventId.DecimalTypeDefaultWarning string string + + Skipping foreign key '{foreignKeyName}' on table '{tableName}' since it is a duplicate of '{duplicateForeignKeyName}'. + Warning SqlServerEventId.DuplicateForeignKeyConstraintIgnored string string string + Found column with table: {tableName}, column name: {columnName}, ordinal: {ordinal}, data type: {dataType}, maximum length: {maxLength}, precision: {precision}, scale: {scale}, nullable: {nullable}, identity: {identity}, default value: {defaultValue}, computed value: {computedValue}, computed value is stored: {stored}. Debug SqlServerEventId.ColumnFound string string int string int int int bool bool string string bool? @@ -248,6 +252,10 @@ Skipping foreign key with identity '{id}' on table '{tableName}', since the principal column '{principalColumnName}' on the foreign key's principal table, '{principalTableName}', was not found in the model. Warning SqlServerEventId.ForeignKeyPrincipalColumnMissingWarning string string string string + + Skipping foreign key '{foreignKeyName}' on table '{tableName}' since principal table information is not available. This usually happens when the user doesn't have permission to read data about principal table. + Warning SqlServerEventId.ForeignKeyReferencesUnknownPrincipalTableWarning string? string? + Skipping foreign key '{foreignKeyName}' on table '{tableName}' since principal table '{principalTableName}' was not found in the model. This usually happens when the principal table was not included in the selection set. Warning SqlServerEventId.ForeignKeyReferencesMissingPrincipalTableWarning string? string? string? @@ -256,10 +264,6 @@ Skipping foreign key '{foreignKeyName}' on table '{tableName}' since all of its columns reference themselves. Debug SqlServerEventId.ReflexiveConstraintIgnored string string - - Skipping foreign key '{foreignKeyName}' on table '{tableName}' since it is a duplicate of '{duplicateForeignKeyName}'. - Warning SqlServerEventId.DuplicateForeignKeyConstraintIgnored string string string - Savepoints are disabled because Multiple Active Result Sets (MARS) is enabled. If 'SaveChanges' fails, then the transaction cannot be automatically rolled back to a known clean state. Instead, the transaction should be rolled back by the application before retrying 'SaveChanges'. See https://go.microsoft.com/fwlink/?linkid=2149338 for more information. To identify the code which triggers this warning, call 'ConfigureWarnings(w => w.Throw(SqlServerEventId.SavepointsDisabledBecauseOfMARS))'. Warning SqlServerEventId.SavepointsDisabledBecauseOfMARS diff --git a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs index 20b1db2a489..dcac5e48bec 100644 --- a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs +++ b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs @@ -694,7 +694,7 @@ private void GetColumns( { commandText += @", [c].[generated_always_type]"; - } + } commandText += @"FROM ( @@ -1196,7 +1196,7 @@ FROM [sys].[foreign_keys] AS [f] .GroupBy( c => (Name: c.GetValueOrDefault("name"), PrincipalTableSchema: c.GetValueOrDefault("principal_table_schema"), - PrincipalTableName: c.GetFieldValue("principal_table_name"), + PrincipalTableName: c.GetValueOrDefault("principal_table_name"), OnDeleteAction: c.GetValueOrDefault("delete_referential_action_desc"))); foreach (var foreignKeyGroup in foreignKeyGroups) @@ -1206,9 +1206,18 @@ FROM [sys].[foreign_keys] AS [f] var principalTableName = foreignKeyGroup.Key.PrincipalTableName; var onDeleteAction = foreignKeyGroup.Key.OnDeleteAction; + if (principalTableName == null) + { + _logger.ForeignKeyReferencesUnknownPrincipalTableWarning( + fkName, + DisplayName(table.Schema, table.Name)); + + continue; + } + _logger.ForeignKeyFound( fkName!, - DisplayName(table.Schema, table.Name!), + DisplayName(table.Schema, table.Name), DisplayName(principalTableSchema, principalTableName), onDeleteAction!); @@ -1217,13 +1226,13 @@ FROM [sys].[foreign_keys] AS [f] && t.Name == principalTableName) ?? tables.FirstOrDefault( t => t.Schema?.Equals(principalTableSchema, StringComparison.OrdinalIgnoreCase) == true - && t.Name!.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); + && t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); if (principalTable == null) { _logger.ForeignKeyReferencesMissingPrincipalTableWarning( fkName, - DisplayName(table.Schema, table.Name!), + DisplayName(table.Schema, table.Name), DisplayName(principalTableSchema, principalTableName)); continue; diff --git a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs index f58bf636340..1a835448a19 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs @@ -2422,7 +2422,7 @@ CONSTRAINT MYFK3 FOREIGN KEY (ForeignKeyId) REFERENCES OtherPrincipalTable(Id), Fixture.ListLoggerFactory.Log, t => t.Id == SqlServerEventId.DuplicateForeignKeyConstraintIgnored); Assert.Equal(LogLevel.Warning, level); Assert.Equal( - SqlServerResources.DuplicateForeignKeyConstraintIgnored(new TestLogger()) + SqlServerResources.LogDuplicateForeignKeyConstraintIgnored(new TestLogger()) .GenerateMessage("MYFK2", "dbo.DependentTable", "MYFK1"), message); var table = dbModel.Tables.Single(t => t.Name == "DependentTable"); From f8e94f2dd645abe2815496afb073c90e1090ef80 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Thu, 2 Sep 2021 18:00:21 -0700 Subject: [PATCH 015/346] Query: Add regression test for #23658 (#25853) Resolves #23658 --- .../Query/ComplexNavigationsQueryTestBase.cs | 12 ++++++++++++ .../Query/ComplexNavigationsQuerySqliteTest.cs | 6 ++++++ .../ComplexNavigationsSharedTypeQuerySqliteTest.cs | 6 ++++++ 3 files changed, 24 insertions(+) diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs index befe6deb720..ead3811794c 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs @@ -4275,5 +4275,17 @@ await AssertQuery( }, elementSorter: e => e.Id); } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Prune_does_not_throw_null_ref(bool async) + { + return AssertQuery( + async, + ss => from ids in (from l2 in ss.Set().Where(i => i.Id < 5) + select l2.Level1_Required_Id).DefaultIfEmpty() + from l1 in ss.Set().Where(x => x.Id != ids) + select l1); + } } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs index 42fb25018bf..130a0fb0106 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs @@ -20,5 +20,11 @@ public override async Task Let_let_contains_from_outer_let(bool async) SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Let_let_contains_from_outer_let(async))).Message); + + public override async Task Prune_does_not_throw_null_ref(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Prune_does_not_throw_null_ref(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs index 2cafac0d176..5e977d32278 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs @@ -22,5 +22,11 @@ public override async Task Let_let_contains_from_outer_let(bool async) SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Let_let_contains_from_outer_let(async))).Message); + + public override async Task Prune_does_not_throw_null_ref(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Prune_does_not_throw_null_ref(async))).Message); } } From 4e68ad1ca0f2bd80dd5a3b8c061a526ed26d44d1 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Thu, 2 Sep 2021 19:35:02 -0700 Subject: [PATCH 016/346] Convert Int32 identity seed value Fixes #25589 --- .../Internal/SnapshotModelProcessor.cs | 42 +++++++++++++++++++ .../Design/SnapshotModelProcessorTest.cs | 6 ++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/EFCore.Design/Migrations/Internal/SnapshotModelProcessor.cs b/src/EFCore.Design/Migrations/Internal/SnapshotModelProcessor.cs index d9b412ca239..284ff14c68f 100644 --- a/src/EFCore.Design/Migrations/Internal/SnapshotModelProcessor.cs +++ b/src/EFCore.Design/Migrations/Internal/SnapshotModelProcessor.cs @@ -82,6 +82,14 @@ public SnapshotModelProcessor( return _modelRuntimeInitializer.Initialize((IModel)model, designTime: true, validationLogger: null); } + private void ProcessCollection(IEnumerable metadata, string version) + { + foreach (var element in metadata) + { + ProcessElement(element, version); + } + } + private void ProcessCollection(IEnumerable metadata, string version) { foreach (var element in metadata) @@ -90,6 +98,23 @@ private void ProcessCollection(IEnumerable metadata, strin } } + private void ProcessElement(IReadOnlyModel model, string version) + { + ProcessElement((IReadOnlyAnnotatable)model, version); + + if ((version.StartsWith("3.", StringComparison.Ordinal) + || version.StartsWith("5.", StringComparison.Ordinal)) + && model is IMutableModel mutableModel) + { + var seed = model["SqlServer:IdentitySeed"]; + if (seed != null + && seed is int intSeed) + { + mutableModel["SqlServer:IdentitySeed"] = (long)intSeed; + } + } + } + private void ProcessElement(IReadOnlyEntityType entityType, string version) { ProcessElement((IReadOnlyAnnotatable)entityType, version); @@ -103,6 +128,23 @@ private void ProcessElement(IReadOnlyEntityType entityType, string version) } } + private void ProcessElement(IReadOnlyProperty property, string version) + { + ProcessElement((IReadOnlyAnnotatable)property, version); + + if ((version.StartsWith("3.", StringComparison.Ordinal) + || version.StartsWith("5.", StringComparison.Ordinal)) + && property is IMutableProperty mutableProperty) + { + var seed = property["SqlServer:IdentitySeed"]; + if (seed != null + && seed is int intSeed) + { + mutableProperty["SqlServer:IdentitySeed"] = (long)intSeed; + } + } + } + private void ProcessElement(IReadOnlyAnnotatable? metadata, string version) { if (version.StartsWith("1.", StringComparison.Ordinal) diff --git a/test/EFCore.Design.Tests/Migrations/Design/SnapshotModelProcessorTest.cs b/test/EFCore.Design.Tests/Migrations/Design/SnapshotModelProcessorTest.cs index c4f6fb72df5..f8b5438e6fb 100644 --- a/test/EFCore.Design.Tests/Migrations/Design/SnapshotModelProcessorTest.cs +++ b/test/EFCore.Design.Tests/Migrations/Design/SnapshotModelProcessorTest.cs @@ -1084,7 +1084,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder .HasAnnotation("ProductVersion", "3.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) + .HasAnnotation("SqlServer:IdentitySeed", 1); modelBuilder.Entity( "Ownership.OwningType1", b => @@ -1092,7 +1093,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) + .HasAnnotation("SqlServer:IdentitySeed", 1); b.HasKey("Id"); From be28cc7692441440b66f3c58db64046d7521fccd Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 3 Sep 2021 03:32:35 +0000 Subject: [PATCH 017/346] Update dependencies from https://github.com/dotnet/runtime build 20210902.21 (#25858) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 3cbc50cefd1..7b076264012 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d - + https://github.com/dotnet/runtime - af90ed66fe7e7bbd14003a775e9834fe699b3781 + a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d diff --git a/eng/Versions.props b/eng/Versions.props index f7e5d33fc58..2a608b6732d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 - 6.0.0-rc.2.21452.18 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.21 3.7.0 From d61cb482763e3d17ec3c1c6de652dc55282afa59 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 3 Sep 2021 05:12:05 +0000 Subject: [PATCH 018/346] Update dependencies from https://github.com/dotnet/runtime build 20210902.24 (#25859) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7b076264012..04294e9c539 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 - + https://github.com/dotnet/runtime - a209a8994cc52ec6d6bf9266ee978f03ec4a5a2d + 317dd69498a5b1f82622adbd1606c9430331dbd4 diff --git a/eng/Versions.props b/eng/Versions.props index 2a608b6732d..bdc16e8eb51 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 - 6.0.0-rc.2.21452.21 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21452.24 3.7.0 From b27ab4bfc18bdd7169a7244201b7b71c8cb1e59e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 3 Sep 2021 14:50:52 +0000 Subject: [PATCH 019/346] Update dependencies from https://github.com/dotnet/runtime build 20210903.3 (#25862) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 04294e9c539..cace2e60610 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae - + https://github.com/dotnet/runtime - 317dd69498a5b1f82622adbd1606c9430331dbd4 + 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae diff --git a/eng/Versions.props b/eng/Versions.props index bdc16e8eb51..d85e7b4a816 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 - 6.0.0-rc.2.21452.24 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.3 3.7.0 From 61a0cac4252f6aa1c90bc7618c13909cba0b8686 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Fri, 3 Sep 2021 17:56:35 +0100 Subject: [PATCH 020/346] Reset unknown original value when current value is set (#25837) Fixes #22465 --- .../Internal/InternalEntityEntry.cs | 18 +++++- src/EFCore/Update/UpdateEntryExtensions.cs | 5 ++ .../GraphUpdates/GraphUpdatesTestBase.cs | 36 ++++++++++++ .../GraphUpdatesTestBaseMiscellaneous.cs | 58 +++++++++++++++++++ .../GraphUpdates/GraphUpdatesSqlServerTest.cs | 7 +++ .../Internal/InternalEntityEntryTestBase.cs | 4 +- 6 files changed, 125 insertions(+), 3 deletions(-) diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index b26d44f687e..0356f722dce 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -448,6 +448,15 @@ public bool IsModified(IProperty property) && !_stateData.IsPropertyFlagged(propertyIndex, PropertyFlag.Unknown); } + /// + /// 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 bool IsUnknown(IProperty property) + => _stateData.IsPropertyFlagged(property.GetIndex(), PropertyFlag.Unknown); + /// /// 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 @@ -1322,7 +1331,14 @@ private void SetProperty( if (propertyIndex != -1) { - _stateData.FlagProperty(propertyIndex, PropertyFlag.Unknown, isFlagged: false); + if (_stateData.IsPropertyFlagged(propertyIndex, PropertyFlag.Unknown)) + { + if (!_originalValues.IsEmpty) + { + SetOriginalValue(propertyBase, value); + } + _stateData.FlagProperty(propertyIndex, PropertyFlag.Unknown, isFlagged: false); + } } if (propertyBase is INavigationBase navigation) diff --git a/src/EFCore/Update/UpdateEntryExtensions.cs b/src/EFCore/Update/UpdateEntryExtensions.cs index eade04b0dc1..1ae84b8ec96 100644 --- a/src/EFCore/Update/UpdateEntryExtensions.cs +++ b/src/EFCore/Update/UpdateEntryExtensions.cs @@ -113,6 +113,11 @@ public static string ToDebugString( builder.Append(" Temporary"); } + if (entry.IsUnknown(property)) + { + builder.Append(" Unknown"); + } + if (entry.HasOriginalValuesSnapshot && property.GetOriginalValueIndex() != -1) { diff --git a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs index 760c76c2cf2..a859713275b 100644 --- a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs +++ b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs @@ -470,6 +470,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con b.HasKey("PartnerId", "ProviderId"); }); + + modelBuilder.Entity( + b => + { + b.Property("EntityZId"); + b.HasOne(e => e.EntityZ).WithMany().HasForeignKey("EntityZId").IsRequired(); + }); } protected virtual object CreateFullGraph() @@ -3377,6 +3384,35 @@ public string Id } } + protected class EventDescriptorZ : NotifyingEntity + { + private int _id; + private EntityZ _entityZ; + + public int Id + { + get => _id; + set => SetWithNotify(value, ref _id); + } + + public EntityZ EntityZ + { + get => _entityZ; + set => SetWithNotify(value, ref _entityZ); + } + } + + protected class EntityZ : NotifyingEntity + { + private long _id; + + public long Id + { + get => _id; + set => _id = value; + } + } + protected class NotifyingEntity : INotifyPropertyChanging, INotifyPropertyChanged { protected void SetWithNotify(T value, ref T field, [CallerMemberName] string propertyName = "") diff --git a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs index 202df790439..243cceadf8b 100644 --- a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs +++ b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs @@ -19,6 +19,64 @@ namespace Microsoft.EntityFrameworkCore public abstract partial class GraphUpdatesTestBase where TFixture : GraphUpdatesTestBase.GraphUpdatesFixtureBase, new() { + [ConditionalTheory] // Issue #22465 + [InlineData(false)] + [InlineData(true)] + public virtual async Task Reset_unknown_original_value_when_current_value_is_set(bool async) + { + await ExecuteWithStrategyInTransactionAsync( + async context => + { + var entityZ = new EntityZ(); + var eventZ = new EventDescriptorZ {EntityZ = entityZ}; + + if (async) + { + await context.AddRangeAsync(entityZ, eventZ); + await context.SaveChangesAsync(); + } + else + { + context.AddRange(entityZ, eventZ); + context.SaveChanges(); + } + + context.Entry(entityZ).State = EntityState.Detached; + context.Entry(eventZ).State = EntityState.Detached; + + context.Entry(entityZ).State = EntityState.Deleted; + context.Entry(eventZ).State = EntityState.Deleted; + + Assert.Same(entityZ, eventZ.EntityZ); + Assert.Equal(entityZ.Id, context.Entry(eventZ).Property("EntityZId").CurrentValue); + Assert.Equal(entityZ.Id, context.Entry(eventZ).Property("EntityZId").OriginalValue); + + if (async) + { + await context.SaveChangesAsync(); + } + else + { + context.SaveChanges(); + } + + Assert.Empty(context.ChangeTracker.Entries()); + }, + async context => + { + if (async) + { + Assert.False(await context.Set().AnyAsync()); + Assert.False(await context.Set().AnyAsync()); + } + else + { + Assert.False(context.Set().Any()); + Assert.False(context.Set().Any()); + } + }); + } + [ConditionalTheory] // Issue #19856 [InlineData(false)] [InlineData(true)] diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTest.cs index 220ab1aaa12..6b53f70486a 100644 --- a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTest.cs @@ -676,6 +676,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con b.HasKey("PartnerId", "ProviderId"); }); + + modelBuilder.Entity( + b => + { + b.Property("EntityZId"); + b.HasOne(e => e.EntityZ).WithMany().HasForeignKey("EntityZId").IsRequired(); + }); } } } diff --git a/test/EFCore.Tests/ChangeTracking/Internal/InternalEntityEntryTestBase.cs b/test/EFCore.Tests/ChangeTracking/Internal/InternalEntityEntryTestBase.cs index df4a25efcda..816e8fbc970 100644 --- a/test/EFCore.Tests/ChangeTracking/Internal/InternalEntityEntryTestBase.cs +++ b/test/EFCore.Tests/ChangeTracking/Internal/InternalEntityEntryTestBase.cs @@ -594,7 +594,7 @@ protected void NullOriginalValuesTest(object entity) entry[nameProperty] = "Beans"; - Assert.Null(entry.GetOriginalValue(nameProperty)); + Assert.Equal(nameProperty.IsShadowProperty() ? "Beans" : null, entry.GetOriginalValue(nameProperty)); Assert.Equal("Beans", entry[nameProperty]); entry.SetOriginalValue(nameProperty, "Franks"); @@ -627,7 +627,7 @@ protected void GenericNullOriginalValuesTest(object entity) entry[nameProperty] = "Beans"; - Assert.Null(entry.GetOriginalValue(nameProperty)); + Assert.Equal(nameProperty.IsShadowProperty() ? "Beans" : null, entry.GetOriginalValue(nameProperty)); Assert.Equal("Beans", entry.GetCurrentValue(nameProperty)); entry.SetOriginalValue(nameProperty, "Franks"); From b0210f02ae790e932442797b93c44e8480e5c21c Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Fri, 3 Sep 2021 19:58:50 +0200 Subject: [PATCH 021/346] Fix doc typo (#25861) Fixes #25860 --- .../Extensions/RelationalPropertyExtensions.cs | 12 ++++++------ src/EFCore.Relational/Metadata/IColumn.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs index 3dd907175f5..c8174eb0649 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs @@ -911,19 +911,19 @@ public static void SetDefaultValue(this IMutableProperty property, object? value } /// - /// Returns a flag indicating if the property as capable of storing only fixed-length data, such as strings. + /// Returns a flag indicating whether the property is capable of storing only fixed-length data, such as strings. /// /// The property. - /// A flag indicating if the property as capable of storing only fixed-length data, such as strings. + /// A flag indicating whether the property is capable of storing only fixed-length data, such as strings. public static bool? IsFixedLength(this IReadOnlyProperty property) => (bool?)property.FindAnnotation(RelationalAnnotationNames.IsFixedLength)?.Value; /// - /// Returns a flag indicating if the property as capable of storing only fixed-length data, such as strings. + /// Returns a flag indicating whether the property is capable of storing only fixed-length data, such as strings. /// /// The property. /// The identifier of the table-like store object containing the column. - /// A flag indicating if the property as capable of storing only fixed-length data, such as strings. + /// A flag indicating whether the property is capable of storing only fixed-length data, such as strings. public static bool? IsFixedLength(this IReadOnlyProperty property, in StoreObjectIdentifier storeObject) { var annotation = property.FindAnnotation(RelationalAnnotationNames.IsFixedLength); @@ -942,7 +942,7 @@ public static void SetDefaultValue(this IMutableProperty property, object? value } /// - /// Sets a flag indicating whether the property as capable of storing only fixed-length data, such as strings. + /// Sets a flag indicating whether the property is capable of storing only fixed-length data, such as strings. /// /// The property. /// A value indicating whether the property is constrained to fixed length values. @@ -950,7 +950,7 @@ public static void SetIsFixedLength(this IMutableProperty property, bool? fixedL => property.SetOrRemoveAnnotation(RelationalAnnotationNames.IsFixedLength, fixedLength); /// - /// Sets a flag indicating whether the property as capable of storing only fixed-length data, such as strings. + /// Sets a flag indicating whether the property is capable of storing only fixed-length data, such as strings. /// /// The property. /// A value indicating whether the property is constrained to fixed length values. diff --git a/src/EFCore.Relational/Metadata/IColumn.cs b/src/EFCore.Relational/Metadata/IColumn.cs index e6c32a04dd6..f9ea1081fa4 100644 --- a/src/EFCore.Relational/Metadata/IColumn.cs +++ b/src/EFCore.Relational/Metadata/IColumn.cs @@ -51,7 +51,7 @@ public interface IColumn : IColumnBase => PropertyMappings.First().Property.IsUnicode(StoreObjectIdentifier.Table(Table.Name, Table.Schema)); /// - /// Returns a flag indicating if the property as capable of storing only fixed-length data, such as strings. + /// Returns a flag indicating whether the property is capable of storing only fixed-length data, such as strings. /// bool? IsFixedLength => PropertyMappings.First().Property.IsFixedLength(StoreObjectIdentifier.Table(Table.Name, Table.Schema)); From 16ef6fda852215a7095722d9eed09b04882b1d5f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 3 Sep 2021 17:59:30 +0000 Subject: [PATCH 022/346] Update dependencies from https://github.com/dotnet/runtime build 20210903.6 (#25866) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index cace2e60610..9e6315e3cfa 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 - + https://github.com/dotnet/runtime - 41dcbd6a2a7e7963f2a508a8b36cad8689d1e4ae + 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 diff --git a/eng/Versions.props b/eng/Versions.props index d85e7b4a816..dc0edc254bb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 - 6.0.0-rc.2.21453.3 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.6 3.7.0 From d82352e3a3bd46683a26cd765c2a0647507fc8bf Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Fri, 3 Sep 2021 11:21:04 -0700 Subject: [PATCH 023/346] Reuse some IExecutionStrategy instances. Don't pass null to ExecutionStrategy.ShouldRetryOn. Use the currently executing strategy to determine whether buffering is needed. Fixes #21350 Fixes #23019 Fixes #21463 --- .../Storage/Internal/CosmosClientWrapper.cs | 242 +++++++++--------- .../Internal/CosmosExecutionStrategy.cs | 4 +- .../RelationalDatabaseFacadeExtensions.cs | 45 ++-- .../Internal/FromSqlQueryingEnumerable.cs | 6 +- .../Internal/SingleQueryingEnumerable.cs | 6 +- .../Query/Internal/SplitQueryingEnumerable.cs | 21 +- ...elationalCompiledQueryCacheKeyGenerator.cs | 3 +- .../RelationalDatabaseFacadeDependencies.cs | 10 + .../RelationalDatabaseCreatorDependencies.cs | 24 +- .../SqlServerRetryingExecutionStrategy.cs | 4 +- .../Internal/SqlServerDatabaseCreator.cs | 47 ++-- .../ChangeTracking/Internal/StateManager.cs | 21 +- .../Internal/StateManagerDependencies.cs | 14 + src/EFCore/Infrastructure/DatabaseFacade.cs | 2 +- .../EntityFrameworkServicesBuilder.cs | 2 + ...piledQueryCacheKeyGeneratorDependencies.cs | 8 +- src/EFCore/Query/QueryCompilationContext.cs | 3 +- .../QueryCompilationContextDependencies.cs | 14 +- src/EFCore/Query/QueryContext.cs | 7 + src/EFCore/Query/QueryContextDependencies.cs | 16 +- src/EFCore/Storage/ExecutionStrategy.cs | 53 ++-- .../Storage/IDatabaseFacadeDependencies.cs | 5 + src/EFCore/Storage/IExecutionStrategy.cs | 11 +- .../Storage/IExecutionStrategyFactory.cs | 4 +- .../Internal/DatabaseFacadeDependencies.cs | 10 + .../Internal/ExecutionStrategyFactory.cs | 10 +- .../SqlServerDatabaseCreatorTest.cs | 2 + .../Storage/ExecutionStrategyTest.cs | 35 ++- 28 files changed, 346 insertions(+), 283 deletions(-) diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs index 3d4ebc4b6a3..1c1db963b6d 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs @@ -62,7 +62,7 @@ public class CosmosClientWrapper : ICosmosClientWrapper private readonly ISingletonCosmosClientWrapper _singletonWrapper; private readonly string _databaseId; - private readonly IExecutionStrategyFactory _executionStrategyFactory; + private readonly IExecutionStrategy _executionStrategy; private readonly IDiagnosticsLogger _commandLogger; private readonly bool? _enableContentResponseOnWrite; @@ -83,14 +83,14 @@ static CosmosClientWrapper() public CosmosClientWrapper( ISingletonCosmosClientWrapper singletonWrapper, IDbContextOptions dbContextOptions, - IExecutionStrategyFactory executionStrategyFactory, + IExecutionStrategy executionStrategy, IDiagnosticsLogger commandLogger) { var options = dbContextOptions.FindExtension(); _singletonWrapper = singletonWrapper; _databaseId = options!.DatabaseName; - _executionStrategyFactory = executionStrategyFactory; + _executionStrategy = executionStrategy; _commandLogger = commandLogger; _enableContentResponseOnWrite = options.EnableContentResponseOnWrite; } @@ -105,19 +105,12 @@ private CosmosClient Client /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool CreateDatabaseIfNotExists(ThroughputProperties? throughput) - => _executionStrategyFactory.Create().Execute( - throughput, CreateDatabaseIfNotExistsOnce, null); + => _executionStrategy.Execute((throughput, this), CreateDatabaseIfNotExistsOnce, 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 virtual bool CreateDatabaseIfNotExistsOnce( + private static bool CreateDatabaseIfNotExistsOnce( DbContext? context, - ThroughputProperties? throughput) - => CreateDatabaseIfNotExistsOnceAsync(context, throughput).GetAwaiter().GetResult(); + (ThroughputProperties? Throughput, CosmosClientWrapper Wrapper) parameters) + => CreateDatabaseIfNotExistsOnceAsync(context, parameters).GetAwaiter().GetResult(); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -128,21 +121,16 @@ public virtual bool CreateDatabaseIfNotExistsOnce( public virtual Task CreateDatabaseIfNotExistsAsync( ThroughputProperties? throughput, CancellationToken cancellationToken = default) - => _executionStrategyFactory.Create().ExecuteAsync( - throughput, CreateDatabaseIfNotExistsOnceAsync, null, cancellationToken); + => _executionStrategy.ExecuteAsync( + (throughput, this), CreateDatabaseIfNotExistsOnceAsync, null, cancellationToken); - /// - /// 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 async Task CreateDatabaseIfNotExistsOnceAsync( + private static async Task CreateDatabaseIfNotExistsOnceAsync( DbContext? _, - ThroughputProperties? throughput, + (ThroughputProperties? Throughput, CosmosClientWrapper Wrapper) parameters, CancellationToken cancellationToken = default) { - var response = await Client.CreateDatabaseIfNotExistsAsync(_databaseId, throughput, cancellationToken: cancellationToken) + var (throughput, wrapper) = parameters; + var response = await wrapper.Client.CreateDatabaseIfNotExistsAsync(wrapper._databaseId, throughput, cancellationToken: cancellationToken) .ConfigureAwait(false); return response.StatusCode == HttpStatusCode.Created; @@ -155,18 +143,12 @@ public virtual async Task CreateDatabaseIfNotExistsOnceAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool DeleteDatabase() - => _executionStrategyFactory.Create().Execute((object?)null, DeleteDatabaseOnce, null); + => _executionStrategy.Execute(this, DeleteDatabaseOnce, 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 virtual bool DeleteDatabaseOnce( + private static bool DeleteDatabaseOnce( DbContext? context, - object? state) - => DeleteDatabaseOnceAsync(context, state).GetAwaiter().GetResult(); + CosmosClientWrapper wrapper) + => DeleteDatabaseOnceAsync(context, wrapper).GetAwaiter().GetResult(); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -176,21 +158,14 @@ public virtual bool DeleteDatabaseOnce( /// public virtual Task DeleteDatabaseAsync( CancellationToken cancellationToken = default) - => _executionStrategyFactory.Create().ExecuteAsync( - (object?)null, DeleteDatabaseOnceAsync, null, cancellationToken); + => _executionStrategy.ExecuteAsync(this, DeleteDatabaseOnceAsync, null, cancellationToken); - /// - /// 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 async Task DeleteDatabaseOnceAsync( + private static async Task DeleteDatabaseOnceAsync( DbContext? _, - object? __, + CosmosClientWrapper wrapper, CancellationToken cancellationToken = default) { - using var response = await Client.GetDatabase(_databaseId).DeleteStreamAsync(cancellationToken: cancellationToken) + using var response = await wrapper.Client.GetDatabase(wrapper._databaseId).DeleteStreamAsync(cancellationToken: cancellationToken) .ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.NotFound) { @@ -208,13 +183,12 @@ public virtual async Task DeleteDatabaseOnceAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual bool CreateContainerIfNotExists(ContainerProperties properties) - => _executionStrategyFactory.Create().Execute( - properties, CreateContainerIfNotExistsOnce, null); + => _executionStrategy.Execute((properties, this), CreateContainerIfNotExistsOnce, null); - private bool CreateContainerIfNotExistsOnce( + private static bool CreateContainerIfNotExistsOnce( DbContext context, - ContainerProperties parameters) - => CreateContainerIfNotExistsOnceAsync(context, parameters).GetAwaiter().GetResult(); + (ContainerProperties Parameters, CosmosClientWrapper Wrapper) parametersTuple) + => CreateContainerIfNotExistsOnceAsync(context, parametersTuple).GetAwaiter().GetResult(); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -223,15 +197,16 @@ private bool CreateContainerIfNotExistsOnce( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual Task CreateContainerIfNotExistsAsync(ContainerProperties properties, CancellationToken cancellationToken = default) - => _executionStrategyFactory.Create().ExecuteAsync( - properties, CreateContainerIfNotExistsOnceAsync, null, cancellationToken); + => _executionStrategy.ExecuteAsync((properties, this), CreateContainerIfNotExistsOnceAsync, null, cancellationToken); - private async Task CreateContainerIfNotExistsOnceAsync( + private static async Task CreateContainerIfNotExistsOnceAsync( DbContext _, - ContainerProperties parameters, + (ContainerProperties Parameters, CosmosClientWrapper Wrapper) parametersTuple, CancellationToken cancellationToken = default) { - using var response = await Client.GetDatabase(_databaseId).CreateContainerStreamAsync( + var parameters = parametersTuple.Parameters; + var wrapper = parametersTuple.Wrapper; + using var response = await wrapper.Client.GetDatabase(wrapper._databaseId).CreateContainerStreamAsync( new Azure.Cosmos.ContainerProperties(parameters.Id, "/" + parameters.PartitionKey) { PartitionKeyDefinitionVersion = PartitionKeyDefinitionVersion.V2, @@ -260,12 +235,11 @@ public virtual bool CreateItem( string containerId, JToken document, IUpdateEntry entry) - => _executionStrategyFactory.Create().Execute( - (containerId, document, entry), CreateItemOnce, null); + => _executionStrategy.Execute((containerId, document, entry, this), CreateItemOnce, null); - private bool CreateItemOnce( + private static bool CreateItemOnce( DbContext context, - (string ContainerId, JToken Document, IUpdateEntry Entry) parameters) + (string ContainerId, JToken Document, IUpdateEntry Entry, CosmosClientWrapper Wrapper) parameters) => CreateItemOnceAsync(context, parameters).GetAwaiter().GetResult(); /// @@ -279,12 +253,11 @@ public virtual Task CreateItemAsync( JToken document, IUpdateEntry updateEntry, CancellationToken cancellationToken = default) - => _executionStrategyFactory.Create().ExecuteAsync( - (containerId, document, updateEntry), CreateItemOnceAsync, null, cancellationToken); + => _executionStrategy.ExecuteAsync((containerId, document, updateEntry, this), CreateItemOnceAsync, null, cancellationToken); - private async Task CreateItemOnceAsync( + private async static Task CreateItemOnceAsync( DbContext _, - (string ContainerId, JToken Document, IUpdateEntry Entry) parameters, + (string ContainerId, JToken Document, IUpdateEntry Entry, CosmosClientWrapper Wrapper) parameters, CancellationToken cancellationToken = default) { await using var stream = new MemoryStream(); @@ -294,8 +267,9 @@ private async Task CreateItemOnceAsync( await jsonWriter.FlushAsync(cancellationToken).ConfigureAwait(false); var entry = parameters.Entry; - var container = Client.GetDatabase(_databaseId).GetContainer(parameters.ContainerId); - var itemRequestOptions = CreateItemRequestOptions(entry); + var wrapper = parameters.Wrapper; + var container = wrapper.Client.GetDatabase(wrapper._databaseId).GetContainer(parameters.ContainerId); + var itemRequestOptions = CreateItemRequestOptions(entry, wrapper._enableContentResponseOnWrite); var partitionKey = CreatePartitionKey(entry); var response = await container.CreateItemStreamAsync( @@ -305,7 +279,7 @@ private async Task CreateItemOnceAsync( cancellationToken) .ConfigureAwait(false); - _commandLogger.ExecutedCreateItem( + wrapper._commandLogger.ExecutedCreateItem( response.Diagnostics.GetClientElapsedTime(), response.Headers.RequestCharge, response.Headers.ActivityId, @@ -329,14 +303,11 @@ public virtual bool ReplaceItem( string documentId, JObject document, IUpdateEntry entry) - => _executionStrategyFactory.Create().Execute( - (collectionId, documentId, document, entry), - ReplaceItemOnce, - null); + => _executionStrategy.Execute((collectionId, documentId, document, entry, this), ReplaceItemOnce, null); - private bool ReplaceItemOnce( + private static bool ReplaceItemOnce( DbContext context, - (string ContainerId, string ItemId, JObject Document, IUpdateEntry Entry) parameters) + (string ContainerId, string ItemId, JObject Document, IUpdateEntry Entry, CosmosClientWrapper Wrapper) parameters) => ReplaceItemOnceAsync(context, parameters).GetAwaiter().GetResult(); /// @@ -351,15 +322,12 @@ public virtual Task ReplaceItemAsync( JObject document, IUpdateEntry updateEntry, CancellationToken cancellationToken = default) - => _executionStrategyFactory.Create().ExecuteAsync( - (collectionId, documentId, document, updateEntry), - ReplaceItemOnceAsync, - null, - cancellationToken); + => _executionStrategy.ExecuteAsync( + (collectionId, documentId, document, updateEntry, this), ReplaceItemOnceAsync, null, cancellationToken); - private async Task ReplaceItemOnceAsync( + private async static Task ReplaceItemOnceAsync( DbContext _, - (string ContainerId, string ResourceId, JObject Document, IUpdateEntry Entry) parameters, + (string ContainerId, string ResourceId, JObject Document, IUpdateEntry Entry, CosmosClientWrapper Wrapper) parameters, CancellationToken cancellationToken = default) { using var stream = new MemoryStream(); @@ -369,8 +337,9 @@ private async Task ReplaceItemOnceAsync( await jsonWriter.FlushAsync(cancellationToken).ConfigureAwait(false); var entry = parameters.Entry; - var container = Client.GetDatabase(_databaseId).GetContainer(parameters.ContainerId); - var itemRequestOptions = CreateItemRequestOptions(entry); + var wrapper = parameters.Wrapper; + var container = wrapper.Client.GetDatabase(wrapper._databaseId).GetContainer(parameters.ContainerId); + var itemRequestOptions = CreateItemRequestOptions(entry, wrapper._enableContentResponseOnWrite); var partitionKey = CreatePartitionKey(entry); using var response = await container.ReplaceItemStreamAsync( @@ -381,7 +350,7 @@ private async Task ReplaceItemOnceAsync( cancellationToken) .ConfigureAwait(false); - _commandLogger.ExecutedReplaceItem( + wrapper._commandLogger.ExecutedReplaceItem( response.Diagnostics.GetClientElapsedTime(), response.Headers.RequestCharge, response.Headers.ActivityId, @@ -404,18 +373,11 @@ public virtual bool DeleteItem( string containerId, string documentId, IUpdateEntry entry) - => _executionStrategyFactory.Create().Execute( - (containerId, documentId, entry), DeleteItemOnce, null); + => _executionStrategy.Execute((containerId, documentId, entry, this), DeleteItemOnce, 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 virtual bool DeleteItemOnce( + private static bool DeleteItemOnce( DbContext context, - (string ContainerId, string DocumentId, IUpdateEntry Entry) parameters) + (string ContainerId, string DocumentId, IUpdateEntry Entry, CosmosClientWrapper Wrapper) parameters) => DeleteItemOnceAsync(context, parameters).GetAwaiter().GetResult(); /// @@ -429,24 +391,18 @@ public virtual Task DeleteItemAsync( string documentId, IUpdateEntry entry, CancellationToken cancellationToken = default) - => _executionStrategyFactory.Create().ExecuteAsync( - (containerId, documentId, entry), DeleteItemOnceAsync, null, cancellationToken); + => _executionStrategy.ExecuteAsync((containerId, documentId, entry, this), DeleteItemOnceAsync, null, cancellationToken); - /// - /// 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 async Task DeleteItemOnceAsync( + private static async Task DeleteItemOnceAsync( DbContext? _, - (string ContainerId, string ResourceId, IUpdateEntry Entry) parameters, + (string ContainerId, string ResourceId, IUpdateEntry Entry, CosmosClientWrapper Wrapper) parameters, CancellationToken cancellationToken = default) { var entry = parameters.Entry; - var items = Client.GetDatabase(_databaseId).GetContainer(parameters.ContainerId); + var wrapper = parameters.Wrapper; + var items = wrapper.Client.GetDatabase(wrapper._databaseId).GetContainer(parameters.ContainerId); - var itemRequestOptions = CreateItemRequestOptions(entry); + var itemRequestOptions = CreateItemRequestOptions(entry, wrapper._enableContentResponseOnWrite); var partitionKey = CreatePartitionKey(entry); using var response = await items.DeleteItemStreamAsync( @@ -456,7 +412,7 @@ public virtual async Task DeleteItemOnceAsync( cancellationToken: cancellationToken) .ConfigureAwait(false); - _commandLogger.ExecutedDeleteItem( + wrapper._commandLogger.ExecutedDeleteItem( response.Diagnostics.GetClientElapsedTime(), response.Headers.RequestCharge, response.Headers.ActivityId, @@ -469,7 +425,7 @@ public virtual async Task DeleteItemOnceAsync( return response.StatusCode == HttpStatusCode.NoContent; } - private ItemRequestOptions? CreateItemRequestOptions(IUpdateEntry entry) + private static ItemRequestOptions? CreateItemRequestOptions(IUpdateEntry entry, bool? enableContentResponseOnWrite) { var etagProperty = entry.EntityType.GetETagProperty(); if (etagProperty == null) @@ -484,8 +440,32 @@ public virtual async Task DeleteItemOnceAsync( etag = converter.ConvertToProvider(etag); } - var enabledContentResponse = _enableContentResponseOnWrite - ?? entry.EntityType.FindProperty(StoreKeyConvention.JObjectPropertyName)?.ValueGenerated == ValueGenerated.OnAddOrUpdate; + bool enabledContentResponse; + if (enableContentResponseOnWrite.HasValue) + { + enabledContentResponse = enableContentResponseOnWrite.Value; + } + else + { + switch (entry.EntityState) + { + case EntityState.Modified: + { + var jObjectProperty = entry.EntityType.FindProperty(StoreKeyConvention.JObjectPropertyName); + enabledContentResponse = (jObjectProperty?.ValueGenerated & ValueGenerated.OnUpdate) == ValueGenerated.OnUpdate; + break; + } + case EntityState.Added: + { + var jObjectProperty = entry.EntityType.FindProperty(StoreKeyConvention.JObjectPropertyName); + enabledContentResponse = (jObjectProperty?.ValueGenerated & ValueGenerated.OnAdd) == ValueGenerated.OnAdd; + break; + } + default: + enabledContentResponse = false; + break; + } + } return new ItemRequestOptions { IfMatchEtag = (string?)etag, EnableContentResponseOnWrite = enabledContentResponse }; } @@ -578,8 +558,7 @@ public virtual JObject ExecuteReadItem( { _commandLogger.ExecutingReadItem(containerId, partitionKey, resourceId); - var response = CreateSingleItemQuery( - containerId, partitionKey, resourceId).GetAwaiter().GetResult(); + var response = _executionStrategy.Execute((containerId, partitionKey, resourceId, this), CreateSingleItemQuery, null); _commandLogger.ExecutedReadItem( response.Diagnostics.GetClientElapsedTime(), @@ -606,8 +585,11 @@ public virtual async Task ExecuteReadItemAsync( { _commandLogger.ExecutingReadItem(containerId, partitionKey, resourceId); - var response = await CreateSingleItemQuery( - containerId, partitionKey, resourceId, cancellationToken) + var response = await _executionStrategy.ExecuteAsync( + (containerId, partitionKey, resourceId, this), + CreateSingleItemQueryAsync, + null, + cancellationToken) .ConfigureAwait(false); _commandLogger.ExecutedReadItem( @@ -621,6 +603,25 @@ public virtual async Task ExecuteReadItemAsync( return JObjectFromReadItemResponseMessage(response); } + private static ResponseMessage CreateSingleItemQuery( + DbContext? context, + (string ContainerId, string? PartitionKey, string ResourceId, CosmosClientWrapper Wrapper) parameters) + => CreateSingleItemQueryAsync(context, parameters).GetAwaiter().GetResult(); + + private static Task CreateSingleItemQueryAsync( + DbContext? _, + (string ContainerId, string? PartitionKey, string ResourceId, CosmosClientWrapper Wrapper) parameters, + CancellationToken cancellationToken = default) + { + var (containerId, partitionKey, resourceId, wrapper) = parameters; + var container = wrapper.Client.GetDatabase(wrapper._databaseId).GetContainer(containerId); + + return container.ReadItemStreamAsync( + resourceId, + string.IsNullOrEmpty(partitionKey) ? PartitionKey.None : new PartitionKey(partitionKey), + cancellationToken: cancellationToken); + } + private static JObject JObjectFromReadItemResponseMessage(ResponseMessage responseMessage) { responseMessage.EnsureSuccessStatusCode(); @@ -663,21 +664,6 @@ public virtual FeedIterator CreateQuery( return container.GetItemQueryStreamIterator(queryDefinition, requestOptions: queryRequestOptions); } - private async Task CreateSingleItemQuery( - string containerId, - string? partitionKey, - string resourceId, - CancellationToken cancellationToken = default) - { - var container = Client.GetDatabase(_databaseId).GetContainer(containerId); - - return await container.ReadItemStreamAsync( - resourceId, - string.IsNullOrEmpty(partitionKey) ? PartitionKey.None : new PartitionKey(partitionKey), - cancellationToken: cancellationToken) - .ConfigureAwait(false); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static JsonTextReader CreateJsonReader(TextReader reader) { diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosExecutionStrategy.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosExecutionStrategy.cs index d56dddbac95..c7194060e06 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosExecutionStrategy.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosExecutionStrategy.cs @@ -96,7 +96,7 @@ public CosmosExecutionStrategy(ExecutionStrategyDependencies dependencies, int m /// 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. /// - protected override bool ShouldRetryOn(Exception? exception) + protected override bool ShouldRetryOn(Exception exception) { return exception switch { @@ -126,7 +126,7 @@ static bool IsTransient(HttpStatusCode statusCode) ?? baseDelay; } - private static TimeSpan? GetDelayFromException(Exception? exception) + private static TimeSpan? GetDelayFromException(Exception exception) { switch (exception) { diff --git a/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs b/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs index 58940cda9a6..eaa012d0053 100644 --- a/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs @@ -502,9 +502,8 @@ public static void SetConnectionString(this DatabaseFacade databaseFacade, strin /// /// The for the context. public static void OpenConnection(this DatabaseFacade databaseFacade) - => databaseFacade.CreateExecutionStrategy().Execute( - databaseFacade, database - => GetFacadeDependencies(database).RelationalConnection.Open()); + => ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Dependencies.ExecutionStrategy + .Execute(databaseFacade, database => GetFacadeDependencies(database).RelationalConnection.Open(), null); /// /// Opens the underlying . @@ -516,9 +515,8 @@ public static void OpenConnection(this DatabaseFacade databaseFacade) public static Task OpenConnectionAsync( this DatabaseFacade databaseFacade, CancellationToken cancellationToken = default) - => databaseFacade.CreateExecutionStrategy().ExecuteAsync( - databaseFacade, (database, ct) => - GetFacadeDependencies(database).RelationalConnection.OpenAsync(ct), cancellationToken); + => ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Dependencies.ExecutionStrategy + .ExecuteAsync(databaseFacade, (database, ct) => GetFacadeDependencies(database).RelationalConnection.OpenAsync(ct), null, cancellationToken); /// /// Closes the underlying . @@ -542,7 +540,7 @@ public static Task CloseConnectionAsync(this DatabaseFacade databaseFacade) /// The to use. /// A that represents the started transaction. public static IDbContextTransaction BeginTransaction(this DatabaseFacade databaseFacade, IsolationLevel isolationLevel) - => databaseFacade.CreateExecutionStrategy().Execute( + => ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Dependencies.ExecutionStrategy.Execute( databaseFacade, database => { var transactionManager = database.GetTransactionManager(); @@ -550,7 +548,8 @@ public static IDbContextTransaction BeginTransaction(this DatabaseFacade databas return transactionManager is IRelationalTransactionManager relationalTransactionManager ? relationalTransactionManager.BeginTransaction(isolationLevel) : transactionManager.BeginTransaction(); - }); + }, + null); /// /// Asynchronously starts a new transaction with a given . @@ -567,7 +566,7 @@ public static Task BeginTransactionAsync( this DatabaseFacade databaseFacade, IsolationLevel isolationLevel, CancellationToken cancellationToken = default) - => databaseFacade.CreateExecutionStrategy().ExecuteAsync( + => ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Dependencies.ExecutionStrategy.ExecuteAsync( databaseFacade, (database, ct) => { var transactionManager = database.GetTransactionManager(); @@ -575,7 +574,7 @@ public static Task BeginTransactionAsync( return transactionManager is IRelationalTransactionManager relationalTransactionManager ? relationalTransactionManager.BeginTransactionAsync(isolationLevel, ct) : transactionManager.BeginTransactionAsync(ct); - }, cancellationToken); + }, null, cancellationToken); /// /// Sets the to be used by database operations on the . @@ -599,16 +598,9 @@ public static Task BeginTransactionAsync( this DatabaseFacade databaseFacade, DbTransaction? transaction, Guid transactionId) - { - var transactionManager = GetTransactionManager(databaseFacade); - - if (!(transactionManager is IRelationalTransactionManager relationalTransactionManager)) - { - throw new InvalidOperationException(RelationalStrings.RelationalNotInUse); - } - - return relationalTransactionManager.UseTransaction(transaction, transactionId); - } + => GetTransactionManager(databaseFacade) is IRelationalTransactionManager relationalTransactionManager + ? relationalTransactionManager.UseTransaction(transaction, transactionId) + : throw new InvalidOperationException(RelationalStrings.RelationalNotInUse); /// /// Sets the to be used by database operations on the . @@ -638,16 +630,9 @@ public static Task BeginTransactionAsync( DbTransaction? transaction, Guid transactionId, CancellationToken cancellationToken = default) - { - var transactionManager = GetTransactionManager(databaseFacade); - - if (!(transactionManager is IRelationalTransactionManager relationalTransactionManager)) - { - throw new InvalidOperationException(RelationalStrings.RelationalNotInUse); - } - - return relationalTransactionManager.UseTransactionAsync(transaction, transactionId, cancellationToken); - } + => GetTransactionManager(databaseFacade) is IRelationalTransactionManager relationalTransactionManager + ? relationalTransactionManager.UseTransactionAsync(transaction, transactionId, cancellationToken) + : throw new InvalidOperationException(RelationalStrings.RelationalNotInUse); /// /// diff --git a/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs index 455b90d7daf..497c2718c3a 100644 --- a/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs @@ -197,8 +197,7 @@ public bool MoveNext() { if (_dataReader == null) { - _relationalQueryContext.ExecutionStrategyFactory.Create() - .Execute(this, (_, enumerator) => InitializeReader(enumerator), null); + _relationalQueryContext.ExecutionStrategy.Execute(this, (_, enumerator) => InitializeReader(enumerator), null); } var hasNext = _dataReader!.Read(); @@ -303,8 +302,7 @@ public async ValueTask MoveNextAsync() { if (_dataReader == null) { - await _relationalQueryContext.ExecutionStrategyFactory.Create() - .ExecuteAsync( + await _relationalQueryContext.ExecutionStrategy.ExecuteAsync( this, (_, enumerator, cancellationToken) => InitializeReaderAsync(enumerator, cancellationToken), null, diff --git a/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs index a3e43cb0416..f1eab3f3954 100644 --- a/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs @@ -165,8 +165,7 @@ public bool MoveNext() { if (_dataReader == null) { - _relationalQueryContext.ExecutionStrategyFactory.Create() - .Execute(this, static (_, enumerator) => InitializeReader(enumerator), null); + _relationalQueryContext.ExecutionStrategy.Execute(this, static (_, enumerator) => InitializeReader(enumerator), null); } var hasNext = _resultCoordinator!.HasNext ?? _dataReader!.Read(); @@ -303,8 +302,7 @@ public async ValueTask MoveNextAsync() { if (_dataReader == null) { - await _relationalQueryContext.ExecutionStrategyFactory.Create() - .ExecuteAsync( + await _relationalQueryContext.ExecutionStrategy.ExecuteAsync( this, static (_, enumerator, cancellationToken) => InitializeReaderAsync(enumerator, cancellationToken), null, diff --git a/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs b/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs index c72b0639741..8b208a4780a 100644 --- a/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs @@ -141,7 +141,6 @@ private sealed class Enumerator : IEnumerator private RelationalDataReader? _dataReader; private DbDataReader? _dbDataReader; private SplitQueryResultCoordinator? _resultCoordinator; - private IExecutionStrategy? _executionStrategy; public Enumerator(SplitQueryingEnumerable queryingEnumerable) { @@ -175,12 +174,7 @@ public bool MoveNext() { if (_dataReader == null) { - if (_executionStrategy == null) - { - _executionStrategy = _relationalQueryContext.ExecutionStrategyFactory.Create(); - } - - _executionStrategy.Execute(this, static (_, enumerator) => InitializeReader(enumerator), null); + _relationalQueryContext.ExecutionStrategy.Execute(this, static (_, enumerator) => InitializeReader(enumerator), null); } var hasNext = _dataReader!.Read(); @@ -192,7 +186,7 @@ public bool MoveNext() _relationalQueryContext, _dbDataReader!, _resultCoordinator.ResultContext, _resultCoordinator); if (_relatedDataLoaders != null) { - _relatedDataLoaders.Invoke(_relationalQueryContext, _executionStrategy!, _resultCoordinator); + _relatedDataLoaders.Invoke(_relationalQueryContext, _relationalQueryContext.ExecutionStrategy, _resultCoordinator); Current = _shaper( _relationalQueryContext, _dbDataReader!, _resultCoordinator.ResultContext, _resultCoordinator); } @@ -285,7 +279,6 @@ private sealed class AsyncEnumerator : IAsyncEnumerator private RelationalDataReader? _dataReader; private DbDataReader? _dbDataReader; private SplitQueryResultCoordinator? _resultCoordinator; - private IExecutionStrategy? _executionStrategy; public AsyncEnumerator(SplitQueryingEnumerable queryingEnumerable) { @@ -317,12 +310,7 @@ public async ValueTask MoveNextAsync() { if (_dataReader == null) { - if (_executionStrategy == null) - { - _executionStrategy = _relationalQueryContext.ExecutionStrategyFactory.Create(); - } - - await _executionStrategy.ExecuteAsync( + await _relationalQueryContext.ExecutionStrategy.ExecuteAsync( this, static (_, enumerator, cancellationToken) => InitializeReaderAsync(enumerator, cancellationToken), null, @@ -338,7 +326,7 @@ await _executionStrategy.ExecuteAsync( Current = _shaper(_relationalQueryContext, _dbDataReader!, _resultCoordinator.ResultContext, _resultCoordinator); if (_relatedDataLoaders != null) { - await _relatedDataLoaders(_relationalQueryContext, _executionStrategy!, _resultCoordinator) + await _relatedDataLoaders(_relationalQueryContext, _relationalQueryContext.ExecutionStrategy, _resultCoordinator) .ConfigureAwait(false); Current = _shaper(_relationalQueryContext, _dbDataReader!, _resultCoordinator.ResultContext, _resultCoordinator); @@ -408,6 +396,7 @@ public async ValueTask DisposeAsync() _resultCoordinator.DataReaders.Clear(); _resultCoordinator = null; } + _dataReader = null; _dbDataReader = null; } diff --git a/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGenerator.cs b/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGenerator.cs index b7b55485b39..644f7de2477 100644 --- a/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGenerator.cs +++ b/src/EFCore.Relational/Query/RelationalCompiledQueryCacheKeyGenerator.cs @@ -4,6 +4,7 @@ using System; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -71,7 +72,7 @@ public override object GenerateCacheKey(Expression query, bool async) base.GenerateCacheKeyCore(query, async), relationalOptions.UseRelationalNulls, relationalOptions.QuerySplittingBehavior, - shouldBuffer: Dependencies.IsRetryingExecutionStrategy); + shouldBuffer: ExecutionStrategy.Current?.RetriesOnFailure ?? Dependencies.IsRetryingExecutionStrategy); } /// diff --git a/src/EFCore.Relational/Storage/Internal/RelationalDatabaseFacadeDependencies.cs b/src/EFCore.Relational/Storage/Internal/RelationalDatabaseFacadeDependencies.cs index e97c55b6124..835a6f160b5 100644 --- a/src/EFCore.Relational/Storage/Internal/RelationalDatabaseFacadeDependencies.cs +++ b/src/EFCore.Relational/Storage/Internal/RelationalDatabaseFacadeDependencies.cs @@ -24,6 +24,7 @@ public record RelationalDatabaseFacadeDependencies : IRelationalDatabaseFacadeDe public RelationalDatabaseFacadeDependencies( IDbContextTransactionManager transactionManager, IDatabaseCreator databaseCreator, + IExecutionStrategy executionStrategy, IExecutionStrategyFactory executionStrategyFactory, IEnumerable databaseProviders, IRelationalCommandDiagnosticsLogger commandLogger, @@ -34,6 +35,7 @@ public RelationalDatabaseFacadeDependencies( { TransactionManager = transactionManager; DatabaseCreator = databaseCreator; + ExecutionStrategy = executionStrategy; ExecutionStrategyFactory = executionStrategyFactory; DatabaseProviders = databaseProviders; CommandLogger = commandLogger; @@ -59,6 +61,14 @@ public RelationalDatabaseFacadeDependencies( /// public virtual IDatabaseCreator DatabaseCreator { get; init; } + /// + /// 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 IExecutionStrategy ExecutionStrategy { get; init; } + /// /// 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.Relational/Storage/RelationalDatabaseCreatorDependencies.cs b/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs index fa1ee092169..3615c6f2d90 100644 --- a/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs @@ -69,20 +69,11 @@ public RelationalDatabaseCreatorDependencies( IMigrationsSqlGenerator migrationsSqlGenerator, IMigrationCommandExecutor migrationCommandExecutor, ISqlGenerationHelper sqlGenerationHelper, + IExecutionStrategy executionStrategy, IExecutionStrategyFactory executionStrategyFactory, ICurrentDbContext currentContext, IRelationalCommandDiagnosticsLogger commandLogger) { - Check.NotNull(model, nameof(model)); - Check.NotNull(connection, nameof(connection)); - Check.NotNull(modelDiffer, nameof(modelDiffer)); - Check.NotNull(migrationsSqlGenerator, nameof(migrationsSqlGenerator)); - Check.NotNull(migrationCommandExecutor, nameof(migrationCommandExecutor)); - Check.NotNull(sqlGenerationHelper, nameof(sqlGenerationHelper)); - Check.NotNull(executionStrategyFactory, nameof(executionStrategyFactory)); - Check.NotNull(currentContext, nameof(currentContext)); - Check.NotNull(commandLogger, nameof(commandLogger)); - #pragma warning disable CS0618 // Type or member is obsolete Model = model; #pragma warning restore CS0618 // Type or member is obsolete @@ -91,7 +82,10 @@ public RelationalDatabaseCreatorDependencies( MigrationsSqlGenerator = migrationsSqlGenerator; MigrationCommandExecutor = migrationCommandExecutor; SqlGenerationHelper = sqlGenerationHelper; + ExecutionStrategy = executionStrategy; +#pragma warning disable CS0618 // Type or member is obsolete ExecutionStrategyFactory = executionStrategyFactory; +#pragma warning restore CS0618 // Type or member is obsolete CurrentContext = currentContext; CommandLogger = commandLogger; } @@ -128,12 +122,18 @@ public RelationalDatabaseCreatorDependencies( public ISqlGenerationHelper SqlGenerationHelper { get; init; } /// - /// Gets the to be used. + /// Gets the execution strategy. + /// + public IExecutionStrategy ExecutionStrategy { get; } + + /// + /// Gets the execution strategy factory to be used. /// + [Obsolete("Use ExecutionStrategy instead")] public IExecutionStrategyFactory ExecutionStrategyFactory { get; init; } /// - /// The command logger. + /// Gets the command logger. /// public IRelationalCommandDiagnosticsLogger CommandLogger { get; init; } diff --git a/src/EFCore.SqlServer/SqlServerRetryingExecutionStrategy.cs b/src/EFCore.SqlServer/SqlServerRetryingExecutionStrategy.cs index bed5a5f83fc..e5a11f8f724 100644 --- a/src/EFCore.SqlServer/SqlServerRetryingExecutionStrategy.cs +++ b/src/EFCore.SqlServer/SqlServerRetryingExecutionStrategy.cs @@ -128,7 +128,7 @@ public SqlServerRetryingExecutionStrategy( /// /// if the specified exception is considered as transient, otherwise . /// - protected override bool ShouldRetryOn(Exception? exception) + protected override bool ShouldRetryOn(Exception exception) { if (_additionalErrorNumbers != null && exception is SqlException sqlException) @@ -166,7 +166,7 @@ protected override bool ShouldRetryOn(Exception? exception) : baseDelay; } - private static bool IsMemoryOptimizedError(Exception? exception) + private static bool IsMemoryOptimizedError(Exception exception) { if (exception is SqlException sqlException) { diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerDatabaseCreator.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerDatabaseCreator.cs index 0aacc0d8c30..116ba88198e 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerDatabaseCreator.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerDatabaseCreator.cs @@ -116,19 +116,18 @@ await ExistsAsync(retryOnNotExists: true, cancellationToken: cancellationToken) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override bool HasTables() - => Dependencies.ExecutionStrategyFactory - .Create() - .Execute( - _connection, - connection => (int)CreateHasTablesCommand() - .ExecuteScalar( - new RelationalCommandParameterObject( - connection, - null, - null, - Dependencies.CurrentContext.Context, - Dependencies.CommandLogger, CommandSource.Migrations))! - != 0); + => Dependencies.ExecutionStrategy.Execute( + _connection, + connection => (int)CreateHasTablesCommand() + .ExecuteScalar( + new RelationalCommandParameterObject( + connection, + null, + null, + Dependencies.CurrentContext.Context, + Dependencies.CommandLogger, CommandSource.Migrations))! + != 0, + null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -136,10 +135,10 @@ public override bool HasTables() /// 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 Task HasTablesAsync(CancellationToken cancellationToken = default) - => Dependencies.ExecutionStrategyFactory.Create().ExecuteAsync( + public override async Task HasTablesAsync(CancellationToken cancellationToken = default) + => (int)(await Dependencies.ExecutionStrategy.ExecuteAsync( _connection, - async (connection, ct) => (int)(await CreateHasTablesCommand() + (connection, ct) => CreateHasTablesCommand() .ExecuteScalarAsync( new RelationalCommandParameterObject( connection, @@ -147,9 +146,10 @@ public override Task HasTablesAsync(CancellationToken cancellationToken = null, Dependencies.CurrentContext.Context, Dependencies.CommandLogger, CommandSource.Migrations), - cancellationToken: ct) - .ConfigureAwait(false))! - != 0, cancellationToken); + cancellationToken: ct), + null, + cancellationToken).ConfigureAwait(false))! + != 0; private IRelationalCommand CreateHasTablesCommand() => _rawSqlCommandBuilder @@ -197,7 +197,7 @@ public override bool Exists() => Exists(retryOnNotExists: false); private bool Exists(bool retryOnNotExists) - => Dependencies.ExecutionStrategyFactory.Create().Execute( + => Dependencies.ExecutionStrategy.Execute( DateTime.UtcNow + RetryTimeout, giveUp => { while (true) @@ -245,7 +245,8 @@ private bool Exists(bool retryOnNotExists) } } } - }); + }, + null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -257,7 +258,7 @@ public override Task ExistsAsync(CancellationToken cancellationToken = def => ExistsAsync(retryOnNotExists: false, cancellationToken: cancellationToken); private Task ExistsAsync(bool retryOnNotExists, CancellationToken cancellationToken) - => Dependencies.ExecutionStrategyFactory.Create().ExecuteAsync( + => Dependencies.ExecutionStrategy.ExecuteAsync( DateTime.UtcNow + RetryTimeout, async (giveUp, ct) => { while (true) @@ -308,7 +309,7 @@ await _rawSqlCommandBuilder } } } - }, cancellationToken); + }, null, cancellationToken); // Login failed is thrown when database does not exist (See Issue #776) // Unable to attach database file is thrown when file does not exist (See Issue #2810) diff --git a/src/EFCore/ChangeTracking/Internal/StateManager.cs b/src/EFCore/ChangeTracking/Internal/StateManager.cs index 292a8b49906..e694e0eafd1 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManager.cs @@ -1162,12 +1162,11 @@ protected virtual async Task SaveChangesAsync( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual int SaveChanges(bool acceptAllChangesOnSuccess) - => Context.Database.AutoTransactionsEnabled - ? Dependencies.ExecutionStrategyFactory.Create().Execute( - (StateManager: this, AcceptAllChangesOnSuccess: acceptAllChangesOnSuccess), - (_, t) => SaveChanges(t.StateManager, t.AcceptAllChangesOnSuccess), - null) - : SaveChanges(this, acceptAllChangesOnSuccess); + => !Context.Database.AutoTransactionsEnabled + ? SaveChanges(this, acceptAllChangesOnSuccess) + : Dependencies.ExecutionStrategy.Execute((StateManager: this, AcceptAllChangesOnSuccess: acceptAllChangesOnSuccess), + static (_, t) => SaveChanges(t.StateManager, t.AcceptAllChangesOnSuccess), + null); private static int SaveChanges(StateManager stateManager, bool acceptAllChangesOnSuccess) { @@ -1218,13 +1217,13 @@ private static int SaveChanges(StateManager stateManager, bool acceptAllChangesO public virtual Task SaveChangesAsync( bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default) - => Context.Database.AutoTransactionsEnabled - ? Dependencies.ExecutionStrategyFactory.Create().ExecuteAsync( + => !Context.Database.AutoTransactionsEnabled + ? SaveChangesAsync(this, acceptAllChangesOnSuccess, cancellationToken) + : Dependencies.ExecutionStrategy.ExecuteAsync( (StateManager: this, AcceptAllChangesOnSuccess: acceptAllChangesOnSuccess), - (_, t, cancellationToken) => SaveChangesAsync(t.StateManager, t.AcceptAllChangesOnSuccess, cancellationToken), + static (_, t, cancellationToken) => SaveChangesAsync(t.StateManager, t.AcceptAllChangesOnSuccess, cancellationToken), null, - cancellationToken) - : SaveChangesAsync(this, acceptAllChangesOnSuccess, cancellationToken); + cancellationToken); private static async Task SaveChangesAsync( StateManager stateManager, diff --git a/src/EFCore/ChangeTracking/Internal/StateManagerDependencies.cs b/src/EFCore/ChangeTracking/Internal/StateManagerDependencies.cs index 9a0e340e3f7..a3265e6d9b1 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManagerDependencies.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManagerDependencies.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; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; @@ -73,6 +74,7 @@ public StateManagerDependencies( IEntityFinderSource entityFinderSource, IDbSetSource setSource, IEntityMaterializerSource entityMaterializerSource, + IExecutionStrategy executionStrategy, IExecutionStrategyFactory executionStrategyFactory, ICoreSingletonOptions coreSingletonOptions, ILoggingOptions loggingOptions, @@ -90,7 +92,10 @@ public StateManagerDependencies( EntityFinderSource = entityFinderSource; SetSource = setSource; EntityMaterializerSource = entityMaterializerSource; + ExecutionStrategy = executionStrategy; +#pragma warning disable CS0618 // Type or member is obsolete ExecutionStrategyFactory = executionStrategyFactory; +#pragma warning restore CS0618 // Type or member is obsolete CoreSingletonOptions = coreSingletonOptions; LoggingOptions = loggingOptions; UpdateLogger = updateLogger; @@ -186,6 +191,15 @@ public StateManagerDependencies( /// 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 IExecutionStrategy ExecutionStrategy { get; init; } + + /// + /// 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. + /// + [Obsolete("Use ExecutionStrategy instead")] public IExecutionStrategyFactory ExecutionStrategyFactory { get; init; } /// diff --git a/src/EFCore/Infrastructure/DatabaseFacade.cs b/src/EFCore/Infrastructure/DatabaseFacade.cs index 04531ff4b8e..6dd018ca6e2 100644 --- a/src/EFCore/Infrastructure/DatabaseFacade.cs +++ b/src/EFCore/Infrastructure/DatabaseFacade.cs @@ -27,7 +27,7 @@ public class DatabaseFacade : IInfrastructure, IDatabaseFacade /// obtained from and it is not designed to be directly constructed /// in your application code. /// - /// The context this database API belongs to . + /// The context this database API belongs to. public DatabaseFacade(DbContext context) { Check.NotNull(context, nameof(context)); diff --git a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs index ebb15526d8a..aae0e145b4e 100644 --- a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs +++ b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs @@ -116,6 +116,7 @@ public static readonly IDictionary CoreServices { typeof(IDbContextServices), new ServiceCharacteristics(ServiceLifetime.Scoped) }, { typeof(IValueGeneratorSelector), new ServiceCharacteristics(ServiceLifetime.Scoped) }, { typeof(IExecutionStrategyFactory), new ServiceCharacteristics(ServiceLifetime.Scoped) }, + { typeof(IExecutionStrategy), new ServiceCharacteristics(ServiceLifetime.Scoped) }, { typeof(IAsyncQueryProvider), new ServiceCharacteristics(ServiceLifetime.Scoped) }, { typeof(IQueryCompiler), new ServiceCharacteristics(ServiceLifetime.Scoped) }, { typeof(ICompiledQueryCacheKeyGenerator), new ServiceCharacteristics(ServiceLifetime.Scoped) }, @@ -279,6 +280,7 @@ public virtual EntityFrameworkServicesBuilder TryAddCoreServices() TryAdd(); TryAdd(); TryAdd(); + TryAdd(p => p.GetRequiredService().Create()); TryAdd(); TryAdd(); TryAdd(); diff --git a/src/EFCore/Query/CompiledQueryCacheKeyGeneratorDependencies.cs b/src/EFCore/Query/CompiledQueryCacheKeyGeneratorDependencies.cs index 4917bb66346..11e1d59cb1d 100644 --- a/src/EFCore/Query/CompiledQueryCacheKeyGeneratorDependencies.cs +++ b/src/EFCore/Query/CompiledQueryCacheKeyGeneratorDependencies.cs @@ -61,15 +61,11 @@ public sealed record CompiledQueryCacheKeyGeneratorDependencies public CompiledQueryCacheKeyGeneratorDependencies( IModel model, ICurrentDbContext currentContext, - IExecutionStrategyFactory executionStrategyFactory) + IExecutionStrategy executionStrategy) { - Check.NotNull(model, nameof(model)); - Check.NotNull(currentContext, nameof(currentContext)); - Check.NotNull(executionStrategyFactory, nameof(executionStrategyFactory)); - Model = model; CurrentContext = currentContext; - IsRetryingExecutionStrategy = executionStrategyFactory.Create().RetriesOnFailure; + IsRetryingExecutionStrategy = executionStrategy.RetriesOnFailure; } /// diff --git a/src/EFCore/Query/QueryCompilationContext.cs b/src/EFCore/Query/QueryCompilationContext.cs index 86db7be2015..03e8dd3e009 100644 --- a/src/EFCore/Query/QueryCompilationContext.cs +++ b/src/EFCore/Query/QueryCompilationContext.cs @@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query @@ -80,7 +81,7 @@ public QueryCompilationContext( Dependencies = dependencies; IsAsync = async; QueryTrackingBehavior = dependencies.QueryTrackingBehavior; - IsBuffering = dependencies.IsRetryingExecutionStrategy; + IsBuffering = ExecutionStrategy.Current?.RetriesOnFailure ?? dependencies.IsRetryingExecutionStrategy; Model = dependencies.Model; ContextOptions = dependencies.ContextOptions; ContextType = dependencies.ContextType; diff --git a/src/EFCore/Query/QueryCompilationContextDependencies.cs b/src/EFCore/Query/QueryCompilationContextDependencies.cs index b00cd030c59..486e4185f80 100644 --- a/src/EFCore/Query/QueryCompilationContextDependencies.cs +++ b/src/EFCore/Query/QueryCompilationContextDependencies.cs @@ -64,28 +64,18 @@ public QueryCompilationContextDependencies( IQueryableMethodTranslatingExpressionVisitorFactory queryableMethodTranslatingExpressionVisitorFactory, IQueryTranslationPostprocessorFactory queryTranslationPostprocessorFactory, IShapedQueryCompilingExpressionVisitorFactory shapedQueryCompilingExpressionVisitorFactory, - IExecutionStrategyFactory executionStrategyFactory, + IExecutionStrategy executionStrategy, ICurrentDbContext currentContext, IDbContextOptions contextOptions, IDiagnosticsLogger logger) { - Check.NotNull(model, nameof(model)); - Check.NotNull(queryTranslationPreprocessorFactory, nameof(queryTranslationPreprocessorFactory)); - Check.NotNull(queryableMethodTranslatingExpressionVisitorFactory, nameof(queryableMethodTranslatingExpressionVisitorFactory)); - Check.NotNull(queryTranslationPostprocessorFactory, nameof(queryTranslationPostprocessorFactory)); - Check.NotNull(shapedQueryCompilingExpressionVisitorFactory, nameof(shapedQueryCompilingExpressionVisitorFactory)); - Check.NotNull(executionStrategyFactory, nameof(executionStrategyFactory)); - Check.NotNull(currentContext, nameof(currentContext)); - Check.NotNull(contextOptions, nameof(contextOptions)); - Check.NotNull(logger, nameof(logger)); - _currentContext = currentContext; Model = model; QueryTranslationPreprocessorFactory = queryTranslationPreprocessorFactory; QueryableMethodTranslatingExpressionVisitorFactory = queryableMethodTranslatingExpressionVisitorFactory; QueryTranslationPostprocessorFactory = queryTranslationPostprocessorFactory; ShapedQueryCompilingExpressionVisitorFactory = shapedQueryCompilingExpressionVisitorFactory; - IsRetryingExecutionStrategy = executionStrategyFactory.Create().RetriesOnFailure; + IsRetryingExecutionStrategy = executionStrategy.RetriesOnFailure; ContextOptions = contextOptions; Logger = logger; } diff --git a/src/EFCore/Query/QueryContext.cs b/src/EFCore/Query/QueryContext.cs index 5f3f6fafc86..3fce3170962 100644 --- a/src/EFCore/Query/QueryContext.cs +++ b/src/EFCore/Query/QueryContext.cs @@ -79,9 +79,16 @@ public virtual void SetNavigationIsLoaded(object entity, INavigationBase navigat public virtual IQueryProvider QueryProvider => Dependencies.QueryProvider; + /// + /// The execution strategy to use while executing the query. + /// + public virtual IExecutionStrategy ExecutionStrategy + => Dependencies.ExecutionStrategy; + /// /// The execution strategy factory to use while executing the query. /// + [Obsolete("Use ExecutionStrategy instead")] public virtual IExecutionStrategyFactory ExecutionStrategyFactory => Dependencies.ExecutionStrategyFactory; diff --git a/src/EFCore/Query/QueryContextDependencies.cs b/src/EFCore/Query/QueryContextDependencies.cs index 05048d04d87..468d0e390f5 100644 --- a/src/EFCore/Query/QueryContextDependencies.cs +++ b/src/EFCore/Query/QueryContextDependencies.cs @@ -60,19 +60,17 @@ public sealed record QueryContextDependencies [EntityFrameworkInternal] public QueryContextDependencies( ICurrentDbContext currentContext, + IExecutionStrategy executionStrategy, IExecutionStrategyFactory executionStrategyFactory, IConcurrencyDetector concurrencyDetector, IDiagnosticsLogger commandLogger, IDiagnosticsLogger queryLogger) { - Check.NotNull(currentContext, nameof(currentContext)); - Check.NotNull(executionStrategyFactory, nameof(executionStrategyFactory)); - Check.NotNull(concurrencyDetector, nameof(concurrencyDetector)); - Check.NotNull(commandLogger, nameof(commandLogger)); - Check.NotNull(queryLogger, nameof(queryLogger)); - CurrentContext = currentContext; + ExecutionStrategy = executionStrategy; +#pragma warning disable CS0618 // Type or member is obsolete ExecutionStrategyFactory = executionStrategyFactory; +#pragma warning restore CS0618 // Type or member is obsolete ConcurrencyDetector = concurrencyDetector; CommandLogger = commandLogger; QueryLogger = queryLogger; @@ -103,6 +101,12 @@ public IQueryProvider QueryProvider /// /// The execution strategy. /// + public IExecutionStrategy ExecutionStrategy { get; init; } + + /// + /// The execution strategy factory. + /// + [Obsolete("Use ExecutionStrategy instead")] public IExecutionStrategyFactory ExecutionStrategyFactory { get; init; } /// diff --git a/src/EFCore/Storage/ExecutionStrategy.cs b/src/EFCore/Storage/ExecutionStrategy.cs index 4833106fb92..12aac0f7cbf 100644 --- a/src/EFCore/Storage/ExecutionStrategy.cs +++ b/src/EFCore/Storage/ExecutionStrategy.cs @@ -110,23 +110,39 @@ protected ExecutionStrategy( /// protected virtual ExecutionStrategyDependencies Dependencies { get; } - private static readonly AsyncLocal _suspended = new(); + private static readonly AsyncLocal _current = new(); /// /// Indicates whether the strategy is suspended. The strategy is typically suspending while executing to avoid /// recursive execution from nested operations. /// + [Obsolete("Use Current instead")] protected static bool Suspended { - get => _suspended.Value ?? false; - set => _suspended.Value = value; + get => Current != null; + set { } + } + + /// + /// Gets or sets the currently executing strategy. All nested calls will be handled by the outermost strategy. + /// + public static ExecutionStrategy? Current + { + get => _current.Value; + protected set => _current.Value = value; } /// /// Indicates whether this might retry the execution after a failure. /// public virtual bool RetriesOnFailure - => !Suspended && MaxRetryCount > 0; + { + get + { + var current = Current; + return (current == null || current == this) && MaxRetryCount > 0; + } + } /// /// Executes the specified operation and returns the result. @@ -149,7 +165,7 @@ public virtual TResult Execute( { Check.NotNull(operation, nameof(operation)); - if (Suspended) + if (Current != null) { return operation(Dependencies.CurrentContext.Context, state); } @@ -172,14 +188,16 @@ private ExecutionResult ExecuteImplementation( { try { - Suspended = true; + Check.DebugAssert(Current == null, "Current != null"); + + Current = this; var result = operation(Dependencies.CurrentContext.Context, state); - Suspended = false; + Current = null; return result; } catch (Exception ex) { - Suspended = false; + Current = null; EntityFrameworkEventSource.Log.ExecutionStrategyOperationFailure(); @@ -247,7 +265,7 @@ public virtual async Task ExecuteAsync( { Check.NotNull(operation, nameof(operation)); - if (Suspended) + if (Current != null) { return await operation(Dependencies.CurrentContext.Context, state, cancellationToken).ConfigureAwait(false); } @@ -275,15 +293,17 @@ private async Task> ExecuteImplementationAsync /// if the specified exception could be thrown after a successful execution, otherwise . /// - protected internal virtual bool ShouldVerifySuccessOn(Exception? exception) + protected internal virtual bool ShouldVerifySuccessOn(Exception exception) => ShouldRetryOn(exception); /// @@ -395,7 +415,7 @@ protected internal virtual bool ShouldVerifySuccessOn(Exception? exception) /// /// if the specified exception is considered as transient, otherwise . /// - protected internal abstract bool ShouldRetryOn(Exception? exception); + protected internal abstract bool ShouldRetryOn(Exception exception); /// /// Recursively gets InnerException from as long as it is an @@ -408,9 +428,10 @@ protected internal virtual bool ShouldVerifySuccessOn(Exception? exception) /// The result from . /// public static TResult CallOnWrappedException( - Exception? exception, - Func exceptionHandler) + Exception exception, + Func exceptionHandler) => exception is DbUpdateException dbUpdateException + && dbUpdateException.InnerException != null ? CallOnWrappedException(dbUpdateException.InnerException, exceptionHandler) : exceptionHandler(exception); } diff --git a/src/EFCore/Storage/IDatabaseFacadeDependencies.cs b/src/EFCore/Storage/IDatabaseFacadeDependencies.cs index 40f62dd4d45..b13076cb80f 100644 --- a/src/EFCore/Storage/IDatabaseFacadeDependencies.cs +++ b/src/EFCore/Storage/IDatabaseFacadeDependencies.cs @@ -35,6 +35,11 @@ public interface IDatabaseFacadeDependencies /// IDatabaseCreator DatabaseCreator { get; } + /// + /// The execution strategy. + /// + IExecutionStrategy ExecutionStrategy { get; } + /// /// The execution strategy factory. /// diff --git a/src/EFCore/Storage/IExecutionStrategy.cs b/src/EFCore/Storage/IExecutionStrategy.cs index f52147313d8..3335f355035 100644 --- a/src/EFCore/Storage/IExecutionStrategy.cs +++ b/src/EFCore/Storage/IExecutionStrategy.cs @@ -4,11 +4,20 @@ using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; namespace Microsoft.EntityFrameworkCore.Storage { /// - /// A strategy that is used to execute a command or query against the database, possibly with logic to retry when a failure occurs. + /// + /// A strategy that is used to execute a command or query against the database, possibly with logic to retry when a failure occurs. + /// + /// + /// The service lifetime is . This means that each + /// instance will use its own instance of this service. + /// The implementation may depend on other services registered with any lifetime. + /// The implementation does not need to be thread-safe. + /// /// public interface IExecutionStrategy { diff --git a/src/EFCore/Storage/IExecutionStrategyFactory.cs b/src/EFCore/Storage/IExecutionStrategyFactory.cs index b33f6e67ed6..f08f5a7d2c8 100644 --- a/src/EFCore/Storage/IExecutionStrategyFactory.cs +++ b/src/EFCore/Storage/IExecutionStrategyFactory.cs @@ -19,9 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Storage public interface IExecutionStrategyFactory { /// - /// Creates a new . + /// Creates a new . /// - /// An instance of . + /// An instance of . IExecutionStrategy Create(); } } diff --git a/src/EFCore/Storage/Internal/DatabaseFacadeDependencies.cs b/src/EFCore/Storage/Internal/DatabaseFacadeDependencies.cs index 40dc5c5dd20..6c00d21962c 100644 --- a/src/EFCore/Storage/Internal/DatabaseFacadeDependencies.cs +++ b/src/EFCore/Storage/Internal/DatabaseFacadeDependencies.cs @@ -34,6 +34,7 @@ public record DatabaseFacadeDependencies : IDatabaseFacadeDependencies public DatabaseFacadeDependencies( IDbContextTransactionManager transactionManager, IDatabaseCreator databaseCreator, + IExecutionStrategy executionStrategy, IExecutionStrategyFactory executionStrategyFactory, IEnumerable databaseProviders, IDiagnosticsLogger commandLogger, @@ -42,6 +43,7 @@ public DatabaseFacadeDependencies( { TransactionManager = transactionManager; DatabaseCreator = databaseCreator; + ExecutionStrategy = executionStrategy; ExecutionStrategyFactory = executionStrategyFactory; DatabaseProviders = databaseProviders; CommandLogger = commandLogger; @@ -65,6 +67,14 @@ public DatabaseFacadeDependencies( /// public virtual IDatabaseCreator DatabaseCreator { get; init; } + /// + /// 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 IExecutionStrategy ExecutionStrategy { get; init; } + /// /// 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/Storage/Internal/ExecutionStrategyFactory.cs b/src/EFCore/Storage/Internal/ExecutionStrategyFactory.cs index 0d4c78b959d..9d2691f3905 100644 --- a/src/EFCore/Storage/Internal/ExecutionStrategyFactory.cs +++ b/src/EFCore/Storage/Internal/ExecutionStrategyFactory.cs @@ -22,6 +22,8 @@ namespace Microsoft.EntityFrameworkCore.Storage.Internal /// public class ExecutionStrategyFactory : IExecutionStrategyFactory { + private readonly NonRetryingExecutionStrategy _instance; + /// /// Creates a new instance of this class with the given service dependencies. /// @@ -31,6 +33,7 @@ public ExecutionStrategyFactory(ExecutionStrategyDependencies dependencies) Check.NotNull(dependencies, nameof(dependencies)); Dependencies = dependencies; + _instance = new NonRetryingExecutionStrategy(Dependencies); } /// @@ -39,10 +42,9 @@ public ExecutionStrategyFactory(ExecutionStrategyDependencies dependencies) protected virtual ExecutionStrategyDependencies Dependencies { get; } /// - /// Creates a new . + /// Creates a new . /// - /// An instance of . - public virtual IExecutionStrategy Create() - => new NonRetryingExecutionStrategy(Dependencies); + /// An instance of . + public virtual IExecutionStrategy Create() => _instance; } } diff --git a/test/EFCore.SqlServer.FunctionalTests/SqlServerDatabaseCreatorTest.cs b/test/EFCore.SqlServer.FunctionalTests/SqlServerDatabaseCreatorTest.cs index 24a6b2b5022..9330c762f41 100644 --- a/test/EFCore.SqlServer.FunctionalTests/SqlServerDatabaseCreatorTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/SqlServerDatabaseCreatorTest.cs @@ -815,7 +815,9 @@ public Task HasTablesAsyncBase(CancellationToken cancellationToken = defau } public IExecutionStrategyFactory ExecutionStrategyFactory +#pragma warning disable CS0618 // Type or member is obsolete => Dependencies.ExecutionStrategyFactory; +#pragma warning restore CS0618 // Type or member is obsolete } } } diff --git a/test/EFCore.Tests/Storage/ExecutionStrategyTest.cs b/test/EFCore.Tests/Storage/ExecutionStrategyTest.cs index ad6da4fccda..e53418bd2c5 100644 --- a/test/EFCore.Tests/Storage/ExecutionStrategyTest.cs +++ b/test/EFCore.Tests/Storage/ExecutionStrategyTest.cs @@ -738,6 +738,31 @@ private async Task ExecuteAsync_retries_until_limit_is_reached( Assert.Equal(3, executionCount); } + [ConditionalFact] + public void ShouldRetryOn_does_not_get_null_on_DbUpdateConcurrencyException() + { + var executionStrategyMock = new TestExecutionStrategy( + Context, + shouldRetryOn: e => + { + Assert.IsType(e); + return true; + }, + getNextDelay: e => TimeSpan.FromTicks(0)); + + var executionCount = 0; + + executionStrategyMock.Execute(() => + { + if (executionCount++ < 1) + { + throw new DbUpdateConcurrencyException(""); + } + }); + + Assert.Equal(2, executionCount); + } + protected DbContext CreateContext() => InMemoryTestHelpers.Instance.CreateContext( InMemoryTestHelpers.Instance.CreateServiceProvider( @@ -764,6 +789,14 @@ public TestExecutionStrategy( _getNextDelay = getNextDelay; } + protected TestExecutionStrategy() + : base( + (ExecutionStrategyDependencies)null, + DefaultMaxRetryCount, + DefaultMaxDelay) + { + } + protected internal override bool ShouldRetryOn(Exception exception) => _shouldRetryOn?.Invoke(exception) == true; @@ -781,7 +814,7 @@ protected internal override bool ShouldRetryOn(Exception exception) public static new bool Suspended { - set => ExecutionStrategy.Suspended = value; + set => ExecutionStrategy.Current = value ? new TestExecutionStrategy() : null; } } } From fddd921044d97c5d34430615115770ee97e52e53 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:51:00 +0000 Subject: [PATCH 024/346] Update dependencies from https://github.com/dotnet/runtime build 20210903.9 (#25869) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9e6315e3cfa..4521d328717 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 - + https://github.com/dotnet/runtime - 693e2f3479e4a17f5f8d91b7c6dc4e11baba5de1 + da89cc752bbedfdbc9d42f2f4b1098f388892709 diff --git a/eng/Versions.props b/eng/Versions.props index dc0edc254bb..1cf221736ce 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 - 6.0.0-rc.2.21453.6 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.9 3.7.0 From c666392d8f3f84f6240d2d3533f96153e29793e6 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 3 Sep 2021 23:10:16 +0000 Subject: [PATCH 025/346] Update dependencies from https://github.com/dotnet/runtime build 20210903.13 (#25873) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4521d328717..191f26420d7 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 - + https://github.com/dotnet/runtime - da89cc752bbedfdbc9d42f2f4b1098f388892709 + ea48ccc279461d29698b91697cafe46398e87178 diff --git a/eng/Versions.props b/eng/Versions.props index 1cf221736ce..4793cfabb94 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 - 6.0.0-rc.2.21453.9 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21453.13 3.7.0 From 9702fc02478c5a1980824b611fad599f6bc2ee93 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Sat, 4 Sep 2021 08:50:33 +0100 Subject: [PATCH 026/346] More links to conceptual docs (#25814) * More links to conceptual docs Part of #17508 * Review updates --- .../Builders/CollectionCollectionBuilder.cs | 3 ++ .../Builders/CollectionCollectionBuilder`.cs | 3 ++ .../Builders/CollectionNavigationBuilder.cs | 3 ++ .../Builders/CollectionNavigationBuilder`.cs | 3 ++ src/EFCore/Metadata/Builders/DataBuilder.cs | 3 ++ src/EFCore/Metadata/Builders/DataBuilder`.cs | 3 ++ .../Metadata/Builders/DiscriminatorBuilder.cs | 3 ++ .../Builders/DiscriminatorBuilder`.cs | 3 ++ .../Metadata/Builders/EntityTypeBuilder.cs | 3 ++ .../Metadata/Builders/EntityTypeBuilder`.cs | 3 ++ .../Builders/IConventionAnnotatableBuilder.cs | 3 ++ .../IConventionDiscriminatorBuilder.cs | 3 ++ .../Builders/IConventionEntityTypeBuilder.cs | 3 ++ .../Builders/IConventionForeignKeyBuilder.cs | 3 ++ .../Builders/IConventionIndexBuilder.cs | 3 ++ .../Builders/IConventionKeyBuilder.cs | 3 ++ .../Builders/IConventionModelBuilder.cs | 3 ++ .../Builders/IConventionNavigationBuilder.cs | 3 ++ .../IConventionOwnedEntityTypeBuilder.cs | 3 ++ .../IConventionPropertyBaseBuilder.cs | 3 ++ .../Builders/IConventionPropertyBuilder.cs | 3 ++ .../IConventionServicePropertyBuilder.cs | 3 ++ .../IConventionSkipNavigationBuilder.cs | 3 ++ src/EFCore/Metadata/Builders/IndexBuilder.cs | 3 ++ src/EFCore/Metadata/Builders/IndexBuilder`.cs | 3 ++ .../InvertibleRelationshipBuilderBase.cs | 3 ++ src/EFCore/Metadata/Builders/KeyBuilder.cs | 3 ++ src/EFCore/Metadata/Builders/KeyBuilder`.cs | 3 ++ .../Metadata/Builders/NavigationBuilder.cs | 3 ++ .../Metadata/Builders/NavigationBuilder`.cs | 3 ++ .../Builders/OwnedEntityTypeBuilder.cs | 3 ++ .../Builders/OwnedEntityTypeBuilder`.cs | 3 ++ .../Builders/OwnedNavigationBuilder.cs | 3 ++ .../Builders/OwnedNavigationBuilder`.cs | 3 ++ .../Metadata/Builders/OwnershipBuilder.cs | 3 ++ .../Metadata/Builders/OwnershipBuilder`.cs | 3 ++ .../PropertiesConfigurationBuilder.cs | 3 ++ .../PropertiesConfigurationBuilder`.cs | 3 ++ .../Metadata/Builders/PropertyBuilder.cs | 3 ++ .../Metadata/Builders/PropertyBuilder`.cs | 3 ++ .../Builders/ReferenceCollectionBuilder.cs | 3 ++ .../Builders/ReferenceCollectionBuilder`.cs | 3 ++ .../Builders/ReferenceNavigationBuilder.cs | 3 ++ .../Builders/ReferenceNavigationBuilder`.cs | 3 ++ .../Builders/ReferenceReferenceBuilder.cs | 3 ++ .../Builders/ReferenceReferenceBuilder`.cs | 3 ++ .../Builders/RelationshipBuilderBase.cs | 3 ++ .../TypeMappingConfigurationBuilder.cs | 3 ++ .../TypeMappingConfigurationBuilder`.cs | 3 ++ src/EFCore/Metadata/ConfigurationSource.cs | 3 ++ .../Metadata/ConfigurationSourceExtensions.cs | 21 ++++++++++ src/EFCore/Metadata/ConstructorBinding.cs | 3 ++ .../Metadata/ContextParameterBinding.cs | 3 ++ .../BackingFieldAttributeConvention.cs | 3 ++ .../Conventions/BackingFieldConvention.cs | 3 ++ .../BaseTypeDiscoveryConvention.cs | 3 ++ .../Conventions/CascadeDeleteConvention.cs | 3 ++ .../ChangeTrackingStrategyConvention.cs | 3 ++ .../ConcurrencyCheckAttributeConvention.cs | 3 ++ .../ConstructorBindingConvention.cs | 3 ++ .../Metadata/Conventions/ConventionSet.cs | 3 ++ .../DatabaseGeneratedAttributeConvention.cs | 3 ++ .../Conventions/DbSetFindingConvention.cs | 3 ++ .../DerivedTypeDiscoveryConvention.cs | 3 ++ .../Conventions/DiscriminatorConvention.cs | 3 ++ .../EntityTypeAttributeConventionBase.cs | 3 ++ ...figurationEntityTypeAttributeConvention.cs | 3 ++ .../ForeignKeyAttributeConvention.cs | 3 ++ .../Conventions/ForeignKeyIndexConvention.cs | 3 ++ .../ForeignKeyPropertyDiscoveryConvention.cs | 3 ++ .../Metadata/Conventions/IConvention.cs | 3 ++ .../Metadata/Conventions/IConventionBatch.cs | 3 ++ .../Conventions/IConventionContext.cs | 3 ++ .../Conventions/IConventionContext`.cs | 3 ++ .../Conventions/IEntityTypeAddedConvention.cs | 3 ++ .../IEntityTypeAnnotationChangedConvention.cs | 3 ++ .../IEntityTypeBaseTypeChangedConvention.cs | 3 ++ .../IEntityTypeIgnoredConvention.cs | 3 ++ .../IEntityTypeMemberIgnoredConvention.cs | 3 ++ .../IEntityTypePrimaryKeyChangedConvention.cs | 3 ++ .../IEntityTypeRemovedConvention.cs | 3 ++ .../Conventions/IForeignKeyAddedConvention.cs | 3 ++ .../IForeignKeyAnnotationChangedConvention.cs | 3 ++ ...yDependentRequirednessChangedConvention.cs | 3 ++ .../IForeignKeyNullNavigationSetConvention.cs | 3 ++ .../IForeignKeyOwnershipChangedConvention.cs | 3 ++ ...ForeignKeyPrincipalEndChangedConvention.cs | 3 ++ .../IForeignKeyPropertiesChangedConvention.cs | 3 ++ .../IForeignKeyRemovedConvention.cs | 3 ++ ...ForeignKeyRequirednessChangedConvention.cs | 3 ++ .../IForeignKeyUniquenessChangedConvention.cs | 3 ++ .../Conventions/IIndexAddedConvention.cs | 3 ++ .../IIndexAnnotationChangedConvention.cs | 3 ++ .../Conventions/IIndexRemovedConvention.cs | 3 ++ .../IIndexUniquenessChangedConvention.cs | 3 ++ .../Conventions/IKeyAddedConvention.cs | 3 ++ .../IKeyAnnotationChangedConvention.cs | 3 ++ .../Conventions/IKeyRemovedConvention.cs | 3 ++ .../IModelAnnotationChangedConvention.cs | 3 ++ .../Conventions/IModelFinalizedConvention.cs | 3 ++ .../Conventions/IModelFinalizingConvention.cs | 3 ++ .../IModelInitializedConvention.cs | 3 ++ .../Conventions/INavigationAddedConvention.cs | 3 ++ .../INavigationAnnotationChangedConvention.cs | 3 ++ .../INavigationRemovedConvention.cs | 3 ++ .../Conventions/IPropertyAddedConvention.cs | 3 ++ .../IPropertyAnnotationChangedConvention.cs | 3 ++ .../IPropertyFieldChangedConvention.cs | 3 ++ .../IPropertyNullabilityChangedConvention.cs | 3 ++ .../Conventions/IPropertyRemovedConvention.cs | 3 ++ .../ISkipNavigationAddedConvention.cs | 3 ++ ...ipNavigationAnnotationChangedConvention.cs | 3 ++ ...ipNavigationForeignKeyChangedConvention.cs | 3 ++ ...ISkipNavigationInverseChangedConvention.cs | 3 ++ .../ISkipNavigationRemovedConvention.cs | 3 ++ .../Conventions/IndexAttributeConvention.cs | 3 ++ .../Infrastructure/IConventionSetBuilder.cs | 3 ++ .../Infrastructure/IConventionSetPlugin.cs | 3 ++ .../IProviderConventionSetBuilder.cs | 3 ++ .../ProviderConventionSetBuilder.cs | 3 ++ .../InheritanceDiscoveryConventionBase.cs | 3 ++ .../InversePropertyAttributeConvention.cs | 3 ++ .../Conventions/KeyAttributeConvention.cs | 3 ++ .../Conventions/KeyDiscoveryConvention.cs | 3 ++ .../KeylessEntityTypeAttributeConvention.cs | 3 ++ .../ManyToManyJoinEntityTypeConvention.cs | 3 ++ .../MaxLengthAttributeConvention.cs | 3 ++ .../Conventions/ModelCleanupConvention.cs | 4 +- .../NavigationAttributeConventionBase.cs | 3 ++ ...vigationBackingFieldAttributeConvention.cs | 3 ++ .../NavigationEagerLoadingConvention.cs | 3 ++ .../Conventions/NonNullableConventionBase.cs | 3 ++ .../NonNullableNavigationConvention.cs | 3 ++ .../NonNullableReferencePropertyConvention.cs | 3 ++ .../NotMappedEntityTypeAttributeConvention.cs | 3 ++ .../NotMappedMemberAttributeConvention.cs | 3 ++ .../OwnedEntityTypeAttributeConvention.cs | 3 ++ .../Conventions/OwnedTypesConvention.cs | 3 ++ .../PrecisionAttributeConvention.cs | 3 ++ .../PropertyAttributeConventionBase.cs | 3 ++ .../PropertyDiscoveryConvention.cs | 3 ++ .../QueryFilterRewritingConvention.cs | 3 ++ .../RelationshipDiscoveryConvention.cs | 3 ++ .../RequiredNavigationAttributeConvention.cs | 3 ++ .../RequiredPropertyAttributeConvention.cs | 3 ++ .../Conventions/RuntimeModelConvention.cs | 3 ++ .../ServicePropertyDiscoveryConvention.cs | 3 ++ .../StringLengthAttributeConvention.cs | 3 ++ .../TimestampAttributeConvention.cs | 3 ++ .../Conventions/TypeMappingConvention.cs | 3 ++ .../Conventions/UnicodeAttributeConvention.cs | 3 ++ .../Conventions/ValidatingConvention.cs | 3 ++ .../Conventions/ValueGenerationConvention.cs | 3 ++ ...pendencyInjectionMethodParameterBinding.cs | 3 ++ .../DependencyInjectionParameterBinding.cs | 3 ++ .../Metadata/EntityTypeFullNameComparer.cs | 3 ++ .../Metadata/EntityTypeParameterBinding.cs | 3 ++ src/EFCore/Metadata/FactoryMethodBinding.cs | 3 ++ src/EFCore/Metadata/ForeignKeyComparer.cs | 3 ++ src/EFCore/Metadata/IClrCollectionAccessor.cs | 13 +++++- src/EFCore/Metadata/IClrPropertyGetter.cs | 13 +++++- src/EFCore/Metadata/IClrPropertySetter.cs | 13 +++++- .../Metadata/IConstructorBindingFactory.cs | 3 ++ src/EFCore/Metadata/IConventionAnnotatable.cs | 3 ++ src/EFCore/Metadata/IConventionAnnotation.cs | 3 ++ src/EFCore/Metadata/IConventionEntityType.cs | 3 ++ src/EFCore/Metadata/IConventionForeignKey.cs | 3 ++ src/EFCore/Metadata/IConventionIndex.cs | 3 ++ src/EFCore/Metadata/IConventionKey.cs | 3 ++ src/EFCore/Metadata/IConventionModel.cs | 3 ++ src/EFCore/Metadata/IConventionNavigation.cs | 3 ++ .../Metadata/IConventionNavigationBase.cs | 3 ++ src/EFCore/Metadata/IConventionProperty.cs | 3 ++ .../Metadata/IConventionPropertyBase.cs | 3 ++ .../Metadata/IConventionServiceProperty.cs | 3 ++ .../Metadata/IConventionSkipNavigation.cs | 3 ++ src/EFCore/Metadata/IConventionTypeBase.cs | 3 ++ src/EFCore/Metadata/IDesignTimeModel.cs | 3 ++ src/EFCore/Metadata/IEntityType.cs | 3 ++ src/EFCore/Metadata/IForeignKey.cs | 3 ++ src/EFCore/Metadata/IIndex.cs | 3 ++ src/EFCore/Metadata/IKey.cs | 3 ++ src/EFCore/Metadata/IMetadataReference.cs | 3 ++ src/EFCore/Metadata/IModel.cs | 37 ++++++++++++++++- src/EFCore/Metadata/IMutableAnnotatable.cs | 3 ++ src/EFCore/Metadata/IMutableEntityType.cs | 3 ++ src/EFCore/Metadata/IMutableForeignKey.cs | 3 ++ src/EFCore/Metadata/IMutableIndex.cs | 3 ++ src/EFCore/Metadata/IMutableKey.cs | 3 ++ src/EFCore/Metadata/IMutableModel.cs | 3 ++ src/EFCore/Metadata/IMutableNavigation.cs | 3 ++ src/EFCore/Metadata/IMutableNavigationBase.cs | 3 ++ src/EFCore/Metadata/IMutableProperty.cs | 3 ++ src/EFCore/Metadata/IMutablePropertyBase.cs | 3 ++ .../Metadata/IMutableServiceProperty.cs | 3 ++ src/EFCore/Metadata/IMutableSkipNavigation.cs | 3 ++ src/EFCore/Metadata/IMutableTypeBase.cs | 3 ++ src/EFCore/Metadata/INavigation.cs | 3 ++ src/EFCore/Metadata/INavigationBase.cs | 3 ++ .../Metadata/IParameterBindingFactories.cs | 3 ++ .../Metadata/IParameterBindingFactory.cs | 3 ++ src/EFCore/Metadata/IProperty.cs | 3 ++ src/EFCore/Metadata/IPropertyBase.cs | 3 ++ .../IPropertyParameterBindingFactory.cs | 3 ++ src/EFCore/Metadata/IReadOnlyEntityType.cs | 3 ++ src/EFCore/Metadata/IReadOnlyForeignKey.cs | 3 ++ src/EFCore/Metadata/IReadOnlyIndex.cs | 3 ++ src/EFCore/Metadata/IReadOnlyKey.cs | 3 ++ src/EFCore/Metadata/IReadOnlyModel.cs | 40 +++++++++++++++++++ src/EFCore/Metadata/IReadOnlyNavigation.cs | 3 ++ .../Metadata/IReadOnlyNavigationBase.cs | 3 ++ src/EFCore/Metadata/IReadOnlyProperty.cs | 4 +- src/EFCore/Metadata/IReadOnlyPropertyBase.cs | 3 ++ .../Metadata/IReadOnlyServiceProperty.cs | 3 ++ .../Metadata/IReadOnlySkipNavigation.cs | 3 ++ src/EFCore/Metadata/IReadOnlyTypeBase.cs | 3 ++ src/EFCore/Metadata/IServiceProperty.cs | 3 ++ src/EFCore/Metadata/ISkipNavigation.cs | 3 ++ src/EFCore/Metadata/ITypeBase.cs | 3 ++ .../Metadata/ITypeMappingConfiguration.cs | 3 ++ src/EFCore/Metadata/IndexComparer.cs | 3 ++ src/EFCore/Metadata/InstantiationBinding.cs | 3 ++ src/EFCore/Metadata/KeyComparer.cs | 3 ++ .../LazyLoaderParameterBindingFactory.cs | 3 ++ src/EFCore/Metadata/MemberIdentity.cs | 3 ++ .../Metadata/ObjectArrayParameterBinding.cs | 3 ++ src/EFCore/Metadata/ParameterBinding.cs | 3 ++ src/EFCore/Metadata/ParameterBindingInfo.cs | 3 ++ .../Metadata/PropertyParameterBinding.cs | 3 ++ src/EFCore/Metadata/PropertySaveBehavior.cs | 4 ++ src/EFCore/Metadata/RuntimeEntityType.cs | 3 ++ src/EFCore/Metadata/RuntimeForeignKey.cs | 3 ++ src/EFCore/Metadata/RuntimeIndex.cs | 3 ++ src/EFCore/Metadata/RuntimeKey.cs | 3 ++ src/EFCore/Metadata/RuntimeModel.cs | 3 ++ src/EFCore/Metadata/RuntimeNavigation.cs | 3 ++ src/EFCore/Metadata/RuntimeProperty.cs | 3 ++ src/EFCore/Metadata/RuntimePropertyBase.cs | 3 ++ src/EFCore/Metadata/RuntimeServiceProperty.cs | 3 ++ src/EFCore/Metadata/RuntimeSkipNavigation.cs | 3 ++ .../RuntimeTypeMappingConfiguration.cs | 3 ++ .../Metadata/ServiceParameterBinding.cs | 3 ++ .../ServiceParameterBindingFactory.cs | 3 ++ src/EFCore/Metadata/SimpleModelFactory.cs | 3 ++ src/EFCore/Metadata/ValueGenerated.cs | 4 ++ .../Query/CollectionShaperExpression.cs | 4 ++ .../Query/CompiledQueryCacheKeyGenerator.cs | 4 ++ src/EFCore/Query/EntityShaperExpression.cs | 4 ++ .../Query/EvaluatableExpressionFilter.cs | 4 ++ .../Query/ExpressionEqualityComparer.cs | 4 ++ src/EFCore/Query/ExpressionPrinter.cs | 4 ++ src/EFCore/Query/GroupByShaperExpression.cs | 4 ++ src/EFCore/Query/IAsyncQueryProvider.cs | 4 ++ .../Query/ICompiledQueryCacheKeyGenerator.cs | 4 ++ src/EFCore/Query/IEntityMaterializerSource.cs | 4 ++ .../Query/IEvaluatableExpressionFilter.cs | 4 ++ .../IEvaluatableExpressionFilterPlugin.cs | 4 ++ src/EFCore/Query/IIncludableQueryable.cs | 4 ++ ...INavigationExpansionExtensibilityHelper.cs | 4 ++ src/EFCore/Query/IPrintableExpression.cs | 4 ++ .../Query/IQueryCompilationContextFactory.cs | 4 ++ src/EFCore/Query/IQueryContextFactory.cs | 4 ++ .../IQueryTranslationPostprocessorFactory.cs | 4 ++ .../IQueryTranslationPreprocessorFactory.cs | 4 ++ ...thodTranslatingExpressionVisitorFactory.cs | 4 ++ src/EFCore/Query/IQueryingEnumerable.cs | 4 ++ ...dQueryCompilingExpressionVisitorFactory.cs | 4 ++ src/EFCore/Query/IncludeExpression.cs | 4 ++ ...terializeCollectionNavigationExpression.cs | 4 ++ .../Query/ProjectionBindingExpression.cs | 4 ++ src/EFCore/Query/ProjectionMember.cs | 4 ++ src/EFCore/Query/QueryCompilationContext.cs | 4 ++ src/EFCore/Query/QueryContext.cs | 4 ++ src/EFCore/Query/QueryRootExpression.cs | 4 ++ .../Query/QueryTranslationPostprocessor.cs | 4 ++ .../Query/QueryTranslationPreprocessor.cs | 4 ++ ...yableMethodTranslatingExpressionVisitor.cs | 4 ++ src/EFCore/Query/QueryableMethods.cs | 4 ++ .../Query/ReplacingExpressionVisitor.cs | 4 ++ src/EFCore/Query/ResultCardinality.cs | 4 ++ .../ShapedQueryCompilingExpressionVisitor.cs | 4 ++ src/EFCore/Query/ShapedQueryExpression.cs | 4 ++ .../Query/TransparentIdentifierFactory.cs | 4 ++ 283 files changed, 1001 insertions(+), 9 deletions(-) diff --git a/src/EFCore/Metadata/Builders/CollectionCollectionBuilder.cs b/src/EFCore/Metadata/Builders/CollectionCollectionBuilder.cs index d189b43f736..1b17265d879 100644 --- a/src/EFCore/Metadata/Builders/CollectionCollectionBuilder.cs +++ b/src/EFCore/Metadata/Builders/CollectionCollectionBuilder.cs @@ -18,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class CollectionCollectionBuilder { /// diff --git a/src/EFCore/Metadata/Builders/CollectionCollectionBuilder`.cs b/src/EFCore/Metadata/Builders/CollectionCollectionBuilder`.cs index a7402ebc9dd..a5722f13bca 100644 --- a/src/EFCore/Metadata/Builders/CollectionCollectionBuilder`.cs +++ b/src/EFCore/Metadata/Builders/CollectionCollectionBuilder`.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// /// One of the entity types in this relationship. /// One of the entity types in this relationship. public class CollectionCollectionBuilder : CollectionCollectionBuilder diff --git a/src/EFCore/Metadata/Builders/CollectionNavigationBuilder.cs b/src/EFCore/Metadata/Builders/CollectionNavigationBuilder.cs index bb2c941f7f2..010ba35341d 100644 --- a/src/EFCore/Metadata/Builders/CollectionNavigationBuilder.cs +++ b/src/EFCore/Metadata/Builders/CollectionNavigationBuilder.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class CollectionNavigationBuilder : IInfrastructure { /// diff --git a/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs b/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs index 7476a59b672..5e473fb4ab5 100644 --- a/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs +++ b/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type to be configured. /// The entity type that this relationship targets. public class CollectionNavigationBuilder : CollectionNavigationBuilder diff --git a/src/EFCore/Metadata/Builders/DataBuilder.cs b/src/EFCore/Metadata/Builders/DataBuilder.cs index b050548a7ed..43708cc1818 100644 --- a/src/EFCore/Metadata/Builders/DataBuilder.cs +++ b/src/EFCore/Metadata/Builders/DataBuilder.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Allows further configuration of model data. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class DataBuilder { /// diff --git a/src/EFCore/Metadata/Builders/DataBuilder`.cs b/src/EFCore/Metadata/Builders/DataBuilder`.cs index bc6212cbfef..cff124611e2 100644 --- a/src/EFCore/Metadata/Builders/DataBuilder`.cs +++ b/src/EFCore/Metadata/Builders/DataBuilder`.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Allows further configuration of model data. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type of the data. public class DataBuilder : DataBuilder { diff --git a/src/EFCore/Metadata/Builders/DiscriminatorBuilder.cs b/src/EFCore/Metadata/Builders/DiscriminatorBuilder.cs index 018bb56b29d..b8d0c5f86a0 100644 --- a/src/EFCore/Metadata/Builders/DiscriminatorBuilder.cs +++ b/src/EFCore/Metadata/Builders/DiscriminatorBuilder.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API surface for setting discriminator values. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class DiscriminatorBuilder : IConventionDiscriminatorBuilder { /// diff --git a/src/EFCore/Metadata/Builders/DiscriminatorBuilder`.cs b/src/EFCore/Metadata/Builders/DiscriminatorBuilder`.cs index 7f52f1223f1..20cf66d7969 100644 --- a/src/EFCore/Metadata/Builders/DiscriminatorBuilder`.cs +++ b/src/EFCore/Metadata/Builders/DiscriminatorBuilder`.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API surface for setting discriminator values. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the discriminator property. public class DiscriminatorBuilder { diff --git a/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs b/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs index 6457543d2ad..29f8ab4f781 100644 --- a/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs @@ -24,6 +24,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class EntityTypeBuilder : IInfrastructure { /// diff --git a/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs b/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs index 26f86e83e67..0f056311c81 100644 --- a/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs +++ b/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. public class EntityTypeBuilder : EntityTypeBuilder where TEntity : class diff --git a/src/EFCore/Metadata/Builders/IConventionAnnotatableBuilder.cs b/src/EFCore/Metadata/Builders/IConventionAnnotatableBuilder.cs index 572d03a625f..ebbc8ec4025 100644 --- a/src/EFCore/Metadata/Builders/IConventionAnnotatableBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionAnnotatableBuilder.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionAnnotatableBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionDiscriminatorBuilder.cs b/src/EFCore/Metadata/Builders/IConventionDiscriminatorBuilder.cs index b01b8c9cbbc..a67ab7f629c 100644 --- a/src/EFCore/Metadata/Builders/IConventionDiscriminatorBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionDiscriminatorBuilder.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API surface for setting discriminator values from conventions. /// + /// + /// See Model building conventions for more information. + /// public interface IConventionDiscriminatorBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionEntityTypeBuilder.cs b/src/EFCore/Metadata/Builders/IConventionEntityTypeBuilder.cs index 689e38cf735..efdc5626555 100644 --- a/src/EFCore/Metadata/Builders/IConventionEntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionEntityTypeBuilder.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionEntityTypeBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionForeignKeyBuilder.cs b/src/EFCore/Metadata/Builders/IConventionForeignKeyBuilder.cs index 835a1848c9a..d688b64806b 100644 --- a/src/EFCore/Metadata/Builders/IConventionForeignKeyBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionForeignKeyBuilder.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionForeignKeyBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionIndexBuilder.cs b/src/EFCore/Metadata/Builders/IConventionIndexBuilder.cs index 356b735f412..c249cdfd7f6 100644 --- a/src/EFCore/Metadata/Builders/IConventionIndexBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionIndexBuilder.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionIndexBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionKeyBuilder.cs b/src/EFCore/Metadata/Builders/IConventionKeyBuilder.cs index ae53c60a532..52af4e020a5 100644 --- a/src/EFCore/Metadata/Builders/IConventionKeyBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionKeyBuilder.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionKeyBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionModelBuilder.cs b/src/EFCore/Metadata/Builders/IConventionModelBuilder.cs index 7c17d27f21f..10eac32624b 100644 --- a/src/EFCore/Metadata/Builders/IConventionModelBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionModelBuilder.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionModelBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionNavigationBuilder.cs b/src/EFCore/Metadata/Builders/IConventionNavigationBuilder.cs index 7a1c0315883..b8a12e7cc9c 100644 --- a/src/EFCore/Metadata/Builders/IConventionNavigationBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionNavigationBuilder.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionNavigationBuilder : IConventionPropertyBaseBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionOwnedEntityTypeBuilder.cs b/src/EFCore/Metadata/Builders/IConventionOwnedEntityTypeBuilder.cs index 8667656c280..206437ceca9 100644 --- a/src/EFCore/Metadata/Builders/IConventionOwnedEntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionOwnedEntityTypeBuilder.cs @@ -7,6 +7,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// This interface is typically used by database providers (and other extensions). It is generally /// not used in application code. /// + /// + /// See Model building conventions for more information. + /// public interface IConventionOwnedEntityTypeBuilder { } diff --git a/src/EFCore/Metadata/Builders/IConventionPropertyBaseBuilder.cs b/src/EFCore/Metadata/Builders/IConventionPropertyBaseBuilder.cs index cadca2111c4..71aa0c479c1 100644 --- a/src/EFCore/Metadata/Builders/IConventionPropertyBaseBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionPropertyBaseBuilder.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionPropertyBaseBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionPropertyBuilder.cs b/src/EFCore/Metadata/Builders/IConventionPropertyBuilder.cs index 93a88b57798..3660049dcbb 100644 --- a/src/EFCore/Metadata/Builders/IConventionPropertyBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionPropertyBuilder.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionPropertyBuilder : IConventionPropertyBaseBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionServicePropertyBuilder.cs b/src/EFCore/Metadata/Builders/IConventionServicePropertyBuilder.cs index b8401640d13..7ac39f8cf58 100644 --- a/src/EFCore/Metadata/Builders/IConventionServicePropertyBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionServicePropertyBuilder.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionServicePropertyBuilder : IConventionPropertyBaseBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IConventionSkipNavigationBuilder.cs b/src/EFCore/Metadata/Builders/IConventionSkipNavigationBuilder.cs index 88108581579..554002b0580 100644 --- a/src/EFCore/Metadata/Builders/IConventionSkipNavigationBuilder.cs +++ b/src/EFCore/Metadata/Builders/IConventionSkipNavigationBuilder.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionSkipNavigationBuilder : IConventionPropertyBaseBuilder { /// diff --git a/src/EFCore/Metadata/Builders/IndexBuilder.cs b/src/EFCore/Metadata/Builders/IndexBuilder.cs index 033b4b039d7..0a13fca51d2 100644 --- a/src/EFCore/Metadata/Builders/IndexBuilder.cs +++ b/src/EFCore/Metadata/Builders/IndexBuilder.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class IndexBuilder : IInfrastructure { /// diff --git a/src/EFCore/Metadata/Builders/IndexBuilder`.cs b/src/EFCore/Metadata/Builders/IndexBuilder`.cs index 7dc136bc6c1..09593563095 100644 --- a/src/EFCore/Metadata/Builders/IndexBuilder`.cs +++ b/src/EFCore/Metadata/Builders/IndexBuilder`.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// // ReSharper disable once UnusedTypeParameter public class IndexBuilder : IndexBuilder { diff --git a/src/EFCore/Metadata/Builders/InvertibleRelationshipBuilderBase.cs b/src/EFCore/Metadata/Builders/InvertibleRelationshipBuilderBase.cs index 5cbbb72a213..e3e1f97d9a0 100644 --- a/src/EFCore/Metadata/Builders/InvertibleRelationshipBuilderBase.cs +++ b/src/EFCore/Metadata/Builders/InvertibleRelationshipBuilderBase.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Base class used for configuring an invertible relationship. /// + /// + /// See Modeling entity types and relationships for more information. + /// public abstract class InvertibleRelationshipBuilderBase : IInfrastructure { private readonly IReadOnlyList? _foreignKeyProperties; diff --git a/src/EFCore/Metadata/Builders/KeyBuilder.cs b/src/EFCore/Metadata/Builders/KeyBuilder.cs index 966cc3cd07d..2da187ff3ce 100644 --- a/src/EFCore/Metadata/Builders/KeyBuilder.cs +++ b/src/EFCore/Metadata/Builders/KeyBuilder.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class KeyBuilder : IInfrastructure { /// diff --git a/src/EFCore/Metadata/Builders/KeyBuilder`.cs b/src/EFCore/Metadata/Builders/KeyBuilder`.cs index 6cb8fcfa794..bb2f78f7dff 100644 --- a/src/EFCore/Metadata/Builders/KeyBuilder`.cs +++ b/src/EFCore/Metadata/Builders/KeyBuilder`.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// // ReSharper disable once UnusedTypeParameter public class KeyBuilder : KeyBuilder { diff --git a/src/EFCore/Metadata/Builders/NavigationBuilder.cs b/src/EFCore/Metadata/Builders/NavigationBuilder.cs index 5bb96d3fc4f..689a434d97d 100644 --- a/src/EFCore/Metadata/Builders/NavigationBuilder.cs +++ b/src/EFCore/Metadata/Builders/NavigationBuilder.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class NavigationBuilder : IInfrastructure, IInfrastructure { /// diff --git a/src/EFCore/Metadata/Builders/NavigationBuilder`.cs b/src/EFCore/Metadata/Builders/NavigationBuilder`.cs index 3e9978bf6fc..9d0887eb272 100644 --- a/src/EFCore/Metadata/Builders/NavigationBuilder`.cs +++ b/src/EFCore/Metadata/Builders/NavigationBuilder`.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class NavigationBuilder : NavigationBuilder where TSource : class where TTarget : class diff --git a/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder.cs b/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder.cs index d640dc46e6a..7c502b35197 100644 --- a/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class OwnedEntityTypeBuilder { /// diff --git a/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder`.cs b/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder`.cs index bdcd842ec63..8dc3a7ef4e0 100644 --- a/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder`.cs +++ b/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder`.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. // ReSharper disable once UnusedTypeParameter public class OwnedEntityTypeBuilder : OwnedEntityTypeBuilder diff --git a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs index 6daa66d19d7..3f1cdfb29f9 100644 --- a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs +++ b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a navigation to an owned entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class OwnedNavigationBuilder : IInfrastructure { private InternalForeignKeyBuilder _builder; diff --git a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder`.cs b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder`.cs index a3a3ba08a3d..d0e85663f03 100644 --- a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder`.cs +++ b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder`.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a navigation to an owned entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class OwnedNavigationBuilder : OwnedNavigationBuilder where TOwnerEntity : class where TDependentEntity : class diff --git a/src/EFCore/Metadata/Builders/OwnershipBuilder.cs b/src/EFCore/Metadata/Builders/OwnershipBuilder.cs index ddb80b0f3f1..ccc3fe9a4b7 100644 --- a/src/EFCore/Metadata/Builders/OwnershipBuilder.cs +++ b/src/EFCore/Metadata/Builders/OwnershipBuilder.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// Provides a simple API for configuring an ownership. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class OwnershipBuilder : RelationshipBuilderBase { /// diff --git a/src/EFCore/Metadata/Builders/OwnershipBuilder`.cs b/src/EFCore/Metadata/Builders/OwnershipBuilder`.cs index 474c8ab2f16..621c8bc81df 100644 --- a/src/EFCore/Metadata/Builders/OwnershipBuilder`.cs +++ b/src/EFCore/Metadata/Builders/OwnershipBuilder`.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// Provides a simple API for configuring an ownership. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class OwnershipBuilder : OwnershipBuilder where TEntity : class where TDependentEntity : class diff --git a/src/EFCore/Metadata/Builders/PropertiesConfigurationBuilder.cs b/src/EFCore/Metadata/Builders/PropertiesConfigurationBuilder.cs index b3cec74ad6a..110da3bb3c8 100644 --- a/src/EFCore/Metadata/Builders/PropertiesConfigurationBuilder.cs +++ b/src/EFCore/Metadata/Builders/PropertiesConfigurationBuilder.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class PropertiesConfigurationBuilder { /// diff --git a/src/EFCore/Metadata/Builders/PropertiesConfigurationBuilder`.cs b/src/EFCore/Metadata/Builders/PropertiesConfigurationBuilder`.cs index 833f6fec42f..bec4f16072f 100644 --- a/src/EFCore/Metadata/Builders/PropertiesConfigurationBuilder`.cs +++ b/src/EFCore/Metadata/Builders/PropertiesConfigurationBuilder`.cs @@ -18,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class PropertiesConfigurationBuilder : PropertiesConfigurationBuilder { /// diff --git a/src/EFCore/Metadata/Builders/PropertyBuilder.cs b/src/EFCore/Metadata/Builders/PropertyBuilder.cs index 8bf7b34e6a7..bc75ac2f60f 100644 --- a/src/EFCore/Metadata/Builders/PropertyBuilder.cs +++ b/src/EFCore/Metadata/Builders/PropertyBuilder.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class PropertyBuilder : IInfrastructure { /// diff --git a/src/EFCore/Metadata/Builders/PropertyBuilder`.cs b/src/EFCore/Metadata/Builders/PropertyBuilder`.cs index fd637533253..638b513f9ff 100644 --- a/src/EFCore/Metadata/Builders/PropertyBuilder`.cs +++ b/src/EFCore/Metadata/Builders/PropertyBuilder`.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class PropertyBuilder : PropertyBuilder { /// diff --git a/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder.cs b/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder.cs index e3ad98f34e3..b4919d4b093 100644 --- a/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder.cs +++ b/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class ReferenceCollectionBuilder : RelationshipBuilderBase { /// diff --git a/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder`.cs b/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder`.cs index ba37ae3142a..051b304fae5 100644 --- a/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder`.cs +++ b/src/EFCore/Metadata/Builders/ReferenceCollectionBuilder`.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The principal entity type in this relationship. /// The dependent entity type in this relationship. public class ReferenceCollectionBuilder : ReferenceCollectionBuilder diff --git a/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder.cs b/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder.cs index b2f18afd530..f8a74669d6f 100644 --- a/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder.cs +++ b/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder.cs @@ -23,6 +23,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class ReferenceNavigationBuilder : IInfrastructure { /// diff --git a/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder`.cs b/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder`.cs index 92c567eeb17..8359c354507 100644 --- a/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder`.cs +++ b/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder`.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type to be configured. /// The entity type that this relationship targets. public class ReferenceNavigationBuilder : ReferenceNavigationBuilder diff --git a/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder.cs b/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder.cs index 3563da810ec..362e85d8f6d 100644 --- a/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder.cs +++ b/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder.cs @@ -18,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// Provides a simple API for configuring a one-to-one relationship. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class ReferenceReferenceBuilder : InvertibleRelationshipBuilderBase { /// diff --git a/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder`.cs b/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder`.cs index 0a0e72e12a2..8df2fc05228 100644 --- a/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder`.cs +++ b/src/EFCore/Metadata/Builders/ReferenceReferenceBuilder`.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// Provides a simple API for configuring a one-to-one relationship. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class ReferenceReferenceBuilder : ReferenceReferenceBuilder where TEntity : class where TRelatedEntity : class diff --git a/src/EFCore/Metadata/Builders/RelationshipBuilderBase.cs b/src/EFCore/Metadata/Builders/RelationshipBuilderBase.cs index 3e21485b18c..0275a5ea432 100644 --- a/src/EFCore/Metadata/Builders/RelationshipBuilderBase.cs +++ b/src/EFCore/Metadata/Builders/RelationshipBuilderBase.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Base class used for configuring a relationship. /// + /// + /// See Modeling entity types and relationships for more information. + /// public abstract class RelationshipBuilderBase : IInfrastructure { private readonly IReadOnlyList? _foreignKeyProperties; diff --git a/src/EFCore/Metadata/Builders/TypeMappingConfigurationBuilder.cs b/src/EFCore/Metadata/Builders/TypeMappingConfigurationBuilder.cs index 0c427c8e2e2..caa9c4d6a33 100644 --- a/src/EFCore/Metadata/Builders/TypeMappingConfigurationBuilder.cs +++ b/src/EFCore/Metadata/Builders/TypeMappingConfigurationBuilder.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class TypeMappingConfigurationBuilder { /// diff --git a/src/EFCore/Metadata/Builders/TypeMappingConfigurationBuilder`.cs b/src/EFCore/Metadata/Builders/TypeMappingConfigurationBuilder`.cs index f4cae9d9d37..af43c7f5460 100644 --- a/src/EFCore/Metadata/Builders/TypeMappingConfigurationBuilder`.cs +++ b/src/EFCore/Metadata/Builders/TypeMappingConfigurationBuilder`.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class TypeMappingConfigurationBuilder : TypeMappingConfigurationBuilder { /// diff --git a/src/EFCore/Metadata/ConfigurationSource.cs b/src/EFCore/Metadata/ConfigurationSource.cs index cb308e37cf5..49a31efc8d6 100644 --- a/src/EFCore/Metadata/ConfigurationSource.cs +++ b/src/EFCore/Metadata/ConfigurationSource.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public enum ConfigurationSource { /// diff --git a/src/EFCore/Metadata/ConfigurationSourceExtensions.cs b/src/EFCore/Metadata/ConfigurationSourceExtensions.cs index 7d406746674..c636ad24145 100644 --- a/src/EFCore/Metadata/ConfigurationSourceExtensions.cs +++ b/src/EFCore/Metadata/ConfigurationSourceExtensions.cs @@ -8,11 +8,17 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Provides extension methods for /// + /// + /// See Model building conventions for more information. + /// public static class ConfigurationSourceExtensions { /// /// Returns a value indicating whether the new configuration source can override configuration set with the old configuration source. /// + /// + /// See Model building conventions for more information. + /// /// The new configuration source. /// The old configuration source. /// if the new configuration source can override configuration set with the old configuration source. @@ -45,6 +51,9 @@ public static bool Overrides(this ConfigurationSource newConfigurationSource, Co /// /// Returns a value indicating whether the new configuration source can override configuration set with the old configuration source. /// + /// + /// See Model building conventions for more information. + /// /// The new configuration source. /// The old configuration source. /// if the new configuration source can override configuration set with the old configuration source. @@ -54,6 +63,9 @@ public static bool Overrides(this ConfigurationSource? newConfigurationSource, C /// /// Returns a value indicating whether the configuration source always takes precedence over the other configuration source. /// + /// + /// See Model building conventions for more information. + /// /// The new configuration source. /// The old configuration source. /// if the configuration source always takes precedence over the other configuration source. @@ -63,6 +75,9 @@ public static bool OverridesStrictly(this ConfigurationSource newConfigurationSo /// /// Returns a value indicating whether the configuration source always takes precedence over the other configuration source. /// + /// + /// See Model building conventions for more information. + /// /// The new configuration source. /// The old configuration source. /// if the configuration source always takes precedence over the other configuration source. @@ -72,6 +87,9 @@ public static bool OverridesStrictly(this ConfigurationSource? newConfigurationS /// /// Returns the configuration source which has higher priority. /// + /// + /// See Model building conventions for more information. + /// /// The left configuration source. /// The right configuration source. /// The configuration source with higher priority. @@ -84,6 +102,9 @@ public static bool OverridesStrictly(this ConfigurationSource? newConfigurationS /// /// Returns the configuration source which has higher priority. /// + /// + /// See Model building conventions for more information. + /// /// The left configuration source. /// The right configuration source. /// The configuration source with higher priority. diff --git a/src/EFCore/Metadata/ConstructorBinding.cs b/src/EFCore/Metadata/ConstructorBinding.cs index ff934f1dffe..cfcdc05f4a2 100644 --- a/src/EFCore/Metadata/ConstructorBinding.cs +++ b/src/EFCore/Metadata/ConstructorBinding.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Defines the binding of parameters to a CLR for an entity type. /// + /// + /// See Entity types with constructors for more information. + /// public class ConstructorBinding : InstantiationBinding { /// diff --git a/src/EFCore/Metadata/ContextParameterBinding.cs b/src/EFCore/Metadata/ContextParameterBinding.cs index 910b7acca5d..d7dcf82e9ab 100644 --- a/src/EFCore/Metadata/ContextParameterBinding.cs +++ b/src/EFCore/Metadata/ContextParameterBinding.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Describes the binding of a , which may or may not also have and associated /// , to a parameter in a constructor, factory method, or similar. /// + /// + /// See Entity types with constructors for more information. + /// public class ContextParameterBinding : ServiceParameterBinding { /// diff --git a/src/EFCore/Metadata/Conventions/BackingFieldAttributeConvention.cs b/src/EFCore/Metadata/Conventions/BackingFieldAttributeConvention.cs index a7c189815b5..e51d2e7ab86 100644 --- a/src/EFCore/Metadata/Conventions/BackingFieldAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/BackingFieldAttributeConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures a property as having a backing field /// based on the attribute. /// + /// + /// See Model building conventions for more information. + /// public class BackingFieldAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs b/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs index fa9f89c4c4f..1ed2c232e30 100644 --- a/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs +++ b/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs @@ -28,6 +28,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// If more than one matching field is found an exception is thrown. /// /// + /// + /// See Model building conventions for more information. + /// public class BackingFieldConvention : IPropertyAddedConvention, INavigationAddedConvention, diff --git a/src/EFCore/Metadata/Conventions/BaseTypeDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/BaseTypeDiscoveryConvention.cs index 7d399273387..fd822cc1900 100644 --- a/src/EFCore/Metadata/Conventions/BaseTypeDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/BaseTypeDiscoveryConvention.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that finds base and derived entity types that are already part of the model based on the associated /// CLR type hierarchy. /// + /// + /// See Model building conventions for more information. + /// public class BaseTypeDiscoveryConvention : #pragma warning disable CS0612 // Type or member is obsolete InheritanceDiscoveryConventionBase, diff --git a/src/EFCore/Metadata/Conventions/CascadeDeleteConvention.cs b/src/EFCore/Metadata/Conventions/CascadeDeleteConvention.cs index a4ac4f39232..c6595eb59c4 100644 --- a/src/EFCore/Metadata/Conventions/CascadeDeleteConvention.cs +++ b/src/EFCore/Metadata/Conventions/CascadeDeleteConvention.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that sets the delete behavior to for required foreign keys /// and for optional ones. /// + /// + /// See Model building conventions for more information. + /// public class CascadeDeleteConvention : IForeignKeyAddedConvention, IForeignKeyRequirednessChangedConvention { /// diff --git a/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs b/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs index 96de4b043c0..368b34699c5 100644 --- a/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs +++ b/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that sets a flag on the model to always skip detecting changes if no entity type is using the /// strategy. /// + /// + /// See Model building conventions for more information. + /// public class ChangeTrackingStrategyConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore/Metadata/Conventions/ConcurrencyCheckAttributeConvention.cs b/src/EFCore/Metadata/Conventions/ConcurrencyCheckAttributeConvention.cs index 1ff81253826..046dde4d312 100644 --- a/src/EFCore/Metadata/Conventions/ConcurrencyCheckAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/ConcurrencyCheckAttributeConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures a property as a concurrency token if it has the . /// + /// + /// See Model building conventions for more information. + /// public class ConcurrencyCheckAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/ConstructorBindingConvention.cs b/src/EFCore/Metadata/Conventions/ConstructorBindingConvention.cs index c5048973788..e35874cc84a 100644 --- a/src/EFCore/Metadata/Conventions/ConstructorBindingConvention.cs +++ b/src/EFCore/Metadata/Conventions/ConstructorBindingConvention.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// * m_[parameter name] /// * m_[pascal-cased parameter name] /// + /// + /// See Model building conventions for more information. + /// public class ConstructorBindingConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore/Metadata/Conventions/ConventionSet.cs b/src/EFCore/Metadata/Conventions/ConventionSet.cs index 62a5aa65fd0..54c2cfde383 100644 --- a/src/EFCore/Metadata/Conventions/ConventionSet.cs +++ b/src/EFCore/Metadata/Conventions/ConventionSet.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents a set of conventions used to build a model. /// + /// + /// See Model building conventions for more information. + /// public class ConventionSet { /// diff --git a/src/EFCore/Metadata/Conventions/DatabaseGeneratedAttributeConvention.cs b/src/EFCore/Metadata/Conventions/DatabaseGeneratedAttributeConvention.cs index 404a2912d1b..f3929530dee 100644 --- a/src/EFCore/Metadata/Conventions/DatabaseGeneratedAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/DatabaseGeneratedAttributeConvention.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// is specified or if /// is specified using a . /// + /// + /// See Model building conventions for more information. + /// public class DatabaseGeneratedAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/DbSetFindingConvention.cs b/src/EFCore/Metadata/Conventions/DbSetFindingConvention.cs index 297a0c8e771..53934cdc359 100644 --- a/src/EFCore/Metadata/Conventions/DbSetFindingConvention.cs +++ b/src/EFCore/Metadata/Conventions/DbSetFindingConvention.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that adds entity types based on the properties defined on the /// derived class. /// + /// + /// See Model building conventions for more information. + /// public class DbSetFindingConvention : IModelInitializedConvention { /// diff --git a/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs index acf2cd538df..d6bfecb30de 100644 --- a/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that finds derived entity types that are already part of the model based on the associated /// CLR type hierarchy. /// + /// + /// See Model building conventions for more information. + /// [Obsolete] public class DerivedTypeDiscoveryConvention : InheritanceDiscoveryConventionBase, IEntityTypeAddedConvention { diff --git a/src/EFCore/Metadata/Conventions/DiscriminatorConvention.cs b/src/EFCore/Metadata/Conventions/DiscriminatorConvention.cs index e03a6a374e4..11559cb870e 100644 --- a/src/EFCore/Metadata/Conventions/DiscriminatorConvention.cs +++ b/src/EFCore/Metadata/Conventions/DiscriminatorConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the discriminator value for entity types in a hierarchy as the entity type name. /// + /// + /// See Model building conventions for more information. + /// public class DiscriminatorConvention : IEntityTypeBaseTypeChangedConvention, IEntityTypeRemovedConvention { /// diff --git a/src/EFCore/Metadata/Conventions/EntityTypeAttributeConventionBase.cs b/src/EFCore/Metadata/Conventions/EntityTypeAttributeConventionBase.cs index 6f485f27513..510cd61822e 100644 --- a/src/EFCore/Metadata/Conventions/EntityTypeAttributeConventionBase.cs +++ b/src/EFCore/Metadata/Conventions/EntityTypeAttributeConventionBase.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A base type for conventions that perform configuration based on an attribute specified on an entity type. /// + /// + /// See Model building conventions for more information. + /// /// The attribute type to look for. public abstract class EntityTypeAttributeConventionBase : IEntityTypeAddedConvention where TAttribute : Attribute diff --git a/src/EFCore/Metadata/Conventions/EntityTypeConfigurationEntityTypeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/EntityTypeConfigurationEntityTypeAttributeConvention.cs index f849ffa8caf..ae59209e8c9 100644 --- a/src/EFCore/Metadata/Conventions/EntityTypeConfigurationEntityTypeAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/EntityTypeConfigurationEntityTypeAttributeConvention.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that applies the entity type configuration specified in . /// + /// + /// See Model building conventions for more information. + /// public class EntityTypeConfigurationEntityTypeAttributeConvention : EntityTypeAttributeConventionBase { private static readonly MethodInfo _configureMethod = typeof(EntityTypeConfigurationEntityTypeAttributeConvention) diff --git a/src/EFCore/Metadata/Conventions/ForeignKeyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/ForeignKeyAttributeConvention.cs index e3f219010ea..b7ebb300a33 100644 --- a/src/EFCore/Metadata/Conventions/ForeignKeyAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/ForeignKeyAttributeConvention.cs @@ -24,6 +24,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// For one-to-one relationships the attribute has to be specified on the navigation property pointing to the principal. /// /// + /// + /// See Model building conventions for more information. + /// public class ForeignKeyAttributeConvention : IEntityTypeAddedConvention, IForeignKeyAddedConvention, diff --git a/src/EFCore/Metadata/Conventions/ForeignKeyIndexConvention.cs b/src/EFCore/Metadata/Conventions/ForeignKeyIndexConvention.cs index 719f3133e3c..d9da5879e6e 100644 --- a/src/EFCore/Metadata/Conventions/ForeignKeyIndexConvention.cs +++ b/src/EFCore/Metadata/Conventions/ForeignKeyIndexConvention.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that creates indexes on foreign key properties unless they are already covered by existing indexes or keys. /// + /// + /// See Model building conventions for more information. + /// public class ForeignKeyIndexConvention : IForeignKeyAddedConvention, IForeignKeyRemovedConvention, diff --git a/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs index e9ef7224dbb..222657e024a 100644 --- a/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs @@ -36,6 +36,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// used to make the names unique. /// /// + /// + /// See Model building conventions for more information. + /// public class ForeignKeyPropertyDiscoveryConvention : IEntityTypeMemberIgnoredConvention, IEntityTypePrimaryKeyChangedConvention, diff --git a/src/EFCore/Metadata/Conventions/IConvention.cs b/src/EFCore/Metadata/Conventions/IConvention.cs index 629b41899f0..98f499079f4 100644 --- a/src/EFCore/Metadata/Conventions/IConvention.cs +++ b/src/EFCore/Metadata/Conventions/IConvention.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// This is the base interface for all convention interfaces, it should not be implemented directly. /// + /// + /// See Model building conventions for more information. + /// public interface IConvention { } diff --git a/src/EFCore/Metadata/Conventions/IConventionBatch.cs b/src/EFCore/Metadata/Conventions/IConventionBatch.cs index 0acee128848..171d47614cf 100644 --- a/src/EFCore/Metadata/Conventions/IConventionBatch.cs +++ b/src/EFCore/Metadata/Conventions/IConventionBatch.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an object that delays any convention invocations until it is run or disposed. /// + /// + /// See Model building conventions for more information. + /// public interface IConventionBatch : IDisposable { /// diff --git a/src/EFCore/Metadata/Conventions/IConventionContext.cs b/src/EFCore/Metadata/Conventions/IConventionContext.cs index aea20452993..cc42423b220 100644 --- a/src/EFCore/Metadata/Conventions/IConventionContext.cs +++ b/src/EFCore/Metadata/Conventions/IConventionContext.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Contextual information associated with each convention call. /// + /// + /// See Model building conventions for more information. + /// public interface IConventionContext { /// diff --git a/src/EFCore/Metadata/Conventions/IConventionContext`.cs b/src/EFCore/Metadata/Conventions/IConventionContext`.cs index 2de52bd887b..47135b774fe 100644 --- a/src/EFCore/Metadata/Conventions/IConventionContext`.cs +++ b/src/EFCore/Metadata/Conventions/IConventionContext`.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Contextual information associated with each convention call. /// + /// + /// See Model building conventions for more information. + /// /// The type of the metadata object. public interface IConventionContext : IConventionContext { diff --git a/src/EFCore/Metadata/Conventions/IEntityTypeAddedConvention.cs b/src/EFCore/Metadata/Conventions/IEntityTypeAddedConvention.cs index 49c24287ade..e53a89d9643 100644 --- a/src/EFCore/Metadata/Conventions/IEntityTypeAddedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IEntityTypeAddedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an entity type is added to the model. /// + /// + /// See Model building conventions for more information. + /// public interface IEntityTypeAddedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IEntityTypeAnnotationChangedConvention.cs b/src/EFCore/Metadata/Conventions/IEntityTypeAnnotationChangedConvention.cs index 63207ea81ed..923dfe28ba6 100644 --- a/src/EFCore/Metadata/Conventions/IEntityTypeAnnotationChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IEntityTypeAnnotationChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an annotation is changed on an entity type. /// + /// + /// See Model building conventions for more information. + /// public interface IEntityTypeAnnotationChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IEntityTypeBaseTypeChangedConvention.cs b/src/EFCore/Metadata/Conventions/IEntityTypeBaseTypeChangedConvention.cs index aa9a2dd1354..e80d7344019 100644 --- a/src/EFCore/Metadata/Conventions/IEntityTypeBaseTypeChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IEntityTypeBaseTypeChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the base type of an entity type changes. /// + /// + /// See Model building conventions for more information. + /// public interface IEntityTypeBaseTypeChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IEntityTypeIgnoredConvention.cs b/src/EFCore/Metadata/Conventions/IEntityTypeIgnoredConvention.cs index 517e630008c..7b7a0d41d1c 100644 --- a/src/EFCore/Metadata/Conventions/IEntityTypeIgnoredConvention.cs +++ b/src/EFCore/Metadata/Conventions/IEntityTypeIgnoredConvention.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an entity type is ignored. /// + /// + /// See Model building conventions for more information. + /// public interface IEntityTypeIgnoredConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IEntityTypeMemberIgnoredConvention.cs b/src/EFCore/Metadata/Conventions/IEntityTypeMemberIgnoredConvention.cs index 85dec0522ea..cc86a361505 100644 --- a/src/EFCore/Metadata/Conventions/IEntityTypeMemberIgnoredConvention.cs +++ b/src/EFCore/Metadata/Conventions/IEntityTypeMemberIgnoredConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an entity type member is ignored. /// + /// + /// See Model building conventions for more information. + /// public interface IEntityTypeMemberIgnoredConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IEntityTypePrimaryKeyChangedConvention.cs b/src/EFCore/Metadata/Conventions/IEntityTypePrimaryKeyChangedConvention.cs index 35f85d0f985..b074710d33e 100644 --- a/src/EFCore/Metadata/Conventions/IEntityTypePrimaryKeyChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IEntityTypePrimaryKeyChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the primary key for an entity type is changed. /// + /// + /// See Model building conventions for more information. + /// public interface IEntityTypePrimaryKeyChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IEntityTypeRemovedConvention.cs b/src/EFCore/Metadata/Conventions/IEntityTypeRemovedConvention.cs index 448c6c772ed..307a32158b7 100644 --- a/src/EFCore/Metadata/Conventions/IEntityTypeRemovedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IEntityTypeRemovedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an entity type is removed from the model. /// + /// + /// See Model building conventions for more information. + /// public interface IEntityTypeRemovedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyAddedConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyAddedConvention.cs index f21ece10539..88f29ce49e4 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyAddedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyAddedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a foreign key is added to the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyAddedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyAnnotationChangedConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyAnnotationChangedConvention.cs index ccdbdc17e1b..0adabeec013 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyAnnotationChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyAnnotationChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an annotation is changed on a foreign key. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyAnnotationChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyDependentRequirednessChangedConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyDependentRequirednessChangedConvention.cs index 00c01acff13..d1c03250158 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyDependentRequirednessChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyDependentRequirednessChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the dependent requiredness for a foreign key is changed. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyDependentRequirednessChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyNullNavigationSetConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyNullNavigationSetConvention.cs index 42f875b4605..789f60d0912 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyNullNavigationSetConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyNullNavigationSetConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a navigation is set to on a foreign key. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyNullNavigationSetConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyOwnershipChangedConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyOwnershipChangedConvention.cs index 296bab708de..268331bd391 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyOwnershipChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyOwnershipChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the ownership value for a foreign key is changed. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyOwnershipChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyPrincipalEndChangedConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyPrincipalEndChangedConvention.cs index 502892f463f..2a8739d71da 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyPrincipalEndChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyPrincipalEndChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the principal end of a foreign key is changed. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyPrincipalEndChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyPropertiesChangedConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyPropertiesChangedConvention.cs index 8a3fde1c40b..edf3c9340bb 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyPropertiesChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyPropertiesChangedConvention.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the foreign key properties or principal key are changed. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyPropertiesChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyRemovedConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyRemovedConvention.cs index c2af6374b4c..eaa738a1db5 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyRemovedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyRemovedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a foreign key is removed. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyRemovedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyRequirednessChangedConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyRequirednessChangedConvention.cs index e67e107a6df..429576ee9ca 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyRequirednessChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyRequirednessChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the requiredness for a foreign key is changed. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyRequirednessChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IForeignKeyUniquenessChangedConvention.cs b/src/EFCore/Metadata/Conventions/IForeignKeyUniquenessChangedConvention.cs index b295a6c272a..329b5744c68 100644 --- a/src/EFCore/Metadata/Conventions/IForeignKeyUniquenessChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IForeignKeyUniquenessChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the uniqueness for a foreign key is changed. /// + /// + /// See Model building conventions for more information. + /// public interface IForeignKeyUniquenessChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IIndexAddedConvention.cs b/src/EFCore/Metadata/Conventions/IIndexAddedConvention.cs index 18ad391961f..d71b747059e 100644 --- a/src/EFCore/Metadata/Conventions/IIndexAddedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IIndexAddedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an index is added to the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface IIndexAddedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IIndexAnnotationChangedConvention.cs b/src/EFCore/Metadata/Conventions/IIndexAnnotationChangedConvention.cs index b1bf78e078d..3645e40a9ab 100644 --- a/src/EFCore/Metadata/Conventions/IIndexAnnotationChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IIndexAnnotationChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an annotation is changed on an index. /// + /// + /// See Model building conventions for more information. + /// public interface IIndexAnnotationChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IIndexRemovedConvention.cs b/src/EFCore/Metadata/Conventions/IIndexRemovedConvention.cs index 02585b8311d..4a9e28f1a38 100644 --- a/src/EFCore/Metadata/Conventions/IIndexRemovedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IIndexRemovedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an index is removed from the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface IIndexRemovedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IIndexUniquenessChangedConvention.cs b/src/EFCore/Metadata/Conventions/IIndexUniquenessChangedConvention.cs index abf64606aeb..bd9ab56aba8 100644 --- a/src/EFCore/Metadata/Conventions/IIndexUniquenessChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IIndexUniquenessChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the uniqueness for an index is changed. /// + /// + /// See Model building conventions for more information. + /// public interface IIndexUniquenessChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IKeyAddedConvention.cs b/src/EFCore/Metadata/Conventions/IKeyAddedConvention.cs index 8f8dd6b031b..9a6906664dd 100644 --- a/src/EFCore/Metadata/Conventions/IKeyAddedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IKeyAddedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a key is added to the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface IKeyAddedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IKeyAnnotationChangedConvention.cs b/src/EFCore/Metadata/Conventions/IKeyAnnotationChangedConvention.cs index ae43fdac1e6..1715425d71e 100644 --- a/src/EFCore/Metadata/Conventions/IKeyAnnotationChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IKeyAnnotationChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an annotation is changed on a key. /// + /// + /// See Model building conventions for more information. + /// public interface IKeyAnnotationChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IKeyRemovedConvention.cs b/src/EFCore/Metadata/Conventions/IKeyRemovedConvention.cs index 8113bd9339a..fb1891d605f 100644 --- a/src/EFCore/Metadata/Conventions/IKeyRemovedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IKeyRemovedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a key is removed. /// + /// + /// See Model building conventions for more information. + /// public interface IKeyRemovedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IModelAnnotationChangedConvention.cs b/src/EFCore/Metadata/Conventions/IModelAnnotationChangedConvention.cs index d23d94aca26..ae71dc0d492 100644 --- a/src/EFCore/Metadata/Conventions/IModelAnnotationChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IModelAnnotationChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an annotation is changed on a model. /// + /// + /// See Model building conventions for more information. + /// public interface IModelAnnotationChangedConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IModelFinalizedConvention.cs b/src/EFCore/Metadata/Conventions/IModelFinalizedConvention.cs index 70f524a9d94..8b52ce7594c 100644 --- a/src/EFCore/Metadata/Conventions/IModelFinalizedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IModelFinalizedConvention.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed after a model is finalized and can no longer be mutated. /// + /// + /// See Model building conventions for more information. + /// public interface IModelFinalizedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IModelFinalizingConvention.cs b/src/EFCore/Metadata/Conventions/IModelFinalizingConvention.cs index 3bb168fd6a2..a36e8b19609 100644 --- a/src/EFCore/Metadata/Conventions/IModelFinalizingConvention.cs +++ b/src/EFCore/Metadata/Conventions/IModelFinalizingConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a model is being finalized. /// + /// + /// See Model building conventions for more information. + /// public interface IModelFinalizingConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IModelInitializedConvention.cs b/src/EFCore/Metadata/Conventions/IModelInitializedConvention.cs index baaa9050b55..57f34a04178 100644 --- a/src/EFCore/Metadata/Conventions/IModelInitializedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IModelInitializedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a model is initialized. /// + /// + /// See Model building conventions for more information. + /// public interface IModelInitializedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/INavigationAddedConvention.cs b/src/EFCore/Metadata/Conventions/INavigationAddedConvention.cs index adb5f709161..e5f62129118 100644 --- a/src/EFCore/Metadata/Conventions/INavigationAddedConvention.cs +++ b/src/EFCore/Metadata/Conventions/INavigationAddedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a navigation is added to the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface INavigationAddedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/INavigationAnnotationChangedConvention.cs b/src/EFCore/Metadata/Conventions/INavigationAnnotationChangedConvention.cs index 2b8cbc205a2..5d9910827c7 100644 --- a/src/EFCore/Metadata/Conventions/INavigationAnnotationChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/INavigationAnnotationChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an annotation is changed on a navigation. /// + /// + /// See Model building conventions for more information. + /// public interface INavigationAnnotationChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/INavigationRemovedConvention.cs b/src/EFCore/Metadata/Conventions/INavigationRemovedConvention.cs index d949017b856..e6ec26488aa 100644 --- a/src/EFCore/Metadata/Conventions/INavigationRemovedConvention.cs +++ b/src/EFCore/Metadata/Conventions/INavigationRemovedConvention.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a navigation is removed from the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface INavigationRemovedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IPropertyAddedConvention.cs b/src/EFCore/Metadata/Conventions/IPropertyAddedConvention.cs index 6c313816ed9..3fd83ee7158 100644 --- a/src/EFCore/Metadata/Conventions/IPropertyAddedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IPropertyAddedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a property is added to the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface IPropertyAddedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IPropertyAnnotationChangedConvention.cs b/src/EFCore/Metadata/Conventions/IPropertyAnnotationChangedConvention.cs index 1af045e7027..e5b7d459c00 100644 --- a/src/EFCore/Metadata/Conventions/IPropertyAnnotationChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IPropertyAnnotationChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an annotation is changed on a property. /// + /// + /// See Model building conventions for more information. + /// public interface IPropertyAnnotationChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IPropertyFieldChangedConvention.cs b/src/EFCore/Metadata/Conventions/IPropertyFieldChangedConvention.cs index 9afadd177df..7dea81e37b8 100644 --- a/src/EFCore/Metadata/Conventions/IPropertyFieldChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IPropertyFieldChangedConvention.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the backing field for a property is changed. /// + /// + /// See Model building conventions for more information. + /// public interface IPropertyFieldChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IPropertyNullabilityChangedConvention.cs b/src/EFCore/Metadata/Conventions/IPropertyNullabilityChangedConvention.cs index 25a310144a5..8ca9b27e91b 100644 --- a/src/EFCore/Metadata/Conventions/IPropertyNullabilityChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IPropertyNullabilityChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when the nullability for a property is changed. /// + /// + /// See Model building conventions for more information. + /// public interface IPropertyNullabilityChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IPropertyRemovedConvention.cs b/src/EFCore/Metadata/Conventions/IPropertyRemovedConvention.cs index ad0febab96f..3df43fcd2ef 100644 --- a/src/EFCore/Metadata/Conventions/IPropertyRemovedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IPropertyRemovedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a property is removed from the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface IPropertyRemovedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/ISkipNavigationAddedConvention.cs b/src/EFCore/Metadata/Conventions/ISkipNavigationAddedConvention.cs index 3bf26e146c0..d62201995f3 100644 --- a/src/EFCore/Metadata/Conventions/ISkipNavigationAddedConvention.cs +++ b/src/EFCore/Metadata/Conventions/ISkipNavigationAddedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a skip navigation is added to the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface ISkipNavigationAddedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/ISkipNavigationAnnotationChangedConvention.cs b/src/EFCore/Metadata/Conventions/ISkipNavigationAnnotationChangedConvention.cs index 4f35f09b1a7..9b510f46964 100644 --- a/src/EFCore/Metadata/Conventions/ISkipNavigationAnnotationChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/ISkipNavigationAnnotationChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when an annotation is changed on a skip navigation. /// + /// + /// See Model building conventions for more information. + /// public interface ISkipNavigationAnnotationChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/ISkipNavigationForeignKeyChangedConvention.cs b/src/EFCore/Metadata/Conventions/ISkipNavigationForeignKeyChangedConvention.cs index 2e30efa0195..0ed0b87b14d 100644 --- a/src/EFCore/Metadata/Conventions/ISkipNavigationForeignKeyChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/ISkipNavigationForeignKeyChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a skip navigation foreign key is changed. /// + /// + /// See Model building conventions for more information. + /// public interface ISkipNavigationForeignKeyChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/ISkipNavigationInverseChangedConvention.cs b/src/EFCore/Metadata/Conventions/ISkipNavigationInverseChangedConvention.cs index 471e2d74239..1f2d389d768 100644 --- a/src/EFCore/Metadata/Conventions/ISkipNavigationInverseChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/ISkipNavigationInverseChangedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a skip navigation inverse is changed. /// + /// + /// See Model building conventions for more information. + /// public interface ISkipNavigationInverseChangedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/ISkipNavigationRemovedConvention.cs b/src/EFCore/Metadata/Conventions/ISkipNavigationRemovedConvention.cs index d35d3e055f3..e45059b733d 100644 --- a/src/EFCore/Metadata/Conventions/ISkipNavigationRemovedConvention.cs +++ b/src/EFCore/Metadata/Conventions/ISkipNavigationRemovedConvention.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a skip navigation is removed from the entity type. /// + /// + /// See Model building conventions for more information. + /// public interface ISkipNavigationRemovedConvention : IConvention { /// diff --git a/src/EFCore/Metadata/Conventions/IndexAttributeConvention.cs b/src/EFCore/Metadata/Conventions/IndexAttributeConvention.cs index a48341c5340..ada5061a8ff 100644 --- a/src/EFCore/Metadata/Conventions/IndexAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/IndexAttributeConvention.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures database indexes based on the . /// + /// + /// See Model building conventions for more information. + /// public class IndexAttributeConvention : IEntityTypeAddedConvention, IEntityTypeBaseTypeChangedConvention, IModelFinalizingConvention { /// diff --git a/src/EFCore/Metadata/Conventions/Infrastructure/IConventionSetBuilder.cs b/src/EFCore/Metadata/Conventions/Infrastructure/IConventionSetBuilder.cs index f30e8536ce5..74a105d4adb 100644 --- a/src/EFCore/Metadata/Conventions/Infrastructure/IConventionSetBuilder.cs +++ b/src/EFCore/Metadata/Conventions/Infrastructure/IConventionSetBuilder.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure /// The implementation does not need to be thread-safe. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionSetBuilder { /// diff --git a/src/EFCore/Metadata/Conventions/Infrastructure/IConventionSetPlugin.cs b/src/EFCore/Metadata/Conventions/Infrastructure/IConventionSetPlugin.cs index 15a9691ea9e..ab7d3b0bebe 100644 --- a/src/EFCore/Metadata/Conventions/Infrastructure/IConventionSetPlugin.cs +++ b/src/EFCore/Metadata/Conventions/Infrastructure/IConventionSetPlugin.cs @@ -25,6 +25,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure /// The implementations do not need to be thread-safe. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionSetPlugin { /// diff --git a/src/EFCore/Metadata/Conventions/Infrastructure/IProviderConventionSetBuilder.cs b/src/EFCore/Metadata/Conventions/Infrastructure/IProviderConventionSetBuilder.cs index 154a643becf..4d765162bac 100644 --- a/src/EFCore/Metadata/Conventions/Infrastructure/IProviderConventionSetBuilder.cs +++ b/src/EFCore/Metadata/Conventions/Infrastructure/IProviderConventionSetBuilder.cs @@ -28,6 +28,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure /// The implementation does not need to be thread-safe. /// /// + /// + /// See Model building conventions for more information. + /// public interface IProviderConventionSetBuilder { /// diff --git a/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs b/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs index fe35e54aec5..212b3c2d55d 100644 --- a/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs +++ b/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs @@ -29,6 +29,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure /// The implementation does not need to be thread-safe. /// /// + /// + /// See Model building conventions for more information. + /// public class ProviderConventionSetBuilder : IProviderConventionSetBuilder { /// diff --git a/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs b/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs index 16ed231707c..4311152b877 100644 --- a/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs +++ b/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Base type for inheritance discovery conventions /// + /// + /// See Model building conventions for more information. + /// [Obsolete] public abstract class InheritanceDiscoveryConventionBase { diff --git a/src/EFCore/Metadata/Conventions/InversePropertyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/InversePropertyAttributeConvention.cs index 060505aebf2..d9a2485b803 100644 --- a/src/EFCore/Metadata/Conventions/InversePropertyAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/InversePropertyAttributeConvention.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures the inverse navigation property based on the /// specified on the other navigation property. /// + /// + /// See Model building conventions for more information. + /// public class InversePropertyAttributeConvention : NavigationAttributeConventionBase, IModelFinalizingConvention diff --git a/src/EFCore/Metadata/Conventions/KeyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/KeyAttributeConvention.cs index 16848f18f32..658685b6d29 100644 --- a/src/EFCore/Metadata/Conventions/KeyAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/KeyAttributeConvention.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the entity type key based on the specified on a property. /// + /// + /// See Model building conventions for more information. + /// public class KeyAttributeConvention : PropertyAttributeConventionBase, IModelFinalizingConvention { /// diff --git a/src/EFCore/Metadata/Conventions/KeyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/KeyDiscoveryConvention.cs index 897d16391aa..d64f93996ff 100644 --- a/src/EFCore/Metadata/Conventions/KeyDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/KeyDiscoveryConvention.cs @@ -26,6 +26,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// is configured using the foreign key properties with an extra property that matches the naming convention above. /// /// + /// + /// See Model building conventions for more information. + /// public class KeyDiscoveryConvention : IEntityTypeAddedConvention, IPropertyAddedConvention, diff --git a/src/EFCore/Metadata/Conventions/KeylessEntityTypeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/KeylessEntityTypeAttributeConvention.cs index f0e5b1cbe5a..7717b5c7ca9 100644 --- a/src/EFCore/Metadata/Conventions/KeylessEntityTypeAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/KeylessEntityTypeAttributeConvention.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that ignores entity types that have the . /// + /// + /// See Model building conventions for more information. + /// public class KeylessEntityTypeAttributeConvention : EntityTypeAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/ManyToManyJoinEntityTypeConvention.cs b/src/EFCore/Metadata/Conventions/ManyToManyJoinEntityTypeConvention.cs index aa9ffd3a3e8..f9430593f02 100644 --- a/src/EFCore/Metadata/Conventions/ManyToManyJoinEntityTypeConvention.cs +++ b/src/EFCore/Metadata/Conventions/ManyToManyJoinEntityTypeConvention.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// a many-to-many join entity with suitable foreign keys, sets the two /// matching skip navigations to use those foreign keys. /// + /// + /// See Model building conventions for more information. + /// public class ManyToManyJoinEntityTypeConvention : ISkipNavigationAddedConvention, ISkipNavigationInverseChangedConvention, diff --git a/src/EFCore/Metadata/Conventions/MaxLengthAttributeConvention.cs b/src/EFCore/Metadata/Conventions/MaxLengthAttributeConvention.cs index e3f43a6082a..3628d286a0f 100644 --- a/src/EFCore/Metadata/Conventions/MaxLengthAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/MaxLengthAttributeConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the maximum length based on the applied on the property. /// + /// + /// See Model building conventions for more information. + /// public class MaxLengthAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/ModelCleanupConvention.cs b/src/EFCore/Metadata/Conventions/ModelCleanupConvention.cs index f12fc7c96b3..039b0ab503e 100644 --- a/src/EFCore/Metadata/Conventions/ModelCleanupConvention.cs +++ b/src/EFCore/Metadata/Conventions/ModelCleanupConvention.cs @@ -5,7 +5,6 @@ using System.Linq; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions @@ -13,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that removes any state that is only used during model building. /// + /// + /// See Model building conventions for more information. + /// public class ModelCleanupConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore/Metadata/Conventions/NavigationAttributeConventionBase.cs b/src/EFCore/Metadata/Conventions/NavigationAttributeConventionBase.cs index 1dcd8acd477..4fbe667d1cf 100644 --- a/src/EFCore/Metadata/Conventions/NavigationAttributeConventionBase.cs +++ b/src/EFCore/Metadata/Conventions/NavigationAttributeConventionBase.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A base type for conventions that perform configuration based on an attribute applied to a navigation. /// + /// + /// See Model building conventions for more information. + /// /// The attribute type to look for. public abstract class NavigationAttributeConventionBase : IEntityTypeAddedConvention, diff --git a/src/EFCore/Metadata/Conventions/NavigationBackingFieldAttributeConvention.cs b/src/EFCore/Metadata/Conventions/NavigationBackingFieldAttributeConvention.cs index f6765675758..6c2bc5c57e0 100644 --- a/src/EFCore/Metadata/Conventions/NavigationBackingFieldAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/NavigationBackingFieldAttributeConvention.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures a navigation property as having a backing field /// based on the attribute. /// + /// + /// See Model building conventions for more information. + /// public class NavigationBackingFieldAttributeConvention : NavigationAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/NavigationEagerLoadingConvention.cs b/src/EFCore/Metadata/Conventions/NavigationEagerLoadingConvention.cs index d180e330696..ee0ebaccaa3 100644 --- a/src/EFCore/Metadata/Conventions/NavigationEagerLoadingConvention.cs +++ b/src/EFCore/Metadata/Conventions/NavigationEagerLoadingConvention.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the navigations to owned entity types as eager loaded. /// + /// + /// See Model building conventions for more information. + /// public class NavigationEagerLoadingConvention : IForeignKeyOwnershipChangedConvention { /// diff --git a/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs b/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs index 9c8d61cb305..5c5ea86c3ef 100644 --- a/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs +++ b/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A base type for conventions that configure model aspects based on whether the member type /// is a non-nullable reference type. /// + /// + /// See Model building conventions for more information. + /// public abstract class NonNullableConventionBase : IModelFinalizingConvention { // For the interpretation of nullability metadata, see diff --git a/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs b/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs index a16a33d1c8b..648a323539a 100644 --- a/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs +++ b/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the non-nullable navigations to principal entity type as required. /// + /// + /// See Model building conventions for more information. + /// public class NonNullableNavigationConvention : NonNullableConventionBase, INavigationAddedConvention, diff --git a/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs b/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs index fa3ae8a111c..86e0f7f7abf 100644 --- a/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs +++ b/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the properties of non-nullable types as required. /// + /// + /// See Model building conventions for more information. + /// public class NonNullableReferencePropertyConvention : NonNullableConventionBase, IPropertyAddedConvention, IPropertyFieldChangedConvention diff --git a/src/EFCore/Metadata/Conventions/NotMappedEntityTypeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/NotMappedEntityTypeAttributeConvention.cs index 01d0b6e24dc..fb28e30b67c 100644 --- a/src/EFCore/Metadata/Conventions/NotMappedEntityTypeAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/NotMappedEntityTypeAttributeConvention.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that ignores entity types that have the . /// + /// + /// See Model building conventions for more information. + /// public class NotMappedEntityTypeAttributeConvention : EntityTypeAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/NotMappedMemberAttributeConvention.cs b/src/EFCore/Metadata/Conventions/NotMappedMemberAttributeConvention.cs index 43b4be2ce28..b56772c0b15 100644 --- a/src/EFCore/Metadata/Conventions/NotMappedMemberAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/NotMappedMemberAttributeConvention.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that ignores members on entity types that have the . /// + /// + /// See Model building conventions for more information. + /// public class NotMappedMemberAttributeConvention : IEntityTypeAddedConvention { /// diff --git a/src/EFCore/Metadata/Conventions/OwnedEntityTypeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/OwnedEntityTypeAttributeConvention.cs index dfb0fe72af3..364023b109d 100644 --- a/src/EFCore/Metadata/Conventions/OwnedEntityTypeAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/OwnedEntityTypeAttributeConvention.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the entity types that have the as owned. /// + /// + /// See Model building conventions for more information. + /// public class OwnedEntityTypeAttributeConvention : EntityTypeAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/OwnedTypesConvention.cs b/src/EFCore/Metadata/Conventions/OwnedTypesConvention.cs index a7f86652688..3a149567e8b 100644 --- a/src/EFCore/Metadata/Conventions/OwnedTypesConvention.cs +++ b/src/EFCore/Metadata/Conventions/OwnedTypesConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures owned entity types with defining navigation as owned entity types /// without defining navigation if there's only one navigation of this type. /// + /// + /// See Model building conventions for more information. + /// [Obsolete("Entity types with defining navigations have been replaced by shared-type entity types")] public class OwnedTypesConvention : IEntityTypeRemovedConvention { diff --git a/src/EFCore/Metadata/Conventions/PrecisionAttributeConvention.cs b/src/EFCore/Metadata/Conventions/PrecisionAttributeConvention.cs index bb5445b8b6f..10d9285e8c7 100644 --- a/src/EFCore/Metadata/Conventions/PrecisionAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/PrecisionAttributeConvention.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the Precision based on the applied on the property. /// + /// + /// See Model building conventions for more information. + /// public class PrecisionAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/PropertyAttributeConventionBase.cs b/src/EFCore/Metadata/Conventions/PropertyAttributeConventionBase.cs index 997943b9ebc..0d7bc59c4c4 100644 --- a/src/EFCore/Metadata/Conventions/PropertyAttributeConventionBase.cs +++ b/src/EFCore/Metadata/Conventions/PropertyAttributeConventionBase.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A base type for conventions that perform configuration based on an attribute applied to a property. /// + /// + /// See Model building conventions for more information. + /// /// The attribute type to look for. public abstract class PropertyAttributeConventionBase : IPropertyAddedConvention, IPropertyFieldChangedConvention where TAttribute : Attribute diff --git a/src/EFCore/Metadata/Conventions/PropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/PropertyDiscoveryConvention.cs index e81995ef07d..8c2a3cd568e 100644 --- a/src/EFCore/Metadata/Conventions/PropertyDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/PropertyDiscoveryConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that adds properties to entity types corresponding to scalar public properties on the CLR type. /// + /// + /// See Model building conventions for more information. + /// public class PropertyDiscoveryConvention : IEntityTypeAddedConvention, IEntityTypeBaseTypeChangedConvention diff --git a/src/EFCore/Metadata/Conventions/QueryFilterRewritingConvention.cs b/src/EFCore/Metadata/Conventions/QueryFilterRewritingConvention.cs index 796e9e3e2da..fc1092f3b00 100644 --- a/src/EFCore/Metadata/Conventions/QueryFilterRewritingConvention.cs +++ b/src/EFCore/Metadata/Conventions/QueryFilterRewritingConvention.cs @@ -18,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// This makes them consistent with how DbSet accesses in the actual queries are represented, which allows for easier processing in the /// query pipeline. /// + /// + /// See Model building conventions for more information. + /// public class QueryFilterRewritingConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore/Metadata/Conventions/RelationshipDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/RelationshipDiscoveryConvention.cs index f9955624947..46f13411aa0 100644 --- a/src/EFCore/Metadata/Conventions/RelationshipDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/RelationshipDiscoveryConvention.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures relationships between entity types based on the navigation properties /// as long as there is no ambiguity as to which is the corresponding inverse navigation. /// + /// + /// See Model building conventions for more information. + /// public class RelationshipDiscoveryConvention : IEntityTypeAddedConvention, IEntityTypeIgnoredConvention, diff --git a/src/EFCore/Metadata/Conventions/RequiredNavigationAttributeConvention.cs b/src/EFCore/Metadata/Conventions/RequiredNavigationAttributeConvention.cs index d4f284ec600..8a4b801e692 100644 --- a/src/EFCore/Metadata/Conventions/RequiredNavigationAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/RequiredNavigationAttributeConvention.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures the principal side of the relationship as required if the /// is applied on the navigation property to the principal entity type. /// + /// + /// See Model building conventions for more information. + /// public class RequiredNavigationAttributeConvention : NavigationAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/RequiredPropertyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/RequiredPropertyAttributeConvention.cs index 5ebc4ecca96..eb50497d136 100644 --- a/src/EFCore/Metadata/Conventions/RequiredPropertyAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/RequiredPropertyAttributeConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures properties as required if they have the applied. /// + /// + /// See Model building conventions for more information. + /// public class RequiredPropertyAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs b/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs index 88393937a19..45d4b28d644 100644 --- a/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs +++ b/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that creates an optimized copy of the mutable model. This convention is typically /// implemented by database providers to update provider annotations when creating a read-only model. /// + /// + /// See Model building conventions for more information. + /// public class RuntimeModelConvention : IModelFinalizedConvention { /// diff --git a/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs index 7ba1c10b6e0..d796dda5399 100644 --- a/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that adds service properties to entity types. /// + /// + /// See Model building conventions for more information. + /// public class ServicePropertyDiscoveryConvention : IEntityTypeAddedConvention, IEntityTypeBaseTypeChangedConvention diff --git a/src/EFCore/Metadata/Conventions/StringLengthAttributeConvention.cs b/src/EFCore/Metadata/Conventions/StringLengthAttributeConvention.cs index ae76cddae7a..6facb45f2d6 100644 --- a/src/EFCore/Metadata/Conventions/StringLengthAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/StringLengthAttributeConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the maximum length based on the applied on the property. /// + /// + /// See Model building conventions for more information. + /// public class StringLengthAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/TimestampAttributeConvention.cs b/src/EFCore/Metadata/Conventions/TimestampAttributeConvention.cs index 74ae9046bc2..d502532590b 100644 --- a/src/EFCore/Metadata/Conventions/TimestampAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/TimestampAttributeConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the property as a concurrency token if a is applied to it. /// + /// + /// See Model building conventions for more information. + /// public class TimestampAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/TypeMappingConvention.cs b/src/EFCore/Metadata/Conventions/TypeMappingConvention.cs index 1671246955d..cc6c5629385 100644 --- a/src/EFCore/Metadata/Conventions/TypeMappingConvention.cs +++ b/src/EFCore/Metadata/Conventions/TypeMappingConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that creates and assigns store type mapping to entity properties. /// + /// + /// See Model building conventions for more information. + /// [Obsolete("Use IModelRuntimeInitializer.Initialize instead.")] public class TypeMappingConvention : IModelFinalizingConvention { diff --git a/src/EFCore/Metadata/Conventions/UnicodeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/UnicodeAttributeConvention.cs index 8f9f6b239ea..e3b3cb5266c 100644 --- a/src/EFCore/Metadata/Conventions/UnicodeAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/UnicodeAttributeConvention.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the Unicode based on the applied on the property. /// + /// + /// See Model building conventions for more information. + /// public class UnicodeAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore/Metadata/Conventions/ValidatingConvention.cs b/src/EFCore/Metadata/Conventions/ValidatingConvention.cs index 46299426a57..3b8b347f41b 100644 --- a/src/EFCore/Metadata/Conventions/ValidatingConvention.cs +++ b/src/EFCore/Metadata/Conventions/ValidatingConvention.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that checks whether the model is valid. /// + /// + /// See Model building conventions for more information. + /// [Obsolete("The validation is no longer performed by a convention")] public class ValidatingConvention : IModelFinalizedConvention { diff --git a/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs b/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs index 420135a0ac9..8f524743d3b 100644 --- a/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs +++ b/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures store value generation as on properties that are /// part of the primary key and not part of any foreign keys. /// + /// + /// See Model building conventions for more information. + /// public class ValueGenerationConvention : IEntityTypePrimaryKeyChangedConvention, IForeignKeyAddedConvention, diff --git a/src/EFCore/Metadata/DependencyInjectionMethodParameterBinding.cs b/src/EFCore/Metadata/DependencyInjectionMethodParameterBinding.cs index 2d34be16b66..e0b669a0d57 100644 --- a/src/EFCore/Metadata/DependencyInjectionMethodParameterBinding.cs +++ b/src/EFCore/Metadata/DependencyInjectionMethodParameterBinding.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// also have and associated , to a parameter in a constructor, /// factory method, or similar. /// + /// + /// See Entity types with constructors for more information. + /// public class DependencyInjectionMethodParameterBinding : DependencyInjectionParameterBinding { /// diff --git a/src/EFCore/Metadata/DependencyInjectionParameterBinding.cs b/src/EFCore/Metadata/DependencyInjectionParameterBinding.cs index fb986b67d42..cb1038f72b1 100644 --- a/src/EFCore/Metadata/DependencyInjectionParameterBinding.cs +++ b/src/EFCore/Metadata/DependencyInjectionParameterBinding.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// also have and associated , to a parameter in a constructor, /// factory method, or similar. /// + /// + /// See Entity types with constructors for more information. + /// public class DependencyInjectionParameterBinding : ServiceParameterBinding { private static readonly MethodInfo _getServiceMethod diff --git a/src/EFCore/Metadata/EntityTypeFullNameComparer.cs b/src/EFCore/Metadata/EntityTypeFullNameComparer.cs index b6750efdc75..d2fe6135fa9 100644 --- a/src/EFCore/Metadata/EntityTypeFullNameComparer.cs +++ b/src/EFCore/Metadata/EntityTypeFullNameComparer.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions for more information. + /// public sealed class EntityTypeFullNameComparer : IComparer, IEqualityComparer { private EntityTypeFullNameComparer() diff --git a/src/EFCore/Metadata/EntityTypeParameterBinding.cs b/src/EFCore/Metadata/EntityTypeParameterBinding.cs index 93ff14bb0e9..5b30409ac2a 100644 --- a/src/EFCore/Metadata/EntityTypeParameterBinding.cs +++ b/src/EFCore/Metadata/EntityTypeParameterBinding.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Describes the binding of a , which may or may not also have and associated /// , to a parameter in a constructor, factory method, or similar. /// + /// + /// See Entity types with constructors for more information. + /// public class EntityTypeParameterBinding : ServiceParameterBinding { /// diff --git a/src/EFCore/Metadata/FactoryMethodBinding.cs b/src/EFCore/Metadata/FactoryMethodBinding.cs index a8d7bba8505..e58c6948889 100644 --- a/src/EFCore/Metadata/FactoryMethodBinding.cs +++ b/src/EFCore/Metadata/FactoryMethodBinding.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Defines the binding of parameters to a factory method. /// + /// + /// See Entity types with constructors for more information. + /// public class FactoryMethodBinding : InstantiationBinding { private readonly object? _factoryInstance; diff --git a/src/EFCore/Metadata/ForeignKeyComparer.cs b/src/EFCore/Metadata/ForeignKeyComparer.cs index 3d96cea2215..b7ff1be4a67 100644 --- a/src/EFCore/Metadata/ForeignKeyComparer.cs +++ b/src/EFCore/Metadata/ForeignKeyComparer.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions for more information. + /// public sealed class ForeignKeyComparer : IEqualityComparer, IComparer { private ForeignKeyComparer() diff --git a/src/EFCore/Metadata/IClrCollectionAccessor.cs b/src/EFCore/Metadata/IClrCollectionAccessor.cs index ab78fb0121d..7c637d60b2b 100644 --- a/src/EFCore/Metadata/IClrCollectionAccessor.cs +++ b/src/EFCore/Metadata/IClrCollectionAccessor.cs @@ -6,9 +6,18 @@ namespace Microsoft.EntityFrameworkCore.Metadata { /// - /// Represents operations backed by compiled delegates that allow manipulation of collections - /// on navigation properties. + /// + /// Represents operations backed by compiled delegates that allow manipulation of collections + /// on navigation properties. + /// + /// + /// This type is typically used by database providers (and other extensions). It is generally + /// not used in application code. + /// /// + /// + /// See Implementation of database providers and extensions for more information. + /// public interface IClrCollectionAccessor { /// diff --git a/src/EFCore/Metadata/IClrPropertyGetter.cs b/src/EFCore/Metadata/IClrPropertyGetter.cs index 5bbc5a4d57b..2a6ffd24597 100644 --- a/src/EFCore/Metadata/IClrPropertyGetter.cs +++ b/src/EFCore/Metadata/IClrPropertyGetter.cs @@ -4,9 +4,18 @@ namespace Microsoft.EntityFrameworkCore.Metadata { /// - /// Represents operations backed by compiled delegates that support getting the value - /// of a mapped EF property. + /// + /// Represents operations backed by compiled delegates that support getting the value + /// of a mapped EF property. + /// + /// + /// This type is typically used by database providers (and other extensions). It is generally + /// not used in application code. + /// /// + /// + /// See Implementation of database providers and extensions for more information. + /// public interface IClrPropertyGetter { /// diff --git a/src/EFCore/Metadata/IClrPropertySetter.cs b/src/EFCore/Metadata/IClrPropertySetter.cs index 3197892992c..62984df561f 100644 --- a/src/EFCore/Metadata/IClrPropertySetter.cs +++ b/src/EFCore/Metadata/IClrPropertySetter.cs @@ -4,9 +4,18 @@ namespace Microsoft.EntityFrameworkCore.Metadata { /// - /// Represents operations backed by compiled delegates that support setting the value - /// of a mapped EF property. + /// + /// Represents operations backed by compiled delegates that support setting the value + /// of a mapped EF property. + /// + /// + /// This type is typically used by database providers (and other extensions). It is generally + /// not used in application code. + /// /// + /// + /// See Implementation of database providers and extensions for more information. + /// public interface IClrPropertySetter { /// diff --git a/src/EFCore/Metadata/IConstructorBindingFactory.cs b/src/EFCore/Metadata/IConstructorBindingFactory.cs index 897ed61a327..2d3114ac598 100644 --- a/src/EFCore/Metadata/IConstructorBindingFactory.cs +++ b/src/EFCore/Metadata/IConstructorBindingFactory.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// This service cannot depend on services registered as . /// /// + /// + /// See Entity types with constructors for more information. + /// public interface IConstructorBindingFactory { /// diff --git a/src/EFCore/Metadata/IConventionAnnotatable.cs b/src/EFCore/Metadata/IConventionAnnotatable.cs index ed33a566365..173e4f52bd7 100644 --- a/src/EFCore/Metadata/IConventionAnnotatable.cs +++ b/src/EFCore/Metadata/IConventionAnnotatable.cs @@ -18,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionAnnotatable : IReadOnlyAnnotatable { /// diff --git a/src/EFCore/Metadata/IConventionAnnotation.cs b/src/EFCore/Metadata/IConventionAnnotation.cs index cb63b5c4bc6..483da66c40a 100644 --- a/src/EFCore/Metadata/IConventionAnnotation.cs +++ b/src/EFCore/Metadata/IConventionAnnotation.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// not used in application code. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionAnnotation : IAnnotation { /// diff --git a/src/EFCore/Metadata/IConventionEntityType.cs b/src/EFCore/Metadata/IConventionEntityType.cs index 9c05ea830e8..46d83bbe2d6 100644 --- a/src/EFCore/Metadata/IConventionEntityType.cs +++ b/src/EFCore/Metadata/IConventionEntityType.cs @@ -23,6 +23,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionEntityType : IReadOnlyEntityType, IConventionTypeBase { /// diff --git a/src/EFCore/Metadata/IConventionForeignKey.cs b/src/EFCore/Metadata/IConventionForeignKey.cs index 0c666c1377d..c47803cc93f 100644 --- a/src/EFCore/Metadata/IConventionForeignKey.cs +++ b/src/EFCore/Metadata/IConventionForeignKey.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionForeignKey : IReadOnlyForeignKey, IConventionAnnotatable { /// diff --git a/src/EFCore/Metadata/IConventionIndex.cs b/src/EFCore/Metadata/IConventionIndex.cs index 79cc0f50839..dfb01361d7a 100644 --- a/src/EFCore/Metadata/IConventionIndex.cs +++ b/src/EFCore/Metadata/IConventionIndex.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionIndex : IReadOnlyIndex, IConventionAnnotatable { /// diff --git a/src/EFCore/Metadata/IConventionKey.cs b/src/EFCore/Metadata/IConventionKey.cs index b14434e55aa..b25e672b254 100644 --- a/src/EFCore/Metadata/IConventionKey.cs +++ b/src/EFCore/Metadata/IConventionKey.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionKey : IReadOnlyKey, IConventionAnnotatable { /// diff --git a/src/EFCore/Metadata/IConventionModel.cs b/src/EFCore/Metadata/IConventionModel.cs index f26a414e7d6..a52347ec001 100644 --- a/src/EFCore/Metadata/IConventionModel.cs +++ b/src/EFCore/Metadata/IConventionModel.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionModel : IReadOnlyModel, IConventionAnnotatable { /// diff --git a/src/EFCore/Metadata/IConventionNavigation.cs b/src/EFCore/Metadata/IConventionNavigation.cs index 294a81c583e..69476f8ca0a 100644 --- a/src/EFCore/Metadata/IConventionNavigation.cs +++ b/src/EFCore/Metadata/IConventionNavigation.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionNavigation : IReadOnlyNavigation, IConventionNavigationBase { /// diff --git a/src/EFCore/Metadata/IConventionNavigationBase.cs b/src/EFCore/Metadata/IConventionNavigationBase.cs index 6b7886203eb..c207af07a57 100644 --- a/src/EFCore/Metadata/IConventionNavigationBase.cs +++ b/src/EFCore/Metadata/IConventionNavigationBase.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionNavigationBase : IReadOnlyNavigationBase, IConventionPropertyBase { /// diff --git a/src/EFCore/Metadata/IConventionProperty.cs b/src/EFCore/Metadata/IConventionProperty.cs index b836b19bc63..305c61dff8b 100644 --- a/src/EFCore/Metadata/IConventionProperty.cs +++ b/src/EFCore/Metadata/IConventionProperty.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionProperty : IReadOnlyProperty, IConventionPropertyBase { /// diff --git a/src/EFCore/Metadata/IConventionPropertyBase.cs b/src/EFCore/Metadata/IConventionPropertyBase.cs index f3896959eea..ac1d067fcc6 100644 --- a/src/EFCore/Metadata/IConventionPropertyBase.cs +++ b/src/EFCore/Metadata/IConventionPropertyBase.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionPropertyBase : IReadOnlyPropertyBase, IConventionAnnotatable { /// diff --git a/src/EFCore/Metadata/IConventionServiceProperty.cs b/src/EFCore/Metadata/IConventionServiceProperty.cs index 8f328e9de15..10e04f03fe2 100644 --- a/src/EFCore/Metadata/IConventionServiceProperty.cs +++ b/src/EFCore/Metadata/IConventionServiceProperty.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionServiceProperty : IReadOnlyServiceProperty, IConventionPropertyBase { /// diff --git a/src/EFCore/Metadata/IConventionSkipNavigation.cs b/src/EFCore/Metadata/IConventionSkipNavigation.cs index f27f4f897cb..2bb4c410b84 100644 --- a/src/EFCore/Metadata/IConventionSkipNavigation.cs +++ b/src/EFCore/Metadata/IConventionSkipNavigation.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionSkipNavigation : IReadOnlySkipNavigation, IConventionNavigationBase { /// diff --git a/src/EFCore/Metadata/IConventionTypeBase.cs b/src/EFCore/Metadata/IConventionTypeBase.cs index dcf4bf9f6a4..7283e122220 100644 --- a/src/EFCore/Metadata/IConventionTypeBase.cs +++ b/src/EFCore/Metadata/IConventionTypeBase.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Model building conventions for more information. + /// public interface IConventionTypeBase : IReadOnlyTypeBase, IConventionAnnotatable { /// diff --git a/src/EFCore/Metadata/IDesignTimeModel.cs b/src/EFCore/Metadata/IDesignTimeModel.cs index f8cfab78ce0..c055ad3b867 100644 --- a/src/EFCore/Metadata/IDesignTimeModel.cs +++ b/src/EFCore/Metadata/IDesignTimeModel.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions for more information. + /// public interface IDesignTimeModel { /// diff --git a/src/EFCore/Metadata/IEntityType.cs b/src/EFCore/Metadata/IEntityType.cs index 87de3e8b25c..0769f799d0b 100644 --- a/src/EFCore/Metadata/IEntityType.cs +++ b/src/EFCore/Metadata/IEntityType.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents an entity type in a model. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IEntityType : IReadOnlyEntityType, ITypeBase { /// diff --git a/src/EFCore/Metadata/IForeignKey.cs b/src/EFCore/Metadata/IForeignKey.cs index 645e3992506..6d38e91accf 100644 --- a/src/EFCore/Metadata/IForeignKey.cs +++ b/src/EFCore/Metadata/IForeignKey.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a relationship where a foreign key composed of properties on the dependent entity type /// references a corresponding primary or alternate key on the principal entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IForeignKey : IReadOnlyForeignKey, IAnnotatable { /// diff --git a/src/EFCore/Metadata/IIndex.cs b/src/EFCore/Metadata/IIndex.cs index 0531e4dd56f..71c70a14b82 100644 --- a/src/EFCore/Metadata/IIndex.cs +++ b/src/EFCore/Metadata/IIndex.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents an index on a set of properties. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IIndex : IReadOnlyIndex, IAnnotatable { /// diff --git a/src/EFCore/Metadata/IKey.cs b/src/EFCore/Metadata/IKey.cs index bf5d9c0bf8c..4ad1393026d 100644 --- a/src/EFCore/Metadata/IKey.cs +++ b/src/EFCore/Metadata/IKey.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a primary or alternate key on an entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IKey : IReadOnlyKey, IAnnotatable { /// diff --git a/src/EFCore/Metadata/IMetadataReference.cs b/src/EFCore/Metadata/IMetadataReference.cs index 01812aa8957..ccac5864070 100644 --- a/src/EFCore/Metadata/IMetadataReference.cs +++ b/src/EFCore/Metadata/IMetadataReference.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a reference to a metadata object. If the metadata object instance is replaced /// this will be updated with the new object. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The metadata type public interface IMetadataReference : IDisposable { diff --git a/src/EFCore/Metadata/IModel.cs b/src/EFCore/Metadata/IModel.cs index cbbf6378d9f..c65afd13c43 100644 --- a/src/EFCore/Metadata/IModel.cs +++ b/src/EFCore/Metadata/IModel.cs @@ -10,7 +10,6 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -30,6 +29,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// The implementation does not need to be thread-safe. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IModel : IReadOnlyModel, IAnnotatable { /// @@ -37,6 +39,9 @@ public interface IModel : IReadOnlyModel, IAnnotatable /// or the given CLR type is being used by shared type entity type /// or the entity type has a defining navigation. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The name of the entity type to find. /// The entity type, or if none is found. new IEntityType? FindEntityType(string name); @@ -45,6 +50,9 @@ public interface IModel : IReadOnlyModel, IAnnotatable /// Gets the entity type for the given name, defining navigation name /// and the defining entity type. Returns if no matching entity type is found. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The name of the entity type to find. /// The defining navigation of the entity type to find. /// The defining entity type of the entity type to find. @@ -60,6 +68,9 @@ public interface IModel : IReadOnlyModel, IAnnotatable /// or the given CLR type is being used by shared type entity type /// or the entity type has a defining navigation. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type to find the corresponding entity type for. /// The entity type, or if none is found. IEntityType? FindRuntimeEntityType(Type type) @@ -75,6 +86,9 @@ public interface IModel : IReadOnlyModel, IAnnotatable /// /// Gets all entity types defined in the model. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// All entity types defined in the model. new IEnumerable GetEntityTypes(); @@ -107,6 +121,9 @@ RuntimeModelDependencies GetModelDependencies() /// the given CLR type is found or the given CLR type is being used by shared type entity type /// or the entity type has a defining navigation. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type to find the corresponding entity type for. /// The entity type, or if none is found. new IEntityType? FindEntityType(Type type); @@ -115,6 +132,9 @@ RuntimeModelDependencies GetModelDependencies() /// Gets the entity type for the given name, defining navigation name /// and the defining entity type. Returns if no matching entity type is found. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the entity type to find. /// The defining navigation of the entity type to find. /// The defining entity type of the entity type to find. @@ -128,6 +148,9 @@ RuntimeModelDependencies GetModelDependencies() /// /// Gets the entity types matching the given type. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the entity type to find. /// The entity types found. [DebuggerStepThrough] @@ -136,6 +159,9 @@ RuntimeModelDependencies GetModelDependencies() /// /// Returns the entity types corresponding to the least derived types from the given. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The base type. /// An optional condition for filtering entity types. /// List of entity types corresponding to the least derived types from the given. @@ -148,18 +174,27 @@ RuntimeModelDependencies GetModelDependencies() /// /// Gets a value indicating whether the given reprensents an indexer access. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The to check. bool IsIndexerMethod(MethodInfo methodInfo); /// /// Gets all the pre-convention configurations. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The pre-convention configurations. IEnumerable GetTypeMappingConfigurations(); /// /// Finds the pre-convention configuration for a given scalar . /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The CLR type. /// The pre-convention configuration or if none is found. ITypeMappingConfiguration? FindTypeMappingConfiguration(Type scalarType); diff --git a/src/EFCore/Metadata/IMutableAnnotatable.cs b/src/EFCore/Metadata/IMutableAnnotatable.cs index d57643f2251..01e593d1ddf 100644 --- a/src/EFCore/Metadata/IMutableAnnotatable.cs +++ b/src/EFCore/Metadata/IMutableAnnotatable.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// not used in application code. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableAnnotatable : IReadOnlyAnnotatable { /// diff --git a/src/EFCore/Metadata/IMutableEntityType.cs b/src/EFCore/Metadata/IMutableEntityType.cs index 60243354ff9..a984f51ba3c 100644 --- a/src/EFCore/Metadata/IMutableEntityType.cs +++ b/src/EFCore/Metadata/IMutableEntityType.cs @@ -22,6 +22,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableEntityType : IReadOnlyEntityType, IMutableTypeBase { /// diff --git a/src/EFCore/Metadata/IMutableForeignKey.cs b/src/EFCore/Metadata/IMutableForeignKey.cs index 652c7c992b1..8100970761b 100644 --- a/src/EFCore/Metadata/IMutableForeignKey.cs +++ b/src/EFCore/Metadata/IMutableForeignKey.cs @@ -18,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableForeignKey : IReadOnlyForeignKey, IMutableAnnotatable { /// diff --git a/src/EFCore/Metadata/IMutableIndex.cs b/src/EFCore/Metadata/IMutableIndex.cs index b6b2f0dabd7..75e6ee16c2e 100644 --- a/src/EFCore/Metadata/IMutableIndex.cs +++ b/src/EFCore/Metadata/IMutableIndex.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableIndex : IReadOnlyIndex, IMutableAnnotatable { /// diff --git a/src/EFCore/Metadata/IMutableKey.cs b/src/EFCore/Metadata/IMutableKey.cs index 4ae7c0b6b1f..7aa7d13f279 100644 --- a/src/EFCore/Metadata/IMutableKey.cs +++ b/src/EFCore/Metadata/IMutableKey.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableKey : IReadOnlyKey, IMutableAnnotatable { /// diff --git a/src/EFCore/Metadata/IMutableModel.cs b/src/EFCore/Metadata/IMutableModel.cs index 35023980e65..0607efa83ee 100644 --- a/src/EFCore/Metadata/IMutableModel.cs +++ b/src/EFCore/Metadata/IMutableModel.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableModel : IReadOnlyModel, IMutableAnnotatable { /// diff --git a/src/EFCore/Metadata/IMutableNavigation.cs b/src/EFCore/Metadata/IMutableNavigation.cs index 287d898e955..2fd0802de38 100644 --- a/src/EFCore/Metadata/IMutableNavigation.cs +++ b/src/EFCore/Metadata/IMutableNavigation.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableNavigation : IReadOnlyNavigation, IMutableNavigationBase { /// diff --git a/src/EFCore/Metadata/IMutableNavigationBase.cs b/src/EFCore/Metadata/IMutableNavigationBase.cs index 06b1d7b3573..c636847a8be 100644 --- a/src/EFCore/Metadata/IMutableNavigationBase.cs +++ b/src/EFCore/Metadata/IMutableNavigationBase.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableNavigationBase : IReadOnlyNavigationBase, IMutablePropertyBase { /// diff --git a/src/EFCore/Metadata/IMutableProperty.cs b/src/EFCore/Metadata/IMutableProperty.cs index cb7be02d21a..004b7371589 100644 --- a/src/EFCore/Metadata/IMutableProperty.cs +++ b/src/EFCore/Metadata/IMutableProperty.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableProperty : IReadOnlyProperty, IMutablePropertyBase { /// diff --git a/src/EFCore/Metadata/IMutablePropertyBase.cs b/src/EFCore/Metadata/IMutablePropertyBase.cs index dc85746efba..948f209b67e 100644 --- a/src/EFCore/Metadata/IMutablePropertyBase.cs +++ b/src/EFCore/Metadata/IMutablePropertyBase.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutablePropertyBase : IReadOnlyPropertyBase, IMutableAnnotatable { /// diff --git a/src/EFCore/Metadata/IMutableServiceProperty.cs b/src/EFCore/Metadata/IMutableServiceProperty.cs index 7f016fe8693..f929fd971bf 100644 --- a/src/EFCore/Metadata/IMutableServiceProperty.cs +++ b/src/EFCore/Metadata/IMutableServiceProperty.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableServiceProperty : IReadOnlyServiceProperty, IMutablePropertyBase { /// diff --git a/src/EFCore/Metadata/IMutableSkipNavigation.cs b/src/EFCore/Metadata/IMutableSkipNavigation.cs index 46130c2439e..74bcb15626f 100644 --- a/src/EFCore/Metadata/IMutableSkipNavigation.cs +++ b/src/EFCore/Metadata/IMutableSkipNavigation.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableSkipNavigation : IReadOnlySkipNavigation, IMutableNavigationBase { /// diff --git a/src/EFCore/Metadata/IMutableTypeBase.cs b/src/EFCore/Metadata/IMutableTypeBase.cs index d6a5c25eeda..bc18d3397a8 100644 --- a/src/EFCore/Metadata/IMutableTypeBase.cs +++ b/src/EFCore/Metadata/IMutableTypeBase.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Once the model is built, represents a read-only view of the same metadata. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IMutableTypeBase : IReadOnlyTypeBase, IMutableAnnotatable { /// diff --git a/src/EFCore/Metadata/INavigation.cs b/src/EFCore/Metadata/INavigation.cs index c0e181976eb..1717e5e7027 100644 --- a/src/EFCore/Metadata/INavigation.cs +++ b/src/EFCore/Metadata/INavigation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a navigation property which can be used to navigate a relationship. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface INavigation : IReadOnlyNavigation, INavigationBase { /// diff --git a/src/EFCore/Metadata/INavigationBase.cs b/src/EFCore/Metadata/INavigationBase.cs index d009986e426..74aa404a811 100644 --- a/src/EFCore/Metadata/INavigationBase.cs +++ b/src/EFCore/Metadata/INavigationBase.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a navigation property which can be used to navigate a relationship. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface INavigationBase : IReadOnlyNavigationBase, IPropertyBase { /// diff --git a/src/EFCore/Metadata/IParameterBindingFactories.cs b/src/EFCore/Metadata/IParameterBindingFactories.cs index 4eea833076d..e7ffa8a3d7e 100644 --- a/src/EFCore/Metadata/IParameterBindingFactories.cs +++ b/src/EFCore/Metadata/IParameterBindingFactories.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// This service cannot depend on services registered as . /// /// + /// + /// See Entity types with constructors for more information. + /// public interface IParameterBindingFactories { /// diff --git a/src/EFCore/Metadata/IParameterBindingFactory.cs b/src/EFCore/Metadata/IParameterBindingFactory.cs index db9b6f353c2..1252f5dbc64 100644 --- a/src/EFCore/Metadata/IParameterBindingFactory.cs +++ b/src/EFCore/Metadata/IParameterBindingFactory.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// This service cannot depend on services registered as . /// /// + /// + /// See Entity types with constructors for more information. + /// public interface IParameterBindingFactory { /// diff --git a/src/EFCore/Metadata/IProperty.cs b/src/EFCore/Metadata/IProperty.cs index 47ed5c0b2c8..3e5ac4ac255 100644 --- a/src/EFCore/Metadata/IProperty.cs +++ b/src/EFCore/Metadata/IProperty.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a scalar property of an entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IProperty : IReadOnlyProperty, IPropertyBase { /// diff --git a/src/EFCore/Metadata/IPropertyBase.cs b/src/EFCore/Metadata/IPropertyBase.cs index 24fa42eceb6..5a6802bfb61 100644 --- a/src/EFCore/Metadata/IPropertyBase.cs +++ b/src/EFCore/Metadata/IPropertyBase.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Base interface for navigations and properties. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IPropertyBase : IReadOnlyPropertyBase, IAnnotatable { /// diff --git a/src/EFCore/Metadata/IPropertyParameterBindingFactory.cs b/src/EFCore/Metadata/IPropertyParameterBindingFactory.cs index 823dd77d7ab..ae8adfc8b21 100644 --- a/src/EFCore/Metadata/IPropertyParameterBindingFactory.cs +++ b/src/EFCore/Metadata/IPropertyParameterBindingFactory.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// This service cannot depend on services registered as . /// /// + /// + /// See Entity types with constructors for more information. + /// public interface IPropertyParameterBindingFactory { /// diff --git a/src/EFCore/Metadata/IReadOnlyEntityType.cs b/src/EFCore/Metadata/IReadOnlyEntityType.cs index 2a0ec6b7436..c7196b89aff 100644 --- a/src/EFCore/Metadata/IReadOnlyEntityType.cs +++ b/src/EFCore/Metadata/IReadOnlyEntityType.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents an entity type in a model. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyEntityType : IReadOnlyTypeBase { /// diff --git a/src/EFCore/Metadata/IReadOnlyForeignKey.cs b/src/EFCore/Metadata/IReadOnlyForeignKey.cs index 0165085a6f5..407932a436c 100644 --- a/src/EFCore/Metadata/IReadOnlyForeignKey.cs +++ b/src/EFCore/Metadata/IReadOnlyForeignKey.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a relationship where a foreign key composed of properties on the dependent entity type /// references a corresponding primary or alternate key on the principal entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyForeignKey : IReadOnlyAnnotatable { /// diff --git a/src/EFCore/Metadata/IReadOnlyIndex.cs b/src/EFCore/Metadata/IReadOnlyIndex.cs index ca769009c20..00f732c578c 100644 --- a/src/EFCore/Metadata/IReadOnlyIndex.cs +++ b/src/EFCore/Metadata/IReadOnlyIndex.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents an index on a set of properties. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyIndex : IReadOnlyAnnotatable { /// diff --git a/src/EFCore/Metadata/IReadOnlyKey.cs b/src/EFCore/Metadata/IReadOnlyKey.cs index af9b7b42a1e..c72d8f4bae5 100644 --- a/src/EFCore/Metadata/IReadOnlyKey.cs +++ b/src/EFCore/Metadata/IReadOnlyKey.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a primary or alternate key on an entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyKey : IReadOnlyAnnotatable { /// diff --git a/src/EFCore/Metadata/IReadOnlyModel.cs b/src/EFCore/Metadata/IReadOnlyModel.cs index cf6a49343d1..f87df556a26 100644 --- a/src/EFCore/Metadata/IReadOnlyModel.cs +++ b/src/EFCore/Metadata/IReadOnlyModel.cs @@ -16,12 +16,18 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// the database. A model is typically created by overriding the /// method on a derived . /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyModel : IReadOnlyAnnotatable { /// /// Gets the default change tracking strategy being used for entities in the model. This strategy indicates how the /// context detects changes to properties for an instance of an entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The change tracking strategy. ChangeTrackingStrategy GetChangeTrackingStrategy(); @@ -35,6 +41,9 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// be used for any property for which no override has been specified. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The access mode being used. [DebuggerStepThrough] PropertyAccessMode GetPropertyAccessMode(); @@ -42,12 +51,18 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// /// Gets the EF Core assembly version used to build this model. /// + /// + /// See Modeling entity types and relationships for more information. + /// string? GetProductVersion() => this[CoreAnnotationNames.ProductVersion] as string; /// /// Gets a value indicating whether the CLR type is used by shared type entities in the model. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The CLR type. /// Whether the CLR type is used by shared type entities in the model. bool IsShared(Type type); @@ -55,6 +70,9 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// /// Gets all entity types defined in the model. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// All entity types defined in the model. IEnumerable GetEntityTypes(); @@ -63,6 +81,9 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// or the given CLR type is being used by shared type entity type /// or the entity type has a defining navigation. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The name of the entity type to find. /// The entity type, or if none is found. IReadOnlyEntityType? FindEntityType(string name); @@ -71,6 +92,9 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// Gets the entity type for the given base name, defining navigation name /// and the defining entity type. Returns if no matching entity type is found. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The name of the entity type to find. /// The defining navigation of the entity type to find. /// The defining entity type of the entity type to find. @@ -85,6 +109,9 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// the given CLR type is found or the given CLR type is being used by shared type entity type /// or the entity type has a defining navigation. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type to find the corresponding entity type for. /// The entity type, or if none is found. IReadOnlyEntityType? FindEntityType(Type type); @@ -93,6 +120,9 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// Gets the entity type for the given type, defining navigation name /// and the defining entity type. Returns if no matching entity type is found. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the entity type to find. /// The defining navigation of the entity type to find. /// The defining entity type of the entity type to find. @@ -105,6 +135,9 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// /// Gets the entity types matching the given type. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the entity type to find. /// The entity types found. IEnumerable FindEntityTypes(Type type); @@ -112,6 +145,9 @@ public interface IReadOnlyModel : IReadOnlyAnnotatable /// /// Returns the entity types corresponding to the least derived types from the given. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The base type. /// An optional condition for filtering entity types. /// List of entity types corresponding to the least derived types from the given. @@ -171,6 +207,10 @@ private static int GetDerivedLevel(Type? derivedType, Dictionary deri /// It is designed for debugging only and may change arbitrarily between releases. /// /// + /// + /// See Modeling entity types and relationships and + /// EF Core debug views for more information. + /// /// Options for generating the string. /// The number of indent spaces to use before each new line. /// A human-readable representation. diff --git a/src/EFCore/Metadata/IReadOnlyNavigation.cs b/src/EFCore/Metadata/IReadOnlyNavigation.cs index 561ad7100a5..bc3136096b1 100644 --- a/src/EFCore/Metadata/IReadOnlyNavigation.cs +++ b/src/EFCore/Metadata/IReadOnlyNavigation.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a navigation property which can be used to navigate a relationship. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyNavigation : IReadOnlyNavigationBase { /// diff --git a/src/EFCore/Metadata/IReadOnlyNavigationBase.cs b/src/EFCore/Metadata/IReadOnlyNavigationBase.cs index 36df11637f0..c93804aa668 100644 --- a/src/EFCore/Metadata/IReadOnlyNavigationBase.cs +++ b/src/EFCore/Metadata/IReadOnlyNavigationBase.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a navigation property which can be used to navigate a relationship. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyNavigationBase : IReadOnlyPropertyBase { /// diff --git a/src/EFCore/Metadata/IReadOnlyProperty.cs b/src/EFCore/Metadata/IReadOnlyProperty.cs index fcfa8d90a4f..2c537139e0e 100644 --- a/src/EFCore/Metadata/IReadOnlyProperty.cs +++ b/src/EFCore/Metadata/IReadOnlyProperty.cs @@ -11,7 +11,6 @@ using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.EntityFrameworkCore.ValueGeneration; namespace Microsoft.EntityFrameworkCore.Metadata @@ -19,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a scalar property of an entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyProperty : IReadOnlyPropertyBase { /// diff --git a/src/EFCore/Metadata/IReadOnlyPropertyBase.cs b/src/EFCore/Metadata/IReadOnlyPropertyBase.cs index 82051adf878..741b33d24c2 100644 --- a/src/EFCore/Metadata/IReadOnlyPropertyBase.cs +++ b/src/EFCore/Metadata/IReadOnlyPropertyBase.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Base type for navigations and properties. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyPropertyBase : IReadOnlyAnnotatable { /// diff --git a/src/EFCore/Metadata/IReadOnlyServiceProperty.cs b/src/EFCore/Metadata/IReadOnlyServiceProperty.cs index 7e8592248ad..335e515215a 100644 --- a/src/EFCore/Metadata/IReadOnlyServiceProperty.cs +++ b/src/EFCore/Metadata/IReadOnlyServiceProperty.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a property on an entity type that represents an /// injected service from the . /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyServiceProperty : IReadOnlyPropertyBase { /// diff --git a/src/EFCore/Metadata/IReadOnlySkipNavigation.cs b/src/EFCore/Metadata/IReadOnlySkipNavigation.cs index ab53d0148ec..d57a6c84442 100644 --- a/src/EFCore/Metadata/IReadOnlySkipNavigation.cs +++ b/src/EFCore/Metadata/IReadOnlySkipNavigation.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a navigation property that is part of a relationship /// that is forwarded through a third entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlySkipNavigation : IReadOnlyNavigationBase { /// diff --git a/src/EFCore/Metadata/IReadOnlyTypeBase.cs b/src/EFCore/Metadata/IReadOnlyTypeBase.cs index cea5f69444d..484c487d173 100644 --- a/src/EFCore/Metadata/IReadOnlyTypeBase.cs +++ b/src/EFCore/Metadata/IReadOnlyTypeBase.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a type in the model. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IReadOnlyTypeBase : IReadOnlyAnnotatable { /// diff --git a/src/EFCore/Metadata/IServiceProperty.cs b/src/EFCore/Metadata/IServiceProperty.cs index 34cb2ce79b8..4e02855f093 100644 --- a/src/EFCore/Metadata/IServiceProperty.cs +++ b/src/EFCore/Metadata/IServiceProperty.cs @@ -7,6 +7,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a property on an entity type that represents an /// injected service from the . /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IServiceProperty : IReadOnlyServiceProperty, IPropertyBase { /// diff --git a/src/EFCore/Metadata/ISkipNavigation.cs b/src/EFCore/Metadata/ISkipNavigation.cs index a1689837033..7cae9fffe35 100644 --- a/src/EFCore/Metadata/ISkipNavigation.cs +++ b/src/EFCore/Metadata/ISkipNavigation.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a navigation property that is part of a relationship /// that is forwarded through a third entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface ISkipNavigation : IReadOnlySkipNavigation, INavigationBase { /// diff --git a/src/EFCore/Metadata/ITypeBase.cs b/src/EFCore/Metadata/ITypeBase.cs index 2fc0540ac32..66cec090fe8 100644 --- a/src/EFCore/Metadata/ITypeBase.cs +++ b/src/EFCore/Metadata/ITypeBase.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a type in the model. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface ITypeBase : IReadOnlyTypeBase, IAnnotatable { /// diff --git a/src/EFCore/Metadata/ITypeMappingConfiguration.cs b/src/EFCore/Metadata/ITypeMappingConfiguration.cs index 29929ab7828..729be9285fc 100644 --- a/src/EFCore/Metadata/ITypeMappingConfiguration.cs +++ b/src/EFCore/Metadata/ITypeMappingConfiguration.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents the configuration for a scalar type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface ITypeMappingConfiguration : IAnnotatable { /// diff --git a/src/EFCore/Metadata/IndexComparer.cs b/src/EFCore/Metadata/IndexComparer.cs index 542093fee6e..80daa3da51d 100644 --- a/src/EFCore/Metadata/IndexComparer.cs +++ b/src/EFCore/Metadata/IndexComparer.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions for more information. + /// public sealed class IndexComparer : IEqualityComparer, IComparer { private IndexComparer() diff --git a/src/EFCore/Metadata/InstantiationBinding.cs b/src/EFCore/Metadata/InstantiationBinding.cs index 461c5128733..e3c5dc9f2f8 100644 --- a/src/EFCore/Metadata/InstantiationBinding.cs +++ b/src/EFCore/Metadata/InstantiationBinding.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Defines how to create an entity instance through the binding of EF model properties to, for /// example, constructor parameters or parameters of a factory method. /// + /// + /// See Entity types with constructors for more information. + /// public abstract class InstantiationBinding { /// diff --git a/src/EFCore/Metadata/KeyComparer.cs b/src/EFCore/Metadata/KeyComparer.cs index a4000fa5d9a..34b8dee3507 100644 --- a/src/EFCore/Metadata/KeyComparer.cs +++ b/src/EFCore/Metadata/KeyComparer.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions for more information. + /// public sealed class KeyComparer : IEqualityComparer, IComparer { private KeyComparer() diff --git a/src/EFCore/Metadata/LazyLoaderParameterBindingFactory.cs b/src/EFCore/Metadata/LazyLoaderParameterBindingFactory.cs index 0787fb35aca..713082c19c4 100644 --- a/src/EFCore/Metadata/LazyLoaderParameterBindingFactory.cs +++ b/src/EFCore/Metadata/LazyLoaderParameterBindingFactory.cs @@ -23,6 +23,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// This service cannot depend on services registered as . /// /// + /// + /// See Entity types with constructors for more information. + /// public class LazyLoaderParameterBindingFactory : ServiceParameterBindingFactory { private static readonly MethodInfo _loadMethod = typeof(ILazyLoader).GetMethod(nameof(ILazyLoader.Load))!; diff --git a/src/EFCore/Metadata/MemberIdentity.cs b/src/EFCore/Metadata/MemberIdentity.cs index 6f371488297..9934a1e83e9 100644 --- a/src/EFCore/Metadata/MemberIdentity.cs +++ b/src/EFCore/Metadata/MemberIdentity.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents the identity of an entity type member, can be based on or just the name. /// + /// + /// See Modeling entity types and relationships for more information. + /// [DebuggerDisplay("{DebuggerDisplay(),nq}")] public readonly struct MemberIdentity : IEquatable { diff --git a/src/EFCore/Metadata/ObjectArrayParameterBinding.cs b/src/EFCore/Metadata/ObjectArrayParameterBinding.cs index 8ff6284590a..2c276f65350 100644 --- a/src/EFCore/Metadata/ObjectArrayParameterBinding.cs +++ b/src/EFCore/Metadata/ObjectArrayParameterBinding.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// a new array of objects suitable for passing to a general purpose factory method such as is often used for /// creating proxies. /// + /// + /// See Entity types with constructors for more information. + /// public class ObjectArrayParameterBinding : ParameterBinding { private readonly IReadOnlyList _bindings; diff --git a/src/EFCore/Metadata/ParameterBinding.cs b/src/EFCore/Metadata/ParameterBinding.cs index babd243ddde..212e6026310 100644 --- a/src/EFCore/Metadata/ParameterBinding.cs +++ b/src/EFCore/Metadata/ParameterBinding.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Describes the binding from one or many EF model properties, dependency injection services, or metadata types to /// a parameter in a constructor, factory method, or similar. /// + /// + /// See Entity types with constructors for more information. + /// public abstract class ParameterBinding { /// diff --git a/src/EFCore/Metadata/ParameterBindingInfo.cs b/src/EFCore/Metadata/ParameterBindingInfo.cs index 825e91e8466..93d071d84dc 100644 --- a/src/EFCore/Metadata/ParameterBindingInfo.cs +++ b/src/EFCore/Metadata/ParameterBindingInfo.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Carries information about a parameter binding. /// + /// + /// See Entity types with constructors for more information. + /// public readonly struct ParameterBindingInfo { /// diff --git a/src/EFCore/Metadata/PropertyParameterBinding.cs b/src/EFCore/Metadata/PropertyParameterBinding.cs index 8ee935eff08..34d6c8c4097 100644 --- a/src/EFCore/Metadata/PropertyParameterBinding.cs +++ b/src/EFCore/Metadata/PropertyParameterBinding.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Describes the binding from an to a parameter in a constructor, factory method, /// or similar. /// + /// + /// See Entity types with constructors for more information. + /// public class PropertyParameterBinding : ParameterBinding { /// diff --git a/src/EFCore/Metadata/PropertySaveBehavior.cs b/src/EFCore/Metadata/PropertySaveBehavior.cs index 92775de7d68..126f954fe56 100644 --- a/src/EFCore/Metadata/PropertySaveBehavior.cs +++ b/src/EFCore/Metadata/PropertySaveBehavior.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Used with and /// /// + /// + /// See Modeling entity types and relationships and + /// Saving data in EF Core for more information. + /// public enum PropertySaveBehavior { /// diff --git a/src/EFCore/Metadata/RuntimeEntityType.cs b/src/EFCore/Metadata/RuntimeEntityType.cs index 8deb055cd59..f260b51799b 100644 --- a/src/EFCore/Metadata/RuntimeEntityType.cs +++ b/src/EFCore/Metadata/RuntimeEntityType.cs @@ -22,6 +22,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents an entity type in a model. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeEntityType : AnnotatableBase, IRuntimeEntityType { private readonly List _foreignKeys = new(); diff --git a/src/EFCore/Metadata/RuntimeForeignKey.cs b/src/EFCore/Metadata/RuntimeForeignKey.cs index f70c4d37ad5..041ede800ae 100644 --- a/src/EFCore/Metadata/RuntimeForeignKey.cs +++ b/src/EFCore/Metadata/RuntimeForeignKey.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a relationship where a foreign key composed of properties on the dependent entity type /// references a corresponding primary or alternate key on the principal entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeForeignKey : AnnotatableBase, IRuntimeForeignKey { private readonly DeleteBehavior _deleteBehavior; diff --git a/src/EFCore/Metadata/RuntimeIndex.cs b/src/EFCore/Metadata/RuntimeIndex.cs index 27527a02522..3f2b98f27ee 100644 --- a/src/EFCore/Metadata/RuntimeIndex.cs +++ b/src/EFCore/Metadata/RuntimeIndex.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents an index on a set of properties. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeIndex : AnnotatableBase, IIndex { private readonly bool _isUnique; diff --git a/src/EFCore/Metadata/RuntimeKey.cs b/src/EFCore/Metadata/RuntimeKey.cs index df63fb73ffc..888b1ca76b9 100644 --- a/src/EFCore/Metadata/RuntimeKey.cs +++ b/src/EFCore/Metadata/RuntimeKey.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a primary or alternate key on an entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeKey : AnnotatableBase, IRuntimeKey { // Warning: Never access these fields directly as access needs to be thread-safe diff --git a/src/EFCore/Metadata/RuntimeModel.cs b/src/EFCore/Metadata/RuntimeModel.cs index 5605f197e3d..d018b88ee30 100644 --- a/src/EFCore/Metadata/RuntimeModel.cs +++ b/src/EFCore/Metadata/RuntimeModel.cs @@ -27,6 +27,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// This is a light-weight implementation that is constructed from a built model and is not meant to be used at design-time. /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeModel : AnnotatableBase, IRuntimeModel { private readonly SortedDictionary _entityTypes = new(StringComparer.Ordinal); diff --git a/src/EFCore/Metadata/RuntimeNavigation.cs b/src/EFCore/Metadata/RuntimeNavigation.cs index a9fea007dbf..1a2e34420db 100644 --- a/src/EFCore/Metadata/RuntimeNavigation.cs +++ b/src/EFCore/Metadata/RuntimeNavigation.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a navigation property which can be used to navigate a relationship. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeNavigation : RuntimePropertyBase, INavigation { // Warning: Never access these fields directly as access needs to be thread-safe diff --git a/src/EFCore/Metadata/RuntimeProperty.cs b/src/EFCore/Metadata/RuntimeProperty.cs index 71453413b45..bd3e91e1f34 100644 --- a/src/EFCore/Metadata/RuntimeProperty.cs +++ b/src/EFCore/Metadata/RuntimeProperty.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a scalar property of an entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeProperty : RuntimePropertyBase, IProperty { private readonly bool _isNullable; diff --git a/src/EFCore/Metadata/RuntimePropertyBase.cs b/src/EFCore/Metadata/RuntimePropertyBase.cs index fe340f7d119..406e06ab77c 100644 --- a/src/EFCore/Metadata/RuntimePropertyBase.cs +++ b/src/EFCore/Metadata/RuntimePropertyBase.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Base type for navigations and properties. /// + /// + /// See Modeling entity types and relationships for more information. + /// public abstract class RuntimePropertyBase : AnnotatableBase, IRuntimePropertyBase { private readonly PropertyInfo? _propertyInfo; diff --git a/src/EFCore/Metadata/RuntimeServiceProperty.cs b/src/EFCore/Metadata/RuntimeServiceProperty.cs index f5093d65af0..c71da49fc7d 100644 --- a/src/EFCore/Metadata/RuntimeServiceProperty.cs +++ b/src/EFCore/Metadata/RuntimeServiceProperty.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a property on an entity type that represents an /// injected service from the . /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeServiceProperty : RuntimePropertyBase, IServiceProperty { private ServiceParameterBinding? _parameterBinding; diff --git a/src/EFCore/Metadata/RuntimeSkipNavigation.cs b/src/EFCore/Metadata/RuntimeSkipNavigation.cs index 3d49c57ac1a..bcca18725bb 100644 --- a/src/EFCore/Metadata/RuntimeSkipNavigation.cs +++ b/src/EFCore/Metadata/RuntimeSkipNavigation.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a navigation property that is part of a relationship /// that is forwarded through a third entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeSkipNavigation : RuntimePropertyBase, IRuntimeSkipNavigation { private readonly RuntimeForeignKey _foreignKey; diff --git a/src/EFCore/Metadata/RuntimeTypeMappingConfiguration.cs b/src/EFCore/Metadata/RuntimeTypeMappingConfiguration.cs index a32bf8b86b4..bd271327b3d 100644 --- a/src/EFCore/Metadata/RuntimeTypeMappingConfiguration.cs +++ b/src/EFCore/Metadata/RuntimeTypeMappingConfiguration.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents scalar type configuration. /// + /// + /// See Modeling entity types and relationships for more information. + /// public sealed class RuntimeTypeMappingConfiguration : AnnotatableBase, ITypeMappingConfiguration { private readonly ValueConverter? _valueConverter; diff --git a/src/EFCore/Metadata/ServiceParameterBinding.cs b/src/EFCore/Metadata/ServiceParameterBinding.cs index 604d5eaaad9..58f55f31cef 100644 --- a/src/EFCore/Metadata/ServiceParameterBinding.cs +++ b/src/EFCore/Metadata/ServiceParameterBinding.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// may not also have and associated , to a parameter in /// a constructor, factory method, or similar. /// + /// + /// See Entity types with constructors for more information. + /// public abstract class ServiceParameterBinding : ParameterBinding { private Func? _serviceDelegate; diff --git a/src/EFCore/Metadata/ServiceParameterBindingFactory.cs b/src/EFCore/Metadata/ServiceParameterBindingFactory.cs index 35560f9033c..7c3ad0b6095 100644 --- a/src/EFCore/Metadata/ServiceParameterBindingFactory.cs +++ b/src/EFCore/Metadata/ServiceParameterBindingFactory.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// This service cannot depend on services registered as . /// /// + /// + /// See Entity types with constructors for more information. + /// public class ServiceParameterBindingFactory : IParameterBindingFactory { private readonly Type _serviceType; diff --git a/src/EFCore/Metadata/SimpleModelFactory.cs b/src/EFCore/Metadata/SimpleModelFactory.cs index 733f48f75a1..85a657d155b 100644 --- a/src/EFCore/Metadata/SimpleModelFactory.cs +++ b/src/EFCore/Metadata/SimpleModelFactory.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// directly is much easier. /// /// + /// + /// See Implementation of database providers and extensions for more information. + /// public class SimpleModelFactory { /// diff --git a/src/EFCore/Metadata/ValueGenerated.cs b/src/EFCore/Metadata/ValueGenerated.cs index bbe8edd183c..2ebc3de2f3b 100644 --- a/src/EFCore/Metadata/ValueGenerated.cs +++ b/src/EFCore/Metadata/ValueGenerated.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// See for more details. /// /// + /// + /// See Modeling entity types and relationships and + /// See Value generation in EF Core for more information. + /// [Flags] public enum ValueGenerated { diff --git a/src/EFCore/Query/CollectionShaperExpression.cs b/src/EFCore/Query/CollectionShaperExpression.cs index 86df28a5042..fb66c8690bd 100644 --- a/src/EFCore/Query/CollectionShaperExpression.cs +++ b/src/EFCore/Query/CollectionShaperExpression.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// [Obsolete("Use provider specific expressions for collection results.")] public class CollectionShaperExpression : Expression, IPrintableExpression { diff --git a/src/EFCore/Query/CompiledQueryCacheKeyGenerator.cs b/src/EFCore/Query/CompiledQueryCacheKeyGenerator.cs index 58945ed618a..d68b00261d3 100644 --- a/src/EFCore/Query/CompiledQueryCacheKeyGenerator.cs +++ b/src/EFCore/Query/CompiledQueryCacheKeyGenerator.cs @@ -25,6 +25,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class CompiledQueryCacheKeyGenerator : ICompiledQueryCacheKeyGenerator { /// diff --git a/src/EFCore/Query/EntityShaperExpression.cs b/src/EFCore/Query/EntityShaperExpression.cs index 3b339d0fe1b..034d49d33a5 100644 --- a/src/EFCore/Query/EntityShaperExpression.cs +++ b/src/EFCore/Query/EntityShaperExpression.cs @@ -25,6 +25,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class EntityShaperExpression : Expression, IPrintableExpression { private static readonly MethodInfo _createUnableToDiscriminateException diff --git a/src/EFCore/Query/EvaluatableExpressionFilter.cs b/src/EFCore/Query/EvaluatableExpressionFilter.cs index 2f6ec9ceb1f..187c6031689 100644 --- a/src/EFCore/Query/EvaluatableExpressionFilter.cs +++ b/src/EFCore/Query/EvaluatableExpressionFilter.cs @@ -21,6 +21,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class EvaluatableExpressionFilter : IEvaluatableExpressionFilter { // This methods are non-deterministic and result varies based on time of running the query. diff --git a/src/EFCore/Query/ExpressionEqualityComparer.cs b/src/EFCore/Query/ExpressionEqualityComparer.cs index 318fabc1e64..ba529b57e06 100644 --- a/src/EFCore/Query/ExpressionEqualityComparer.cs +++ b/src/EFCore/Query/ExpressionEqualityComparer.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// /// A comparer which implements for . /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public sealed class ExpressionEqualityComparer : IEqualityComparer { /// diff --git a/src/EFCore/Query/ExpressionPrinter.cs b/src/EFCore/Query/ExpressionPrinter.cs index 4611240c333..26163167418 100644 --- a/src/EFCore/Query/ExpressionPrinter.cs +++ b/src/EFCore/Query/ExpressionPrinter.cs @@ -24,6 +24,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class ExpressionPrinter : ExpressionVisitor { private static readonly List _simpleMethods = new() diff --git a/src/EFCore/Query/GroupByShaperExpression.cs b/src/EFCore/Query/GroupByShaperExpression.cs index 5b25033b663..d096076eac1 100644 --- a/src/EFCore/Query/GroupByShaperExpression.cs +++ b/src/EFCore/Query/GroupByShaperExpression.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class GroupByShaperExpression : Expression, IPrintableExpression { /// diff --git a/src/EFCore/Query/IAsyncQueryProvider.cs b/src/EFCore/Query/IAsyncQueryProvider.cs index 1c92d44354f..de6c198f908 100644 --- a/src/EFCore/Query/IAsyncQueryProvider.cs +++ b/src/EFCore/Query/IAsyncQueryProvider.cs @@ -19,6 +19,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IAsyncQueryProvider : IQueryProvider { /// diff --git a/src/EFCore/Query/ICompiledQueryCacheKeyGenerator.cs b/src/EFCore/Query/ICompiledQueryCacheKeyGenerator.cs index be8f8df805a..be8cc51fcb6 100644 --- a/src/EFCore/Query/ICompiledQueryCacheKeyGenerator.cs +++ b/src/EFCore/Query/ICompiledQueryCacheKeyGenerator.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface ICompiledQueryCacheKeyGenerator { /// diff --git a/src/EFCore/Query/IEntityMaterializerSource.cs b/src/EFCore/Query/IEntityMaterializerSource.cs index 811fb3c9a80..fbac9571fdf 100644 --- a/src/EFCore/Query/IEntityMaterializerSource.cs +++ b/src/EFCore/Query/IEntityMaterializerSource.cs @@ -24,6 +24,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IEntityMaterializerSource { /// diff --git a/src/EFCore/Query/IEvaluatableExpressionFilter.cs b/src/EFCore/Query/IEvaluatableExpressionFilter.cs index a3d7c49432b..c7b5d49841f 100644 --- a/src/EFCore/Query/IEvaluatableExpressionFilter.cs +++ b/src/EFCore/Query/IEvaluatableExpressionFilter.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IEvaluatableExpressionFilter { /// diff --git a/src/EFCore/Query/IEvaluatableExpressionFilterPlugin.cs b/src/EFCore/Query/IEvaluatableExpressionFilterPlugin.cs index c1aad499341..db72148581f 100644 --- a/src/EFCore/Query/IEvaluatableExpressionFilterPlugin.cs +++ b/src/EFCore/Query/IEvaluatableExpressionFilterPlugin.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IEvaluatableExpressionFilterPlugin { /// diff --git a/src/EFCore/Query/IIncludableQueryable.cs b/src/EFCore/Query/IIncludableQueryable.cs index 51ad5c14740..7959aa6f530 100644 --- a/src/EFCore/Query/IIncludableQueryable.cs +++ b/src/EFCore/Query/IIncludableQueryable.cs @@ -8,6 +8,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// /// Supports queryable Include/ThenInclude chaining operators. /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// /// The entity type. /// The property type. // ReSharper disable once UnusedTypeParameter diff --git a/src/EFCore/Query/INavigationExpansionExtensibilityHelper.cs b/src/EFCore/Query/INavigationExpansionExtensibilityHelper.cs index a91a7a6fd8a..46d00ee7089 100644 --- a/src/EFCore/Query/INavigationExpansionExtensibilityHelper.cs +++ b/src/EFCore/Query/INavigationExpansionExtensibilityHelper.cs @@ -8,6 +8,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// /// Service which helps with various aspects of navigation expansion extensibility. /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface INavigationExpansionExtensibilityHelper { /// diff --git a/src/EFCore/Query/IPrintableExpression.cs b/src/EFCore/Query/IPrintableExpression.cs index e0a8e9bada4..a63e004012c 100644 --- a/src/EFCore/Query/IPrintableExpression.cs +++ b/src/EFCore/Query/IPrintableExpression.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IPrintableExpression { /// diff --git a/src/EFCore/Query/IQueryCompilationContextFactory.cs b/src/EFCore/Query/IQueryCompilationContextFactory.cs index 13d7580b64d..b87194a321b 100644 --- a/src/EFCore/Query/IQueryCompilationContextFactory.cs +++ b/src/EFCore/Query/IQueryCompilationContextFactory.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IQueryCompilationContextFactory { /// diff --git a/src/EFCore/Query/IQueryContextFactory.cs b/src/EFCore/Query/IQueryContextFactory.cs index cd45b56f21e..5493cd4fb0c 100644 --- a/src/EFCore/Query/IQueryContextFactory.cs +++ b/src/EFCore/Query/IQueryContextFactory.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IQueryContextFactory { /// diff --git a/src/EFCore/Query/IQueryTranslationPostprocessorFactory.cs b/src/EFCore/Query/IQueryTranslationPostprocessorFactory.cs index 839c241dd49..90b370770fc 100644 --- a/src/EFCore/Query/IQueryTranslationPostprocessorFactory.cs +++ b/src/EFCore/Query/IQueryTranslationPostprocessorFactory.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IQueryTranslationPostprocessorFactory { /// diff --git a/src/EFCore/Query/IQueryTranslationPreprocessorFactory.cs b/src/EFCore/Query/IQueryTranslationPreprocessorFactory.cs index 7e5ace75815..64438453ba5 100644 --- a/src/EFCore/Query/IQueryTranslationPreprocessorFactory.cs +++ b/src/EFCore/Query/IQueryTranslationPreprocessorFactory.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IQueryTranslationPreprocessorFactory { /// diff --git a/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs b/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs index 59db0d080dd..8051b9a4797 100644 --- a/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs +++ b/src/EFCore/Query/IQueryableMethodTranslatingExpressionVisitorFactory.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IQueryableMethodTranslatingExpressionVisitorFactory { /// diff --git a/src/EFCore/Query/IQueryingEnumerable.cs b/src/EFCore/Query/IQueryingEnumerable.cs index 2f4e9791ed2..e91f022f300 100644 --- a/src/EFCore/Query/IQueryingEnumerable.cs +++ b/src/EFCore/Query/IQueryingEnumerable.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IQueryingEnumerable { /// diff --git a/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs b/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs index 71a63491525..d282c8695f0 100644 --- a/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs +++ b/src/EFCore/Query/IShapedQueryCompilingExpressionVisitorFactory.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public interface IShapedQueryCompilingExpressionVisitorFactory { /// diff --git a/src/EFCore/Query/IncludeExpression.cs b/src/EFCore/Query/IncludeExpression.cs index a437d9dd7cd..f1767532177 100644 --- a/src/EFCore/Query/IncludeExpression.cs +++ b/src/EFCore/Query/IncludeExpression.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class IncludeExpression : Expression, IPrintableExpression { /// diff --git a/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs b/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs index d187a34e6fe..bccf6b662c4 100644 --- a/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs +++ b/src/EFCore/Query/MaterializeCollectionNavigationExpression.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class MaterializeCollectionNavigationExpression : Expression, IPrintableExpression { /// diff --git a/src/EFCore/Query/ProjectionBindingExpression.cs b/src/EFCore/Query/ProjectionBindingExpression.cs index f4a17f32254..b7f402a49ee 100644 --- a/src/EFCore/Query/ProjectionBindingExpression.cs +++ b/src/EFCore/Query/ProjectionBindingExpression.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class ProjectionBindingExpression : Expression, IPrintableExpression { /// diff --git a/src/EFCore/Query/ProjectionMember.cs b/src/EFCore/Query/ProjectionMember.cs index 3e3805770eb..d7046baf29e 100644 --- a/src/EFCore/Query/ProjectionMember.cs +++ b/src/EFCore/Query/ProjectionMember.cs @@ -19,6 +19,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// [DebuggerDisplay("{ToString(), nq}")] public sealed class ProjectionMember { diff --git a/src/EFCore/Query/QueryCompilationContext.cs b/src/EFCore/Query/QueryCompilationContext.cs index 03e8dd3e009..de147203fe6 100644 --- a/src/EFCore/Query/QueryCompilationContext.cs +++ b/src/EFCore/Query/QueryCompilationContext.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class QueryCompilationContext { /// diff --git a/src/EFCore/Query/QueryContext.cs b/src/EFCore/Query/QueryContext.cs index 3fce3170962..43ea5e24d75 100644 --- a/src/EFCore/Query/QueryContext.cs +++ b/src/EFCore/Query/QueryContext.cs @@ -24,6 +24,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public abstract class QueryContext : IParameterValues { private readonly IDictionary _parameterValues = new Dictionary(); diff --git a/src/EFCore/Query/QueryRootExpression.cs b/src/EFCore/Query/QueryRootExpression.cs index 43b1edf6ac7..ccda29d9a1a 100644 --- a/src/EFCore/Query/QueryRootExpression.cs +++ b/src/EFCore/Query/QueryRootExpression.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class QueryRootExpression : Expression, IPrintableExpression { /// diff --git a/src/EFCore/Query/QueryTranslationPostprocessor.cs b/src/EFCore/Query/QueryTranslationPostprocessor.cs index 18028486a81..e935f7e0be5 100644 --- a/src/EFCore/Query/QueryTranslationPostprocessor.cs +++ b/src/EFCore/Query/QueryTranslationPostprocessor.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class QueryTranslationPostprocessor { /// diff --git a/src/EFCore/Query/QueryTranslationPreprocessor.cs b/src/EFCore/Query/QueryTranslationPreprocessor.cs index cfd78e54cd5..cd13064315d 100644 --- a/src/EFCore/Query/QueryTranslationPreprocessor.cs +++ b/src/EFCore/Query/QueryTranslationPreprocessor.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class QueryTranslationPreprocessor { /// diff --git a/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs index a6086a42249..11822771f5c 100644 --- a/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public abstract class QueryableMethodTranslatingExpressionVisitor : ExpressionVisitor { private readonly bool _subquery; diff --git a/src/EFCore/Query/QueryableMethods.cs b/src/EFCore/Query/QueryableMethods.cs index bb1b81f17d4..57646806579 100644 --- a/src/EFCore/Query/QueryableMethods.cs +++ b/src/EFCore/Query/QueryableMethods.cs @@ -13,6 +13,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// /// A class that provides reflection metadata for translatable LINQ methods. /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public static class QueryableMethods { //public static MethodInfo AggregateWithoutSeed { get; } diff --git a/src/EFCore/Query/ReplacingExpressionVisitor.cs b/src/EFCore/Query/ReplacingExpressionVisitor.cs index af4e7f0405f..60fce162515 100644 --- a/src/EFCore/Query/ReplacingExpressionVisitor.cs +++ b/src/EFCore/Query/ReplacingExpressionVisitor.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class ReplacingExpressionVisitor : ExpressionVisitor { private readonly IReadOnlyList _originals; diff --git a/src/EFCore/Query/ResultCardinality.cs b/src/EFCore/Query/ResultCardinality.cs index bbe4b1f73f9..0bdd584103c 100644 --- a/src/EFCore/Query/ResultCardinality.cs +++ b/src/EFCore/Query/ResultCardinality.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public enum ResultCardinality { /// diff --git a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs index 0ead22674ef..9725cc6fe4d 100644 --- a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs @@ -35,6 +35,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public abstract class ShapedQueryCompilingExpressionVisitor : ExpressionVisitor { private static readonly PropertyInfo _cancellationTokenMemberInfo diff --git a/src/EFCore/Query/ShapedQueryExpression.cs b/src/EFCore/Query/ShapedQueryExpression.cs index 15fda5e79ad..da45afd431d 100644 --- a/src/EFCore/Query/ShapedQueryExpression.cs +++ b/src/EFCore/Query/ShapedQueryExpression.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public class ShapedQueryExpression : Expression, IPrintableExpression { /// diff --git a/src/EFCore/Query/TransparentIdentifierFactory.cs b/src/EFCore/Query/TransparentIdentifierFactory.cs index 885722d13a8..b3d15d6b28d 100644 --- a/src/EFCore/Query/TransparentIdentifierFactory.cs +++ b/src/EFCore/Query/TransparentIdentifierFactory.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Query /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// and How EF Core queries work for more information. + /// public static class TransparentIdentifierFactory { /// From 774113105ee62e6e663506ac02fcaecfa56c2eff Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Sat, 4 Sep 2021 11:48:11 -0700 Subject: [PATCH 027/346] Readd test for obsolete ToQuery Fixes #24623 --- .../CSharpRuntimeAnnotationCodeGenerator.cs | 14 ++- .../Conventions/RuntimeModelConvention.cs | 18 ++-- .../Query/QueryBugsTest.cs | 59 ------------ .../Query/RawSqlServerTest.cs | 92 +++++++++++++++++++ 4 files changed, 113 insertions(+), 70 deletions(-) create mode 100644 test/EFCore.SqlServer.FunctionalTests/Query/RawSqlServerTest.cs diff --git a/src/EFCore/Design/Internal/CSharpRuntimeAnnotationCodeGenerator.cs b/src/EFCore/Design/Internal/CSharpRuntimeAnnotationCodeGenerator.cs index c7b73d1b759..b33c6138732 100644 --- a/src/EFCore/Design/Internal/CSharpRuntimeAnnotationCodeGenerator.cs +++ b/src/EFCore/Design/Internal/CSharpRuntimeAnnotationCodeGenerator.cs @@ -64,11 +64,15 @@ public virtual void Generate(IEntityType entityType, CSharpRuntimeAnnotationCode var annotations = parameters.Annotations; if (!parameters.IsRuntime) { - annotations.Remove(CoreAnnotationNames.PropertyAccessMode); - annotations.Remove(CoreAnnotationNames.NavigationAccessMode); - annotations.Remove(CoreAnnotationNames.DiscriminatorProperty); - annotations.Remove(CoreAnnotationNames.AmbiguousNavigations); - annotations.Remove(CoreAnnotationNames.NavigationCandidates); + foreach (var annotation in annotations) + { + if (CoreAnnotationNames.AllNames.Contains(annotation.Key) + && annotation.Key != CoreAnnotationNames.DiscriminatorValue + && annotation.Key != CoreAnnotationNames.DiscriminatorMappingComplete) + { + annotations.Remove(annotation.Key); + } + } } GenerateSimpleAnnotations(parameters); diff --git a/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs b/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs index 45d4b28d644..1ce792486c9 100644 --- a/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs +++ b/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs @@ -250,11 +250,18 @@ protected virtual void ProcessEntityTypeAnnotations( { if (!runtime) { - annotations.Remove(CoreAnnotationNames.PropertyAccessMode); - annotations.Remove(CoreAnnotationNames.NavigationAccessMode); - annotations.Remove(CoreAnnotationNames.DiscriminatorProperty); - annotations.Remove(CoreAnnotationNames.AmbiguousNavigations); - annotations.Remove(CoreAnnotationNames.NavigationCandidates); +#pragma warning disable CS0612 // Type or member is obsolete + foreach (var annotation in annotations) + { + if (CoreAnnotationNames.AllNames.Contains(annotation.Key) + && annotation.Key != CoreAnnotationNames.QueryFilter + && annotation.Key != CoreAnnotationNames.DefiningQuery + && annotation.Key != CoreAnnotationNames.DiscriminatorValue + && annotation.Key != CoreAnnotationNames.DiscriminatorMappingComplete) + { + annotations.Remove(annotation.Key); + } + } if (annotations.TryGetValue(CoreAnnotationNames.QueryFilter, out var queryFilter)) { @@ -262,7 +269,6 @@ protected virtual void ProcessEntityTypeAnnotations( new QueryRootRewritingExpressionVisitor(runtimeEntityType.Model).Rewrite((Expression)queryFilter!); } -#pragma warning disable CS0612 // Type or member is obsolete if (annotations.TryGetValue(CoreAnnotationNames.DefiningQuery, out var definingQuery)) { annotations[CoreAnnotationNames.DefiningQuery] = diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs index 3997a4f7e99..549600a8076 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs @@ -3928,65 +3928,6 @@ public class AddressTurnovers13157 #endregion - #region Issue13346 - - [ConditionalFact] - public virtual async Task ToQuery_can_define_in_own_terms_using_FromSql() - { - var contextFactory = await InitializeAsync(seed: c => c.Seed()); - - using (var context = contextFactory.CreateContext()) - { - var query = context.Set().ToList(); - - Assert.Equal(4, query.Count); - - AssertSql("SELECT o.Amount From Orders AS o"); - } - } - - protected class MyContext13346 : DbContext - { - public virtual DbSet Orders { get; set; } - - public MyContext13346(DbContextOptions options) - : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .HasNoKey() - .ToSqlQuery("SELECT o.Amount From Orders AS o"); - } - - public void Seed() - { - AddRange( - new Order13346 { Amount = 1 }, - new Order13346 { Amount = 2 }, - new Order13346 { Amount = 3 }, - new Order13346 { Amount = 4 } - ); - - SaveChanges(); - } - - public class Order13346 - { - public int Id { get; set; } - public int Amount { get; set; } - } - - public class OrderSummary13346 - { - public int Amount { get; set; } - } - } - - #endregion - #region Issue13079 [ConditionalFact] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/RawSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/RawSqlServerTest.cs new file mode 100644 index 00000000000..915160a8434 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/Query/RawSqlServerTest.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; +using Xunit.Abstractions; + +// ReSharper disable InconsistentNaming +namespace Microsoft.EntityFrameworkCore.Query +{ + public class RawSqlServerTest : NonSharedModelTestBase + { + public RawSqlServerTest(ITestOutputHelper testOutputHelper) + { + //TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); + } + + // Issue #13346, #24623 + [ConditionalFact] + public virtual async Task ToQuery_can_use_FromSqlRaw() + { + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using (var context = contextFactory.CreateContext()) + { + var query = context.Set().ToList(); + + Assert.Equal(4, query.Count); + + AssertSql("SELECT o.Amount From Orders AS o -- RAW"); + } + } + + protected class MyContext13346 : DbContext + { + public virtual DbSet Orders { get; set; } + + public MyContext13346(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { +#pragma warning disable CS0618 // Type or member is obsolete + modelBuilder.Entity() + .HasNoKey() + .ToQuery(() => Set().FromSqlRaw("SELECT o.Amount From Orders AS o -- RAW")); +#pragma warning restore CS0618 // Type or member is obsolete + } + + public void Seed() + { + AddRange( + new Order13346 { Amount = 1 }, + new Order13346 { Amount = 2 }, + new Order13346 { Amount = 3 }, + new Order13346 { Amount = 4 } + ); + + SaveChanges(); + } + + public class Order13346 + { + public int Id { get; set; } + public int Amount { get; set; } + } + + public class OrderSummary13346 + { + public int Amount { get; set; } + } + } + + protected override string StoreName { get; } = "RawSqlServerTest"; + + protected TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + + protected override ITestStoreFactory TestStoreFactory + => SqlServerTestStoreFactory.Instance; + + protected void AssertSql(params string[] expected) + => TestSqlLoggerFactory.AssertBaseline(expected); + + protected void ClearLog() + => TestSqlLoggerFactory.Clear(); + } +} From f3c82b676ad78cc2bd1f7c9bc66ba7e4f60513eb Mon Sep 17 00:00:00 2001 From: maumar Date: Sat, 4 Sep 2021 00:11:29 -0700 Subject: [PATCH 028/346] Fix to #25842 - Cosmos: Translate string.Equals with StringComparison.Ordinal Fixes #25842 --- .../Query/Internal/StringMethodTranslator.cs | 13 +++++--- .../NorthwindFunctionsQueryCosmosTest.cs | 30 +++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/EFCore.Cosmos/Query/Internal/StringMethodTranslator.cs b/src/EFCore.Cosmos/Query/Internal/StringMethodTranslator.cs index 93a845ae18e..798e1633f97 100644 --- a/src/EFCore.Cosmos/Query/Internal/StringMethodTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/StringMethodTranslator.cs @@ -250,14 +250,19 @@ public StringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) || _stringComparisonWithComparisonTypeArgumentStatic.Equals(method)) { var comparisonTypeArgument = arguments[^1]; + if (comparisonTypeArgument is SqlConstantExpression constantComparisonTypeArgument && constantComparisonTypeArgument.Value is StringComparison comparisonTypeArgumentValue - && comparisonTypeArgumentValue == StringComparison.OrdinalIgnoreCase) + && (comparisonTypeArgumentValue == StringComparison.OrdinalIgnoreCase + || comparisonTypeArgumentValue == StringComparison.Ordinal)) { - return _stringComparisonWithComparisonTypeArgumentInstance.Equals(method) - ? TranslateSystemFunction("STRINGEQUALS", typeof(bool), instance!, arguments[0], _sqlExpressionFactory.Constant(true)) - : TranslateSystemFunction("STRINGEQUALS", typeof(bool), arguments[0], arguments[1], _sqlExpressionFactory.Constant(true)); + ? comparisonTypeArgumentValue == StringComparison.OrdinalIgnoreCase + ? TranslateSystemFunction("STRINGEQUALS", typeof(bool), instance!, arguments[0], _sqlExpressionFactory.Constant(true)) + : TranslateSystemFunction("STRINGEQUALS", typeof(bool), instance!, arguments[0]) + : comparisonTypeArgumentValue == StringComparison.OrdinalIgnoreCase + ? TranslateSystemFunction("STRINGEQUALS", typeof(bool), arguments[0], arguments[1], _sqlExpressionFactory.Constant(true)) + : TranslateSystemFunction("STRINGEQUALS", typeof(bool), arguments[0], arguments[1]); } } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs index 4527f2aaa7a..d7e70455d30 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs @@ -1365,6 +1365,36 @@ FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND STRINGEQUALS(c[""CustomerID""], ""alFkI"", true))"); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Case_sensitive_string_comparison_instance(bool async) + { + await AssertQuery( + async, + ss => ss.Set().Where(c => c.CustomerID.Equals("ALFKI", StringComparison.Ordinal)), + entryCount: 1); + + AssertSql( + @"SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND STRINGEQUALS(c[""CustomerID""], ""ALFKI""))"); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Case_sensitive_string_comparison_static(bool async) + { + await AssertQuery( + async, + ss => ss.Set().Where(c => string.Equals(c.CustomerID, "ALFKI", StringComparison.Ordinal)), + entryCount: 1); + + AssertSql( + @"SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND STRINGEQUALS(c[""CustomerID""], ""ALFKI""))"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); From 268bd9560d6077c3fd2721b57fe2166c0920e48e Mon Sep 17 00:00:00 2001 From: hfpt Date: Sun, 22 Aug 2021 22:53:46 -0500 Subject: [PATCH 029/346] Query: add translation for string.IndexOf(string, int) #25396 --- .../SqlServerStringMethodTranslator.cs | 102 +++++++++++------- .../Query/NorthwindFunctionsQueryTestBase.cs | 9 ++ .../NorthwindFunctionsQuerySqlServerTest.cs | 19 +++- 3 files changed, 89 insertions(+), 41 deletions(-) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index 09f1635d443..f5777c77ae7 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -24,6 +24,9 @@ public class SqlServerStringMethodTranslator : IMethodCallTranslator private static readonly MethodInfo _indexOfMethodInfo = typeof(string).GetRequiredRuntimeMethod(nameof(string.IndexOf), new[] { typeof(string) }); + private static readonly MethodInfo _indexOfMethodInfoWithStartingPosition + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IndexOf), new[] { typeof(string), typeof(int) }); + private static readonly MethodInfo _replaceMethodInfo = typeof(string).GetRequiredRuntimeMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) }); @@ -120,46 +123,12 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor { if (_indexOfMethodInfo.Equals(method)) { - var argument = arguments[0]; - var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument)!; - argument = _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping); - - SqlExpression charIndexExpression; - var storeType = stringTypeMapping.StoreType; - if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) - || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) - { - charIndexExpression = _sqlExpressionFactory.Function( - "CHARINDEX", - new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, - nullable: true, - argumentsPropagateNullability: new[] { true, true }, - typeof(long)); - - charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); - } - else - { - charIndexExpression = _sqlExpressionFactory.Function( - "CHARINDEX", - new[] { argument, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }, - nullable: true, - argumentsPropagateNullability: new[] { true, true }, - method.ReturnType); - } - - charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); + return TranslateIndexOf(instance, method, arguments[0], null); + } - return _sqlExpressionFactory.Case( - new[] - { - new CaseWhenClause( - _sqlExpressionFactory.Equal( - argument, - _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), - _sqlExpressionFactory.Constant(0)) - }, - charIndexExpression); + if (_indexOfMethodInfoWithStartingPosition.Equals(method)) + { + return TranslateIndexOf(instance, method, arguments[0], arguments[1]); } if (_replaceMethodInfo.Equals(method)) @@ -470,6 +439,61 @@ private SqlExpression TranslateStartsEndsWith(SqlExpression instance, SqlExpress pattern); } + private SqlExpression TranslateIndexOf(SqlExpression instance, MethodInfo method, SqlExpression searchExpression, SqlExpression? startIndex) + { + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, searchExpression)!; + searchExpression = _sqlExpressionFactory.ApplyTypeMapping(searchExpression, stringTypeMapping); + + SqlExpression[] charIndexArguments; + if (startIndex == null) + { + charIndexArguments = new[] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }; + } + else + { + var startIndexSql = _sqlExpressionFactory.Add(startIndex, _sqlExpressionFactory.Constant(1)); + charIndexArguments = new[] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), startIndexSql }; + } + + SqlExpression charIndexExpression; + var storeType = stringTypeMapping.StoreType; + if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) + || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) + { + charIndexExpression = _sqlExpressionFactory.Function( + "CHARINDEX", + charIndexArguments, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + typeof(long)); + + charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); + } + else + { + charIndexExpression = _sqlExpressionFactory.Function( + "CHARINDEX", + charIndexArguments, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + method.ReturnType); + } + + charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); + + return _sqlExpressionFactory.Case( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.Equal( + searchExpression, + _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), + _sqlExpressionFactory.Constant(0)) + }, + charIndexExpression); + } + + // See https://docs.microsoft.com/en-us/sql/t-sql/language-elements/like-transact-sql private bool IsLikeWildChar(char c) => c == '%' || c == '_' || c == '['; diff --git a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs index 319710d4572..c6150057b91 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs @@ -1528,6 +1528,15 @@ public virtual Task Indexof_with_emptystring(bool async) ss => ss.Set().Where(c => c.CustomerID == "ALFKI").Select(c => c.ContactName.IndexOf(string.Empty))); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Indexof_with_one_arg(bool async) + { + return AssertQueryScalar( + async, + ss => ss.Set().Where(c => c.CustomerID == "ALFKI").Select(c => c.ContactName.IndexOf("a"))); + } + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Indexof_with_starting_position(bool async) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs index 1b742e7e9a3..599edb3875b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs @@ -1498,13 +1498,28 @@ FROM [Customers] AS [c] WHERE [c].[CustomerID] = N'ALFKI'"); } - [ConditionalTheory(Skip = "issue #25396")] + public override async Task Indexof_with_one_arg(bool async) + { + await base.Indexof_with_one_arg(async); + + AssertSql( + @"SELECT CASE + WHEN N'a' = N'' THEN 0 + ELSE CAST(CHARINDEX(N'a', [c].[ContactName]) AS int) - 1 +END +FROM [Customers] AS [c] +WHERE [c].[CustomerID] = N'ALFKI'"); + } + public override async Task Indexof_with_starting_position(bool async) { await base.Indexof_with_starting_position(async); AssertSql( - @"SELECT [c].[ContactName] + @"SELECT CASE + WHEN N'a' = N'' THEN 0 + ELSE CAST(CHARINDEX(N'a', [c].[ContactName], 3 + 1) AS int) - 1 +END FROM [Customers] AS [c] WHERE [c].[CustomerID] = N'ALFKI'"); } From ef4fd39681b18a9a9c5490c9ca6acdac2141b70b Mon Sep 17 00:00:00 2001 From: hfpt Date: Sat, 28 Aug 2021 10:09:52 -0500 Subject: [PATCH 030/346] replace == null with is null --- .../Query/Internal/SqlServerStringMethodTranslator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index f5777c77ae7..56960417fa1 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -445,7 +445,7 @@ private SqlExpression TranslateIndexOf(SqlExpression instance, MethodInfo method searchExpression = _sqlExpressionFactory.ApplyTypeMapping(searchExpression, stringTypeMapping); SqlExpression[] charIndexArguments; - if (startIndex == null) + if (startIndex is null) { charIndexArguments = new[] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }; } From 6445149bdf32399a7332253b47089ea7846ae853 Mon Sep 17 00:00:00 2001 From: hfpt Date: Sun, 5 Sep 2021 22:04:21 -0500 Subject: [PATCH 031/346] Code review fixes --- .../SqlServerStringMethodTranslator.cs | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index 56960417fa1..9013783eb07 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -443,18 +443,17 @@ private SqlExpression TranslateIndexOf(SqlExpression instance, MethodInfo method { var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, searchExpression)!; searchExpression = _sqlExpressionFactory.ApplyTypeMapping(searchExpression, stringTypeMapping); + instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); - SqlExpression[] charIndexArguments; - if (startIndex is null) - { - charIndexArguments = new[] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }; - } - else + var charIndexArguments = new SqlExpression[2] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }; + + if (startIndex is not null) { - var startIndexSql = _sqlExpressionFactory.Add(startIndex, _sqlExpressionFactory.Constant(1)); - charIndexArguments = new[] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), startIndexSql }; + charIndexArguments = charIndexArguments.Append(_sqlExpressionFactory.Add(startIndex, _sqlExpressionFactory.Constant(1))).ToArray(); } + var argumentsPropagateNullability = Enumerable.Repeat(true, charIndexArguments.Length).ToArray(); + SqlExpression charIndexExpression; var storeType = stringTypeMapping.StoreType; if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) @@ -464,7 +463,7 @@ private SqlExpression TranslateIndexOf(SqlExpression instance, MethodInfo method "CHARINDEX", charIndexArguments, nullable: true, - argumentsPropagateNullability: new[] { true, true }, + argumentsPropagateNullability, typeof(long)); charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); @@ -475,7 +474,7 @@ private SqlExpression TranslateIndexOf(SqlExpression instance, MethodInfo method "CHARINDEX", charIndexArguments, nullable: true, - argumentsPropagateNullability: new[] { true, true }, + argumentsPropagateNullability, method.ReturnType); } @@ -484,11 +483,11 @@ private SqlExpression TranslateIndexOf(SqlExpression instance, MethodInfo method return _sqlExpressionFactory.Case( new[] { - new CaseWhenClause( - _sqlExpressionFactory.Equal( - searchExpression, - _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), - _sqlExpressionFactory.Constant(0)) + new CaseWhenClause( + _sqlExpressionFactory.Equal( + searchExpression, + _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), + _sqlExpressionFactory.Constant(0)) }, charIndexExpression); } From a0bb25fec68c07e7c123ffba28224548099f4ea9 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Mon, 6 Sep 2021 22:09:50 +0200 Subject: [PATCH 032/346] Add test for projected Contains(null) (#25893) Closes #19702 --- .../NorthwindAggregateOperatorsQueryCosmosTest.cs | 6 ++++++ .../Query/NorthwindAggregateOperatorsQueryTestBase.cs | 11 +++++++++++ .../NorthwindAggregateOperatorsQuerySqlServerTest.cs | 10 ++++++++++ 3 files changed, 27 insertions(+) diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs index 09075a44b51..f96336902a4 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs @@ -1398,6 +1398,12 @@ public override Task Contains_over_entityType_with_null_should_rewrite_to_false( return base.Contains_over_entityType_with_null_should_rewrite_to_false(async); } + [ConditionalTheory(Skip = "Issue#17246 (Contains over subquery is not supported)")] + public override Task Contains_over_entityType_with_null_in_projection(bool async) + { + return base.Contains_over_entityType_with_null_in_projection(async); + } + public override async Task String_FirstOrDefault_in_projection_does_not_do_client_eval(bool async) { await base.String_FirstOrDefault_in_projection_does_not_do_client_eval(async); diff --git a/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs index 693fe96d132..3cf6a34a649 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindAggregateOperatorsQueryTestBase.cs @@ -1579,6 +1579,17 @@ public virtual Task Contains_over_entityType_with_null_should_rewrite_to_identit ss => ss.Set().Where(o => ss.Set().Where(o => o.CustomerID == "VINET").Contains(null))); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Contains_over_entityType_with_null_in_projection(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where( + o => ss.Set().Where(o => o.CustomerID == "VINET") + .Contains(null))); + } + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Contains_over_scalar_with_null_should_rewrite_to_identity_equality_subquery(bool async) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs index b0d6857f651..61492642b27 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs @@ -1177,6 +1177,16 @@ FROM [Orders] AS [o] WHERE 0 = 1"); } + public override async Task Contains_over_entityType_with_null_in_projection(bool async) + { + await base.Contains_over_entityType_with_null_in_projection(async); + + AssertSql( + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM [Orders] AS [o] +WHERE 0 = 1"); + } + public override async Task Contains_over_scalar_with_null_should_rewrite_to_identity_equality_subquery(bool async) { await base.Contains_over_scalar_with_null_should_rewrite_to_identity_equality_subquery(async); From 673785d03479a75290b8483e95a069475c6123f6 Mon Sep 17 00:00:00 2001 From: hfpt Date: Mon, 6 Sep 2021 15:23:05 -0500 Subject: [PATCH 033/346] Replace Array with List (IEnumerable) to manage the dynamic params size. --- .../Query/Internal/SqlServerStringMethodTranslator.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs index 9013783eb07..b12e3880514 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerStringMethodTranslator.cs @@ -445,14 +445,14 @@ private SqlExpression TranslateIndexOf(SqlExpression instance, MethodInfo method searchExpression = _sqlExpressionFactory.ApplyTypeMapping(searchExpression, stringTypeMapping); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); - var charIndexArguments = new SqlExpression[2] { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }; + var charIndexArguments = new List { searchExpression, _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping) }; if (startIndex is not null) { - charIndexArguments = charIndexArguments.Append(_sqlExpressionFactory.Add(startIndex, _sqlExpressionFactory.Constant(1))).ToArray(); + charIndexArguments.Add(_sqlExpressionFactory.Add(startIndex, _sqlExpressionFactory.Constant(1))); } - var argumentsPropagateNullability = Enumerable.Repeat(true, charIndexArguments.Length).ToArray(); + var argumentsPropagateNullability = Enumerable.Repeat(true, charIndexArguments.Count); SqlExpression charIndexExpression; var storeType = stringTypeMapping.StoreType; From 3fe9bef6f53bc992b150b6b26017e2bd14f299c0 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Tue, 7 Sep 2021 08:46:00 -0700 Subject: [PATCH 034/346] Sort inserts to preserve tracking order in more cases. Add a test for deadlocks. Fixes #15180 Fixes #25228 --- .../Update/Internal/CommandBatchPreparer.cs | 2 +- .../Internal/ModificationCommandComparer.cs | 21 ++- .../TransactionTestBase.cs | 18 +-- .../BatchingTest.cs | 140 +++++++++++++++++- 4 files changed, 156 insertions(+), 25 deletions(-) diff --git a/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs b/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs index 6e679019454..a70dedb1688 100644 --- a/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs +++ b/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs @@ -178,7 +178,6 @@ protected virtual IEnumerable CreateModificationCo foreach (var mapping in mappings) { var table = mapping.Table; - var tableKey = (table.Name, table.Schema); IModificationCommand command; var isMainEntry = true; @@ -189,6 +188,7 @@ protected virtual IEnumerable CreateModificationCo sharedTablesCommandsMap = new Dictionary<(string, string?), SharedTableEntryMap>(); } + var tableKey = (table.Name, table.Schema); if (!sharedTablesCommandsMap.TryGetValue(tableKey, out var sharedCommandsMap)) { sharedCommandsMap = new SharedTableEntryMap(table, updateAdapter); diff --git a/src/EFCore.Relational/Update/Internal/ModificationCommandComparer.cs b/src/EFCore.Relational/Update/Internal/ModificationCommandComparer.cs index 914d7be6332..7f1fefe0a31 100644 --- a/src/EFCore.Relational/Update/Internal/ModificationCommandComparer.cs +++ b/src/EFCore.Relational/Update/Internal/ModificationCommandComparer.cs @@ -46,13 +46,13 @@ public virtual int Compare(IReadOnlyModificationCommand? x, IReadOnlyModificatio return 1; } - result = StringComparer.Ordinal.Compare(x.Schema, y.Schema); + result = StringComparer.Ordinal.Compare(x.TableName, y.TableName); if (result != 0) { return result; } - result = StringComparer.Ordinal.Compare(x.TableName, y.TableName); + result = StringComparer.Ordinal.Compare(x.Schema, y.Schema); if (result != 0) { return result; @@ -82,18 +82,15 @@ public virtual int Compare(IReadOnlyModificationCommand? x, IReadOnlyModificatio } } - if (xState != EntityState.Added) + var xKey = xEntry.EntityType.FindPrimaryKey()!; + for (var i = 0; i < xKey.Properties.Count; i++) { - var xKey = xEntry.EntityType.FindPrimaryKey()!; - for (var i = 0; i < xKey.Properties.Count; i++) - { - var xKeyProperty = xKey.Properties[i]; + var xKeyProperty = xKey.Properties[i]; - result = xKeyProperty.GetCurrentValueComparer().Compare(xEntry, yEntry); - if (result != 0) - { - return result; - } + result = xKeyProperty.GetCurrentValueComparer().Compare(xEntry, yEntry); + if (result != 0) + { + return result; } } } diff --git a/test/EFCore.Relational.Specification.Tests/TransactionTestBase.cs b/test/EFCore.Relational.Specification.Tests/TransactionTestBase.cs index f4fe9ed5d68..e1c43e6f11e 100644 --- a/test/EFCore.Relational.Specification.Tests/TransactionTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/TransactionTestBase.cs @@ -48,7 +48,7 @@ public virtual async Task SaveChanges_can_be_used_with_no_transaction(bool async context.Database.AutoTransactionsEnabled = false; context.Add( - new TransactionCustomer { Id = 77, Name = "Bobble" }); + new TransactionCustomer { Id = -77, Name = "Bobble" }); context.Entry(context.Set().OrderBy(c => c.Id).Last()).State = EntityState.Added; @@ -69,9 +69,9 @@ public virtual async Task SaveChanges_can_be_used_with_no_transaction(bool async Assert.Equal( new List { + -77, 1, 2, - 77 }, context.Set().OrderBy(c => c.Id).Select(e => e.Id).ToList()); } @@ -119,7 +119,7 @@ public virtual async Task SaveChanges_uses_enlisted_transaction(bool async, bool context.Database.AutoTransactionsEnabled = autoTransactionsEnabled; context.Add( - new TransactionCustomer { Id = 77, Name = "Bobble" }); + new TransactionCustomer { Id = -77, Name = "Bobble" }); context.Entry(context.Set().OrderBy(c => c.Id).Last()).State = EntityState.Added; @@ -151,7 +151,7 @@ public virtual async Task SaveChanges_uses_enlisted_transaction(bool async, bool if (!autoTransactionsEnabled) { using var context = CreateContext(); - context.Entry(context.Set().Single(c => c.Id == 77)).State = EntityState.Deleted; + context.Entry(context.Set().Single(c => c.Id == -77)).State = EntityState.Deleted; if (async) { @@ -275,7 +275,7 @@ public virtual async Task SaveChanges_uses_ambient_transaction(bool async, bool context.Database.AutoTransactionsEnabled = autoTransactionsEnabled; context.Add( - new TransactionCustomer { Id = 77, Name = "Bobble" }); + new TransactionCustomer { Id = -77, Name = "Bobble" }); context.Entry(context.Set().OrderBy(c => c.Id).Last()).State = EntityState.Added; @@ -305,7 +305,7 @@ public virtual async Task SaveChanges_uses_ambient_transaction(bool async, bool Fixture.ListLoggerFactory.Log.Skip(2).First().Message); using var context = CreateContext(); - context.Entry(context.Set().Single(c => c.Id == 77)).State = EntityState.Deleted; + context.Entry(context.Set().Single(c => c.Id == -77)).State = EntityState.Deleted; if (async) { @@ -1268,7 +1268,7 @@ public virtual async Task SaveChanges_can_be_used_with_no_savepoint(bool async) ? await context.Database.BeginTransactionAsync() : context.Database.BeginTransaction(); - context.Add(new TransactionCustomer { Id = 77, Name = "Bobble" }); + context.Add(new TransactionCustomer { Id = -77, Name = "Bobble" }); if (async) { @@ -1279,7 +1279,7 @@ public virtual async Task SaveChanges_can_be_used_with_no_savepoint(bool async) context.SaveChanges(); } - context.Add(new TransactionCustomer { Id = 78, Name = "Hobble" }); + context.Add(new TransactionCustomer { Id = -78, Name = "Hobble" }); context.Add(new TransactionCustomer { Id = 1, Name = "Gobble" }); // Cause SaveChanges failure if (async) @@ -1298,7 +1298,7 @@ public virtual async Task SaveChanges_can_be_used_with_no_savepoint(bool async) using (var context = CreateContext()) { - Assert.Equal(78, context.Set().Max(c => c.Id)); + Assert.Equal(-78, context.Set().Min(c => c.Id)); } } diff --git a/test/EFCore.SqlServer.FunctionalTests/BatchingTest.cs b/test/EFCore.SqlServer.FunctionalTests/BatchingTest.cs index 0e61b60e550..4fa323a94c0 100644 --- a/test/EFCore.SqlServer.FunctionalTests/BatchingTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/BatchingTest.cs @@ -4,9 +4,12 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.SqlServer.Diagnostics.Internal; +using Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal; +using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -125,6 +128,93 @@ public void Inserts_and_updates_are_batched_correctly() context => AssertDatabaseState(context, true, expectedBlogs)); } + [ConditionalTheory] + [InlineData(1)] + [InlineData(3)] + [InlineData(4)] + [InlineData(100)] + public void Insertion_order_is_preserved(int maxBatchSize) + { + var blogId = new Guid(); + + TestHelpers.ExecuteWithStrategyInTransaction( + () => (BloggingContext)Fixture.CreateContext(maxBatchSize: maxBatchSize), + UseTransaction, + context => + { + var owner = new Owner(); + var blog = new Blog + { + Owner = owner + }; + + for (var i = 0; i < 20; i++) + { + context.Add(new Post { Order = i, Blog = blog }); + } + + context.SaveChanges(); + + blogId = blog.Id; + }, + context => + { + var posts = context.Set().Where(p => p.BlogId == blogId).OrderBy(p => p.Order); + var lastId = 0; + foreach (var post in posts) + { + Assert.True(post.PostId > lastId, $"Last ID: {lastId}, current ID: {post.PostId}"); + lastId = post.PostId; + } + }); + } + + [ConditionalFact] + public void Deadlock_on_deletes_with_dependents_is_handled_correctly() + { + var owners = new[] { new Owner { Name = "0" }, new Owner { Name = "1" } }; + using (var context = CreateContext()) + { + context.Owners.AddRange(owners); + + for (var h = 0; h <= 40; h++) + { + var owner = owners[h % 2]; + var blog = new Blog + { + Id = Guid.NewGuid(), + Owner = owner, + Order = h + }; + + for (var i = 0; i <= 40; i++) + { + blog.Posts.Add(new Post { Comments = { new Comment() } }); + } + + context.Add(blog); + } + + context.SaveChanges(); + } + + Parallel.ForEach(owners, owner => + { + using var context = (BloggingContext)Fixture.CreateContext(useConnectionString: true); + + context.RemoveRange(context.Blogs.Where(b => b.OwnerId == owner.Id)); + + context.SaveChanges(); + }); + + using (var context = CreateContext()) + { + Assert.Empty(context.Blogs); + } + + Fixture.Reseed(); + } + [ConditionalFact] public void Inserts_when_database_type_is_different() { @@ -251,6 +341,7 @@ private class Blog public string OwnerId { get; set; } public Owner Owner { get; set; } public byte[] Version { get; set; } + public ICollection Posts { get; } = new HashSet(); } private class Owner @@ -260,6 +351,22 @@ private class Owner public byte[] Version { get; set; } } + private class Post + { + public int PostId { get; set; } + public int? Order { get; set; } + public Guid BlogId { get; set; } + public Blog Blog { get; set; } + public ICollection Comments { get; } = new HashSet(); + } + + private class Comment + { + public int CommentId { get; set; } + public int PostId { get; set; } + public Post Post { get; set; } + } + public class BatchingTestFixture : SharedStoreFixtureBase { protected override string StoreName { get; } = "BatchingTest"; @@ -284,10 +391,37 @@ ALTER TABLE dbo.Owners ALTER COLUMN Name nvarchar(MAX);"); } - public DbContext CreateContext(int minBatchSize) + public DbContext CreateContext( + int? minBatchSize = null, + int? maxBatchSize = null, + bool useConnectionString = false, + bool disableConnectionResiliency = false) { - var optionsBuilder = new DbContextOptionsBuilder(CreateOptions()); - new SqlServerDbContextOptionsBuilder(optionsBuilder).MinBatchSize(minBatchSize); + var options = CreateOptions(); + var optionsBuilder = new DbContextOptionsBuilder(options); + if (useConnectionString) + { + RelationalOptionsExtension extension = options.FindExtension() + ?? new SqlServerOptionsExtension(); + + extension = extension.WithConnection(null).WithConnectionString(((SqlServerTestStore)TestStore).ConnectionString); + ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); + } + + if (minBatchSize.HasValue) + { + new SqlServerDbContextOptionsBuilder(optionsBuilder).MinBatchSize(minBatchSize.Value); + } + + if (maxBatchSize.HasValue) + { + new SqlServerDbContextOptionsBuilder(optionsBuilder).MinBatchSize(maxBatchSize.Value); + } + + if (disableConnectionResiliency) + { + new SqlServerDbContextOptionsBuilder(optionsBuilder).ExecutionStrategy(d => new SqlServerExecutionStrategy(d)); + } return new BloggingContext(optionsBuilder.Options); } } From 8ee4c054802602adf847f85fea23031b230a6d8a Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Tue, 7 Sep 2021 17:51:15 +0200 Subject: [PATCH 035/346] Cosmos: return null instead of throwing from Find (#25887) Fixes #25115 --- ...yableMethodTranslatingExpressionVisitor.cs | 2 +- .../Storage/Internal/CosmosClientWrapper.cs | 11 ++- .../Storage/Internal/ICosmosClientWrapper.cs | 4 +- .../FindCosmosTest.cs | 83 +++++++++++++++++++ 4 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs index 5966236baf8..d52745e07b9 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs @@ -129,7 +129,7 @@ public override Expression Visit(Expression expression) var readItemExpression = new ReadItemExpression(entityType, propertyParameterList); return CreateShapedQueryExpression(entityType, readItemExpression) - .UpdateResultCardinality(ResultCardinality.Single); + .UpdateResultCardinality(ResultCardinality.SingleOrDefault); } } } diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs index 1c1db963b6d..fae2804a2d2 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs @@ -551,7 +551,7 @@ public virtual IAsyncEnumerable ExecuteSqlQueryAsync( /// 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 JObject ExecuteReadItem( + public virtual JObject? ExecuteReadItem( string containerId, string? partitionKey, string resourceId) @@ -577,7 +577,7 @@ public virtual JObject ExecuteReadItem( /// 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 async Task ExecuteReadItemAsync( + public virtual async Task ExecuteReadItemAsync( string containerId, string? partitionKey, string resourceId, @@ -622,8 +622,13 @@ private static Task CreateSingleItemQueryAsync( cancellationToken: cancellationToken); } - private static JObject JObjectFromReadItemResponseMessage(ResponseMessage responseMessage) + private static JObject? JObjectFromReadItemResponseMessage(ResponseMessage responseMessage) { + if (responseMessage.StatusCode == HttpStatusCode.NotFound) + { + return null; + } + responseMessage.EnsureSuccessStatusCode(); var responseStream = responseMessage.Content; diff --git a/src/EFCore.Cosmos/Storage/Internal/ICosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/ICosmosClientWrapper.cs index 45b2529b1d0..888f0f497f3 100644 --- a/src/EFCore.Cosmos/Storage/Internal/ICosmosClientWrapper.cs +++ b/src/EFCore.Cosmos/Storage/Internal/ICosmosClientWrapper.cs @@ -148,7 +148,7 @@ Task DeleteItemAsync( /// 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. /// - JObject ExecuteReadItem( + JObject? ExecuteReadItem( string containerId, string? partitionKey, string resourceId); @@ -159,7 +159,7 @@ JObject ExecuteReadItem( /// 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. /// - Task ExecuteReadItemAsync( + Task ExecuteReadItemAsync( string containerId, string? partitionKey, string resourceId, diff --git a/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs new file mode 100644 index 00000000000..7f62bcb671b --- /dev/null +++ b/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace Microsoft.EntityFrameworkCore +{ + public abstract class FindCosmosTest : FindTestBase + { + protected FindCosmosTest(FindCosmosFixture fixture) + : base(fixture) + { + fixture.TestSqlLoggerFactory.Clear(); + } + + [ConditionalFact(Skip = "#25886")] + public override void Find_base_type_using_derived_set_tracked() {} + + [ConditionalFact(Skip = "#25886")] + public override Task Find_base_type_using_derived_set_tracked_async() + => Task.CompletedTask; + + [ConditionalFact(Skip = "#25886")] + public override void Find_derived_using_base_set_type_from_store() {} + + [ConditionalFact(Skip = "#25886")] + public override Task Find_derived_using_base_set_type_from_store_async() + => Task.CompletedTask; + + public class FindCosmosTestSet : FindCosmosTest + { + public FindCosmosTestSet(FindCosmosFixture fixture) + : base(fixture) + { + } + + protected override TEntity Find(DbContext context, params object[] keyValues) + => context.Set().Find(keyValues); + + protected override ValueTask FindAsync(DbContext context, params object[] keyValues) + => context.Set().FindAsync(keyValues); + } + + public class FindCosmosTestContext : FindCosmosTest + { + public FindCosmosTestContext(FindCosmosFixture fixture) + : base(fixture) + { + } + + protected override TEntity Find(DbContext context, params object[] keyValues) + => context.Find(keyValues); + + protected override ValueTask FindAsync(DbContext context, params object[] keyValues) + => context.FindAsync(keyValues); + } + + public class FindCosmosTestNonGeneric : FindCosmosTest + { + public FindCosmosTestNonGeneric(FindCosmosFixture fixture) + : base(fixture) + { + } + + protected override TEntity Find(DbContext context, params object[] keyValues) + => (TEntity)context.Find(typeof(TEntity), keyValues); + + protected override async ValueTask FindAsync(DbContext context, params object[] keyValues) + => (TEntity)await context.FindAsync(typeof(TEntity), keyValues); + } + + public class FindCosmosFixture : FindFixtureBase + { + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + + protected override ITestStoreFactory TestStoreFactory + => CosmosTestStoreFactory.Instance; + } + } +} From 3a0defcdb61c6832b705b45fac590024bf447107 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 7 Sep 2021 16:35:06 +0000 Subject: [PATCH 036/346] Update dependencies from https://github.com/dotnet/runtime build 20210904.1 (#25876) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 191f26420d7..4eb01bd460d 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b - + https://github.com/dotnet/runtime - ea48ccc279461d29698b91697cafe46398e87178 + b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b diff --git a/eng/Versions.props b/eng/Versions.props index 4793cfabb94..fc7727a3d8a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 - 6.0.0-rc.2.21453.13 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21454.1 3.7.0 From cc63bbf8fe640cd9e35c81b326ab53d348ef9704 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 7 Sep 2021 16:35:38 +0000 Subject: [PATCH 037/346] Update dependencies from https://github.com/dotnet/arcade build 20210903.2 (#25884) [main] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 8 ++++---- eng/common/tools.ps1 | 11 +++++++++++ eng/common/tools.sh | 9 +++++++++ global.json | 8 ++++---- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7ab398c33e9..235b55a9a0d 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -47,13 +47,13 @@ - + https://github.com/dotnet/arcade - 474307e526160c813c9fd58060eb8356ccca6099 + 0ec8dbacaefa7ccdb4bc96e120e07dc60c6eda98 - + https://github.com/dotnet/arcade - 474307e526160c813c9fd58060eb8356ccca6099 + 0ec8dbacaefa7ccdb4bc96e120e07dc60c6eda98 diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 56ee4a577ac..02347914f5d 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -709,6 +709,15 @@ function MSBuild() { Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' } + if ($ci) { + $env:NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY = 'true' + $env:NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT = 6 + $env:NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS = 1000 + Write-PipelineSetVariable -Name 'NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY' -Value 'true' + Write-PipelineSetVariable -Name 'NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT' -Value '6' + Write-PipelineSetVariable -Name 'NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS' -Value '1000' + } + $toolsetBuildProject = InitializeToolset $basePath = Split-Path -parent $toolsetBuildProject $possiblePaths = @( @@ -717,6 +726,8 @@ function MSBuild() { (Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.Arcade.Sdk.dll')), (Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.ArcadeLogging.dll')), (Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.Arcade.Sdk.dll')) + (Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.ArcadeLogging.dll')), + (Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.Arcade.Sdk.dll')) ) $selectedPath = $null foreach ($path in $possiblePaths) { diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 41e323104df..6a4871ef72b 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -417,6 +417,13 @@ function MSBuild { export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" + + export NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY=true + export NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT=6 + export NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS=1000 + Write-PipelineSetVariable -name "NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY" -value "true" + Write-PipelineSetVariable -name "NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT" -value "6" + Write-PipelineSetVariable -name "NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS" -value "1000" fi local toolset_dir="${_InitializeToolset%/*}" @@ -427,6 +434,8 @@ function MSBuild { possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.Arcade.Sdk.dll" ) possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.ArcadeLogging.dll" ) possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.Arcade.Sdk.dll" ) + possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.ArcadeLogging.dll" ) + possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.Arcade.Sdk.dll" ) for path in "${possiblePaths[@]}"; do if [[ -f $path ]]; then selectedPath=$path diff --git a/global.json b/global.json index aa183d0c637..eef3634046b 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "tools": { - "dotnet": "6.0.100-rc.1.21379.2", + "dotnet": "6.0.100-rc.1.21430.12", "runtimes": { "dotnet": [ "3.1.16", @@ -13,12 +13,12 @@ } }, "sdk": { - "version": "6.0.100-rc.1.21379.2", + "version": "6.0.100-rc.1.21430.12", "allowPrerelease": true, "rollForward": "latestMajor" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21427.6", - "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21427.6" + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21453.2", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.21453.2" } } From d810a3b703288678ecf809dbce1e59508955eff2 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 7 Sep 2021 19:18:41 +0000 Subject: [PATCH 038/346] Update dependencies from https://github.com/dotnet/runtime build 20210907.6 (#25907) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4eb01bd460d..613a01cbe70 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 - + https://github.com/dotnet/runtime - b7e72a4ab2cb4832d88f7f23a2493287f7bcc43b + c300b096419523024f2b807ec9db3c2d91df0298 diff --git a/eng/Versions.props b/eng/Versions.props index fc7727a3d8a..6f06c684263 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 - 6.0.0-rc.2.21454.1 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.6 3.7.0 From c2234539660d15f47f3af1350825699e7b2a54eb Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 7 Sep 2021 21:00:38 +0000 Subject: [PATCH 039/346] Update dependencies from https://github.com/dotnet/runtime build 20210907.12 (#25909) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 613a01cbe70..0aa2490d82f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 - + https://github.com/dotnet/runtime - c300b096419523024f2b807ec9db3c2d91df0298 + 8482854c4906a25d0a007fcf2f5deac61cb40b31 diff --git a/eng/Versions.props b/eng/Versions.props index 6f06c684263..a583797ec90 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 - 6.0.0-rc.2.21457.6 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.12 3.7.0 From 7b55039e19f06dbbcac4154efc1aa05c4877b60b Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Tue, 7 Sep 2021 14:08:42 -0700 Subject: [PATCH 040/346] Update branding for 5.0.11 (#25902) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 258b84f4df3..cd1dbc9330f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,6 +1,6 @@ - 5.0.10 + 5.0.11 servicing False true From 4bcd792c4d64a5d137fea14b042aebe26545b1f2 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Tue, 7 Sep 2021 14:08:46 -0700 Subject: [PATCH 041/346] Update branding for 3.1.20 (#25901) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 7220f4df354..b300a6d9ad1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,6 +1,6 @@ - 3.1.19 + 3.1.20 servicing False true From f96aa981822933e2bc7ce3f7a970bc0f7c70e668 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Tue, 7 Sep 2021 15:08:41 -0700 Subject: [PATCH 042/346] Query: Add regression test for #23784 (#25855) Resolves #23784 --- .../Query/NorthwindFunctionsQueryCosmosTest.cs | 6 ++++++ .../Query/NorthwindFunctionsQueryTestBase.cs | 11 +++++++++++ .../Query/NorthwindFunctionsQuerySqlServerTest.cs | 5 +++++ .../Query/NorthwindFunctionsQuerySqliteTest.cs | 5 +++++ 4 files changed, 27 insertions(+) diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs index d7e70455d30..60f6ba46599 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs @@ -1395,6 +1395,12 @@ FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND STRINGEQUALS(c[""CustomerID""], ""ALFKI""))"); } + [ConditionalTheory(Skip = "Issue #17246")] + public override Task Datetime_subtraction_TotalDays(bool async) + { + return base.Datetime_subtraction_TotalDays(async); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs index 319710d4572..037c81e9708 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs @@ -1893,5 +1893,16 @@ public virtual Task Regex_IsMatch_MethodCall_constant_input(bool async) ss => ss.Set().Where(o => Regex.IsMatch("ALFKI", o.CustomerID)), entryCount: 1); } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Datetime_subtraction_TotalDays(bool async) + { + var date = new DateTime(1997, 1, 1); + return AssertQuery( + async, + ss => ss.Set().Where(o => o.OrderDate.HasValue && (o.OrderDate.Value - date).TotalDays > 365), + entryCount: 267); + } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs index 1b742e7e9a3..680cf207440 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs @@ -1823,6 +1823,11 @@ public override Task Regex_IsMatch_MethodCall_constant_input(bool async) return AssertTranslationFailed(() => base.Regex_IsMatch_MethodCall_constant_input(async)); } + public override Task Datetime_subtraction_TotalDays(bool async) + { + return AssertTranslationFailed(() => base.Datetime_subtraction_TotalDays(async)); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindFunctionsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindFunctionsQuerySqliteTest.cs index b5ff5b12dcb..c81ec422dd8 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindFunctionsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindFunctionsQuerySqliteTest.cs @@ -617,6 +617,11 @@ public override async Task Regex_IsMatch_MethodCall_constant_input(bool async) WHERE regexp(""c"".""CustomerID"", 'ALFKI')"); } + public override Task Datetime_subtraction_TotalDays(bool async) + { + return AssertTranslationFailed(() => base.Datetime_subtraction_TotalDays(async)); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } From 990393b6ebebda33c26fdabf894a00e509ca4e3e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 7 Sep 2021 22:41:15 +0000 Subject: [PATCH 043/346] [main] Update dependencies from dotnet/runtime (#25883) [main] Update dependencies from dotnet/runtime - Nullability fixes --- eng/Version.Details.xml | 44 +++++++++---------- eng/Versions.props | 22 +++++----- .../Infrastructure/SpatialiteLoader.cs | 4 +- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 235b55a9a0d..aa8253c432c 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e - + https://github.com/dotnet/runtime - 9671726c0a79d5f4cab320b32da1cd4463a0d1be + b7e10374429b5af32debc4660aa9bce41cfb903e diff --git a/eng/Versions.props b/eng/Versions.props index 32bf0bffa9d..84d4ff6f7ae 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 - 7.0.0-alpha.1.21430.3 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21456.1 3.7.0 diff --git a/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs b/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs index eaac6d0250c..cb7dece454d 100644 --- a/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs +++ b/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs @@ -127,7 +127,7 @@ private static void FindExtension() var candidateAssets = new Dictionary<(string, string), int>(); var rid = RuntimeInformation.RuntimeIdentifier; var rids = DependencyContext.Default!.RuntimeGraph.FirstOrDefault(g => g.Runtime == rid)?.Fallbacks.ToList() - ?? new List(); + ?? new List(); rids.Insert(0, rid); foreach (var library in DependencyContext.Default.RuntimeLibraries) @@ -142,7 +142,7 @@ private static void FindExtension() StringComparison.OrdinalIgnoreCase)) { var fallbacks = rids.IndexOf(group.Runtime); - if (fallbacks != -1) + if (fallbacks != -1 && library.Path is not null) { candidateAssets.Add((library.Path, file.Path), fallbacks); } From acad6c35f4476351e59d3750190e814701cb5c92 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 7 Sep 2021 22:57:06 +0000 Subject: [PATCH 044/346] Update dependencies from https://github.com/dotnet/runtime build 20210907.14 (#25916) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0aa2490d82f..28527baedd2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 - + https://github.com/dotnet/runtime - 8482854c4906a25d0a007fcf2f5deac61cb40b31 + 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 diff --git a/eng/Versions.props b/eng/Versions.props index a583797ec90..56d578a96b2 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 - 6.0.0-rc.2.21457.12 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.14 3.7.0 From 0df9d5a6e4ef076e400617700d863793af780a14 Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Thu, 26 Aug 2021 09:56:48 -0700 Subject: [PATCH 045/346] :arrow_up: Bump SQLitePCLRaw to 2.0.6 --- .../EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj | 2 +- src/EFCore.Sqlite/EFCore.Sqlite.csproj | 2 +- .../Microsoft.Data.Sqlite.Core.csproj | 2 +- src/Microsoft.Data.Sqlite/Microsoft.Data.Sqlite.csproj | 2 +- .../EFCore.Sqlite.FunctionalTests.csproj | 2 +- .../Microsoft.Data.Sqlite.Tests.csproj | 2 +- .../Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj | 2 +- .../Microsoft.Data.Sqlite.sqlite3.Tests.csproj | 2 +- .../Microsoft.Data.Sqlite.winsqlite3.Tests.csproj | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj b/benchmark/EFCore.Sqlite.Benchmarks/EFCore.Sqlite.Benchmarks.csproj index 9e259ee0623..1e69372b348 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/src/EFCore.Sqlite/EFCore.Sqlite.csproj b/src/EFCore.Sqlite/EFCore.Sqlite.csproj index 84348f9bf3e..231c9c36f77 100644 --- a/src/EFCore.Sqlite/EFCore.Sqlite.csproj +++ b/src/EFCore.Sqlite/EFCore.Sqlite.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/Microsoft.Data.Sqlite.Core/Microsoft.Data.Sqlite.Core.csproj b/src/Microsoft.Data.Sqlite.Core/Microsoft.Data.Sqlite.Core.csproj index 95ffd298805..801c3e67826 100644 --- a/src/Microsoft.Data.Sqlite.Core/Microsoft.Data.Sqlite.Core.csproj +++ b/src/Microsoft.Data.Sqlite.Core/Microsoft.Data.Sqlite.Core.csproj @@ -39,7 +39,7 @@ Microsoft.Data.Sqlite.SqliteTransaction - + diff --git a/src/Microsoft.Data.Sqlite/Microsoft.Data.Sqlite.csproj b/src/Microsoft.Data.Sqlite/Microsoft.Data.Sqlite.csproj index e2832e8c64f..cabcd1466f9 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/test/EFCore.Sqlite.FunctionalTests/EFCore.Sqlite.FunctionalTests.csproj b/test/EFCore.Sqlite.FunctionalTests/EFCore.Sqlite.FunctionalTests.csproj index 39f50c5226d..fdd118480a7 100644 --- a/test/EFCore.Sqlite.FunctionalTests/EFCore.Sqlite.FunctionalTests.csproj +++ b/test/EFCore.Sqlite.FunctionalTests/EFCore.Sqlite.FunctionalTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj index 54302301925..987df8b6193 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj index babe99fac04..7987d9734bf 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.e_sqlcipher.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj index 2209ad53a91..efd58536fcb 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.winsqlite3.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.winsqlite3.Tests.csproj index 87a7da23029..7f7909af569 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.winsqlite3.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.winsqlite3.Tests.csproj @@ -11,7 +11,7 @@ - + From fdbc2b9c10d41aeef1d030a9c115e1af504563ce Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 02:23:00 +0000 Subject: [PATCH 046/346] Update dependencies from https://github.com/dotnet/runtime build 20210907.19 (#25919) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 28527baedd2..f37309833c2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb - + https://github.com/dotnet/runtime - 3b6f9c6f4ec621cf2e7e5c5ddf80f20187b30fb4 + 6eca241bcc6b60d9815e2566bb661a14c2eeccfb diff --git a/eng/Versions.props b/eng/Versions.props index 56d578a96b2..df2a2406cc5 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 - 6.0.0-rc.2.21457.14 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.19 3.7.0 From 31e551d13f9e275217f8900c69397a6ee7a59830 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 8 Sep 2021 07:37:52 +0200 Subject: [PATCH 047/346] Add test for scaffolding multiple indexes on the same column (#25917) Fixes #11846 --- .../SqlServerDatabaseModelFactoryTest.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs index 1a835448a19..b621213b02f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs @@ -852,6 +852,48 @@ CREATE TABLE IndexTable ( "DROP TABLE IndexTable;"); } + [ConditionalFact] + public void Create_multiple_indexes_on_same_column() + { + Test( + @" +CREATE TABLE IndexTable ( + Id int, + IndexProperty int +); + +CREATE INDEX IX_One on IndexTable ( IndexProperty ) WITH (FILLFACTOR = 100); +CREATE INDEX IX_Two on IndexTable ( IndexProperty ) WITH (FILLFACTOR = 50);", + Enumerable.Empty(), + Enumerable.Empty(), + dbModel => + { + var table = dbModel.Tables.Single(); + + Assert.Equal(2, table.Indexes.Count); + Assert.All( + table.Indexes, c => + { + Assert.Equal("dbo", c.Table.Schema); + Assert.Equal("IndexTable", c.Table.Name); + }); + + Assert.Collection( + table.Indexes.OrderBy(i => i.Name), + index => + { + Assert.Equal("IX_One", index.Name); + Assert.Equal(100, index[SqlServerAnnotationNames.FillFactor]); + }, + index => + { + Assert.Equal("IX_Two", index.Name); + Assert.Equal(50, index[SqlServerAnnotationNames.FillFactor]); + }); + }, + "DROP TABLE IndexTable;"); + } + [ConditionalFact] public void Create_foreign_keys() { From 0d18566b76a34b7e65d1a7918a67f0f3dec2a6ef Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 8 Sep 2021 07:39:43 +0200 Subject: [PATCH 048/346] Remove MethodCallCodeFragment constructor accepting a chained call (#25910) Fixes #19780 --- .../Internal/SqlServerAnnotationCodeGenerator.cs | 12 ++++-------- src/EFCore/Design/MethodCallCodeFragment.cs | 12 ++++++++++-- .../Design/Internal/CSharpHelperTest.cs | 10 +++++----- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs index 43e02397891..f6055dbc3d3 100644 --- a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs +++ b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs @@ -215,19 +215,15 @@ public override IReadOnlyList GenerateFluentApiCalls( // ttb => ttb.HasPeriodStart("Start").HasColumnName("ColumnStart") temporalTableBuilderCalls.Add( periodStartColumnName != null - ? new MethodCallCodeFragment( - _temporalTableHasPeriodStartMethodInfo, - new[] { periodStartProperty.Name }, - new MethodCallCodeFragment(_temporalPropertyHasColumnNameMethodInfo, periodStartColumnName)) + ? new MethodCallCodeFragment(_temporalTableHasPeriodStartMethodInfo, periodStartProperty.Name) + .Chain(new MethodCallCodeFragment(_temporalPropertyHasColumnNameMethodInfo, periodStartColumnName)) : new MethodCallCodeFragment(_temporalTableHasPeriodStartMethodInfo, periodStartProperty.Name)); // ttb => ttb.HasPeriodEnd("End").HasColumnName("ColumnEnd") temporalTableBuilderCalls.Add( periodEndColumnName != null - ? new MethodCallCodeFragment( - _temporalTableHasPeriodEndMethodInfo, - new[] { periodEndProperty.Name }, - new MethodCallCodeFragment(_temporalPropertyHasColumnNameMethodInfo, periodEndColumnName)) + ? new MethodCallCodeFragment(_temporalTableHasPeriodEndMethodInfo, periodEndProperty.Name) + .Chain(new MethodCallCodeFragment(_temporalPropertyHasColumnNameMethodInfo, periodEndColumnName)) : new MethodCallCodeFragment(_temporalTableHasPeriodEndMethodInfo, periodEndProperty.Name)); // ToTable(tb => tb.IsTemporal(ttb => { ... })) diff --git a/src/EFCore/Design/MethodCallCodeFragment.cs b/src/EFCore/Design/MethodCallCodeFragment.cs index d5d9386e856..b2628ae9aaa 100644 --- a/src/EFCore/Design/MethodCallCodeFragment.cs +++ b/src/EFCore/Design/MethodCallCodeFragment.cs @@ -72,11 +72,19 @@ public MethodCallCodeFragment(string method, params object?[] arguments) /// The method's . /// The method call's arguments. Can be . /// The next method call to chain after this. + [Obsolete("Use the constructor without a chained call, and then invoke Chain() on the result", error: true)] public MethodCallCodeFragment( MethodInfo methodInfo, object?[] arguments, MethodCallCodeFragment chainedCall) : this(methodInfo, arguments) + => throw new NotSupportedException(); + + private MethodCallCodeFragment( + MethodInfo methodInfo, + MethodCallCodeFragment chainedCall, + object?[] arguments) + : this(methodInfo, arguments) { Check.NotNull(chainedCall, nameof(chainedCall)); @@ -89,7 +97,7 @@ public MethodCallCodeFragment( /// The method's name. /// The method call's arguments. Can be . /// The next method call to chain after this. - [Obsolete("Use the overload accepting a MethodInfo")] + [Obsolete("Use the overload accepting a MethodInfo, and then invoke Chain on the instance for the chained call")] public MethodCallCodeFragment( string method, object?[] arguments, @@ -170,6 +178,6 @@ public virtual MethodCallCodeFragment Chain(MethodCallCodeFragment call) #pragma warning disable 618 ? new(_method!, _arguments.ToArray(), ChainedCall?.Chain(call) ?? call) #pragma warning restore 618 - : new(MethodInfo, _arguments.ToArray(), ChainedCall?.Chain(call) ?? call); + : new(MethodInfo, ChainedCall?.Chain(call) ?? call, _arguments.ToArray()); } } diff --git a/test/EFCore.Design.Tests/Design/Internal/CSharpHelperTest.cs b/test/EFCore.Design.Tests/Design/Internal/CSharpHelperTest.cs index ff9db93949f..17c12a8b686 100644 --- a/test/EFCore.Design.Tests/Design/Internal/CSharpHelperTest.cs +++ b/test/EFCore.Design.Tests/Design/Internal/CSharpHelperTest.cs @@ -334,8 +334,8 @@ public void Fragment_MethodCallCodeFragment_works_when_chaining() [ConditionalFact] public void Fragment_MethodCallCodeFragment_works_when_chaining_on_chain() { - var method = new MethodCallCodeFragment( - _testFuncMethodInfo, new[] { "One" }, new MethodCallCodeFragment(_testFuncMethodInfo, "Two")) + var method = new MethodCallCodeFragment(_testFuncMethodInfo, "One") + .Chain(new MethodCallCodeFragment(_testFuncMethodInfo, "Two")) .Chain(_testFuncMethodInfo, "Three"); var result = new CSharpHelper(TypeMappingSource).Fragment(method); @@ -346,8 +346,8 @@ public void Fragment_MethodCallCodeFragment_works_when_chaining_on_chain() [ConditionalFact] public void Fragment_MethodCallCodeFragment_works_when_chaining_on_chain_with_call() { - var method = new MethodCallCodeFragment(_testFuncMethodInfo, new[] { "One" }, new MethodCallCodeFragment(_testFuncMethodInfo, "Two")) - .Chain(new MethodCallCodeFragment(_testFuncMethodInfo, new[] { "Three" }, new MethodCallCodeFragment(_testFuncMethodInfo, "Four"))); + var method = new MethodCallCodeFragment(_testFuncMethodInfo, "One").Chain(new MethodCallCodeFragment(_testFuncMethodInfo, "Two")) + .Chain(new MethodCallCodeFragment(_testFuncMethodInfo, "Three").Chain(new MethodCallCodeFragment(_testFuncMethodInfo, "Four"))); var result = new CSharpHelper(TypeMappingSource).Fragment(method); @@ -379,7 +379,7 @@ public void Fragment_MethodCallCodeFragment_works_with_identifier() [ConditionalFact] public void Fragment_MethodCallCodeFragment_works_with_identifier_chained() { - var method = new MethodCallCodeFragment(_testFuncMethodInfo, new[] { "One"}, new MethodCallCodeFragment(_testFuncMethodInfo)); + var method = new MethodCallCodeFragment(_testFuncMethodInfo, "One").Chain(new MethodCallCodeFragment(_testFuncMethodInfo)); var result = new CSharpHelper(TypeMappingSource).Fragment(method, instanceIdentifier: "builder"); From d8c2ea6db873e743b3d7a02705aa9a0525fb65da Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 06:17:26 +0000 Subject: [PATCH 049/346] Update dependencies from https://github.com/dotnet/runtime build 20210907.23 (#25921) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index f37309833c2..1fd060635f3 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab - + https://github.com/dotnet/runtime - 6eca241bcc6b60d9815e2566bb661a14c2eeccfb + 895eb99d4987654cfb18e922a00c428678394bab diff --git a/eng/Versions.props b/eng/Versions.props index df2a2406cc5..57a7e779c55 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 - 6.0.0-rc.2.21457.19 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.23 3.7.0 From 04b6d558a7c0374456e16ea7726128b4dc79b2b3 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 8 Sep 2021 07:35:14 +0100 Subject: [PATCH 050/346] Update SQLite dependencies to 2.0.4 (#25550) Fixes #25497 --- eng/Versions.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index b300a6d9ad1..8d0b0261578 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -24,9 +24,9 @@ 2.0.0 2.0.0 2.0.0 - 2.0.2 - 2.0.2 - 2.0.2 + 2.0.4 + 2.0.4 + 2.0.4 1.1.118 0.11.3 1.1.3 From 9392d8c7935e22c54706255c2bbe2d993fa28646 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 8 Sep 2021 07:49:58 +0100 Subject: [PATCH 051/346] Store store-generated FK values in the store-generated snapshot (#25894) Fixes #22603 --- .../Internal/InternalEntityEntry.cs | 6 ++- .../StoreGeneratedValuesFactoryFactory.cs | 44 +++++++++++++++++++ src/EFCore/Metadata/Internal/EntityType.cs | 6 +-- .../Metadata/Internal/IRuntimeEntityType.cs | 2 +- src/EFCore/Metadata/RuntimeEntityType.cs | 6 +-- .../StoreGeneratedTestBase.cs | 21 ++++++++- .../StoreGeneratedSqlServerTest.cs | 35 ++++++++++++++- 7 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 src/EFCore/ChangeTracking/Internal/StoreGeneratedValuesFactoryFactory.cs diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index 0356f722dce..b505052b521 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -613,6 +613,10 @@ public void PropagateValue( SetTemporaryValue(dependentProperty, principalValue); } } + else if (principalEntry.GetValueType(principalProperty) == CurrentValueType.StoreGenerated) + { + SetStoreGeneratedValue(dependentProperty, principalValue); + } else { SetProperty(dependentProperty, principalValue, isMaterialization, setModified); @@ -1052,7 +1056,7 @@ public void EnsureStoreGeneratedValues() { if (_storeGeneratedValues.IsEmpty) { - _storeGeneratedValues = new SidecarValues(((IRuntimeEntityType)EntityType).StoreGeneratedValuesFactory(this)); + _storeGeneratedValues = new SidecarValues(((IRuntimeEntityType)EntityType).StoreGeneratedValuesFactory()); } } diff --git a/src/EFCore/ChangeTracking/Internal/StoreGeneratedValuesFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/StoreGeneratedValuesFactoryFactory.cs new file mode 100644 index 00000000000..0a51dd34f66 --- /dev/null +++ b/src/EFCore/ChangeTracking/Internal/StoreGeneratedValuesFactoryFactory.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Metadata; + +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 class StoreGeneratedValuesFactoryFactory : SidecarValuesFactoryFactory + { + /// + /// 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. + /// + protected override bool UseEntityVariable + => 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. + /// + protected override Expression CreateReadShadowValueExpression(ParameterExpression parameter, IPropertyBase property) + => Expression.Default(property.ClrType); + + /// + /// 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. + /// + protected override Expression CreateReadValueExpression(ParameterExpression parameter, IPropertyBase property) + => Expression.Default(property.ClrType); + } +} diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs index 86920ccdd56..c07a89021a8 100644 --- a/src/EFCore/Metadata/Internal/EntityType.cs +++ b/src/EFCore/Metadata/Internal/EntityType.cs @@ -77,7 +77,7 @@ private readonly SortedDictionary _serviceProperties private Func? _relationshipSnapshotFactory; private Func? _originalValuesFactory; private Func? _temporaryValuesFactory; - private Func? _storeGeneratedValuesFactory; + private Func? _storeGeneratedValuesFactory; private Func? _shadowValuesFactory; private Func? _emptyShadowValuesFactory; private Func? _instanceFactory; @@ -2665,13 +2665,13 @@ public virtual Func OriginalValuesFactory /// 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 Func StoreGeneratedValuesFactory + public virtual Func StoreGeneratedValuesFactory => NonCapturingLazyInitializer.EnsureInitialized( ref _storeGeneratedValuesFactory, this, static entityType => { entityType.EnsureReadOnly(); - return new SidecarValuesFactoryFactory().Create(entityType); + return new StoreGeneratedValuesFactoryFactory().CreateEmpty(entityType); }); /// diff --git a/src/EFCore/Metadata/Internal/IRuntimeEntityType.cs b/src/EFCore/Metadata/Internal/IRuntimeEntityType.cs index 86ce6e8887e..cd59f1313f7 100644 --- a/src/EFCore/Metadata/Internal/IRuntimeEntityType.cs +++ b/src/EFCore/Metadata/Internal/IRuntimeEntityType.cs @@ -45,7 +45,7 @@ public interface IRuntimeEntityType : IEntityType /// 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. /// - Func StoreGeneratedValuesFactory { get; } + Func StoreGeneratedValuesFactory { get; } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Metadata/RuntimeEntityType.cs b/src/EFCore/Metadata/RuntimeEntityType.cs index f260b51799b..638df57a49b 100644 --- a/src/EFCore/Metadata/RuntimeEntityType.cs +++ b/src/EFCore/Metadata/RuntimeEntityType.cs @@ -66,7 +66,7 @@ private readonly SortedDictionary _serviceProper private Func? _relationshipSnapshotFactory; private Func? _originalValuesFactory; private Func? _temporaryValuesFactory; - private Func? _storeGeneratedValuesFactory; + private Func? _storeGeneratedValuesFactory; private Func? _shadowValuesFactory; private Func? _emptyShadowValuesFactory; private Func? _instanceFactory; @@ -1258,10 +1258,10 @@ Func IRuntimeEntityType.OriginalValuesFactory static entityType => new OriginalValuesFactoryFactory().Create(entityType)); /// - Func IRuntimeEntityType.StoreGeneratedValuesFactory + Func IRuntimeEntityType.StoreGeneratedValuesFactory => NonCapturingLazyInitializer.EnsureInitialized( ref _storeGeneratedValuesFactory, this, - static entityType => new SidecarValuesFactoryFactory().Create(entityType)); + static entityType => new StoreGeneratedValuesFactoryFactory().CreateEmpty(entityType)); /// Func IRuntimeEntityType.TemporaryValuesFactory diff --git a/test/EFCore.Specification.Tests/StoreGeneratedTestBase.cs b/test/EFCore.Specification.Tests/StoreGeneratedTestBase.cs index 0ec16f0eb56..d40ff4536d8 100644 --- a/test/EFCore.Specification.Tests/StoreGeneratedTestBase.cs +++ b/test/EFCore.Specification.Tests/StoreGeneratedTestBase.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Reflection; @@ -1467,6 +1468,19 @@ public int Id } public string Name { get; set; } + + public ICollection MixedMetaphors { get; set; } + public Species Species { get; set; } + } + + protected class Species + { + public int Id { get; set; } + public string Name { get; set; } + + public int? DarwinId { get; set; } + public int? MetaphoricId { get; set; } + } protected class Gumball @@ -1915,7 +1929,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con property.SetAfterSaveBehavior(PropertySaveBehavior.Throw); }); - modelBuilder.Entity(); + modelBuilder.Entity( + b => + { + b.HasOne(e => e.Species).WithOne().HasForeignKey(e => e.DarwinId); + b.HasMany(e => e.MixedMetaphors).WithOne().HasForeignKey(e => e.MetaphoricId); + }); modelBuilder.Entity( b => diff --git a/test/EFCore.SqlServer.FunctionalTests/StoreGeneratedSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/StoreGeneratedSqlServerTest.cs index 3c6e2997eb0..6726e148e09 100644 --- a/test/EFCore.SqlServer.FunctionalTests/StoreGeneratedSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/StoreGeneratedSqlServerTest.cs @@ -29,11 +29,32 @@ public virtual void Exception_in_SaveChanges_causes_store_values_to_be_reverted( var entities = new List(); for (var i = 0; i < 100; i++) { - entities.Add(new Darwin()); + entities.Add(new() + { + Species = new() { Name = "Goldfish (with legs)" }, + MixedMetaphors = new List + { + new() { Name = "Large ground finch" }, + new() { Name = "Medium ground finch" }, + new() { Name = "Small tree finch" }, + new() { Name = "Green warbler-finch" } + } + }); } entities.Add( - new Darwin { Id = 1777 }); + new() + { + Id = 1777, + Species = new() { Name = "Goldfish (with legs)" }, + MixedMetaphors = new List + { + new() { Name = "Large ground finch" }, + new() { Name = "Medium ground finch" }, + new() { Name = "Small tree finch" }, + new() { Name = "Green warbler-finch" } + } + }); for (var i = 0; i < 2; i++) { @@ -77,9 +98,19 @@ public virtual void Exception_in_SaveChanges_causes_store_values_to_be_reverted( { Assert.Equal(0, entity.Id); Assert.Null(entity._id); + Assert.Null(entity.Species.DarwinId); + foreach (var species in entity.MixedMetaphors) + { + Assert.Null(species.MetaphoricId); + } } Assert.Equal(1777, entities[100].Id); + Assert.Equal(1777, entities[100].Species.DarwinId); + foreach (var species in entities[100].MixedMetaphors) + { + Assert.Equal(1777, species.MetaphoricId); + } foreach (var entity in entities) { From 30ff4460acd03e4b7d93141ddc180a6f91921638 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 8 Sep 2021 07:50:49 +0100 Subject: [PATCH 052/346] Allow setting original/current values using a typed dictionary (#25895) Fixes #22968 --- src/EFCore/ChangeTracking/PropertyValues.cs | 2 +- .../PropertyValuesTestBase.cs | 90 +++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/EFCore/ChangeTracking/PropertyValues.cs b/src/EFCore/ChangeTracking/PropertyValues.cs index 9f9db927350..34d0b07d1d2 100644 --- a/src/EFCore/ChangeTracking/PropertyValues.cs +++ b/src/EFCore/ChangeTracking/PropertyValues.cs @@ -116,7 +116,7 @@ protected PropertyValues(InternalEntityEntry internalEntry) /// See Accessing tracked entities in EF Core for more information. /// /// The dictionary to read values from. - public virtual void SetValues(IDictionary values) + public virtual void SetValues(IDictionary values) { Check.NotNull(values, nameof(values)); diff --git a/test/EFCore.Specification.Tests/PropertyValuesTestBase.cs b/test/EFCore.Specification.Tests/PropertyValuesTestBase.cs index 4e8dc710684..982d9e79206 100644 --- a/test/EFCore.Specification.Tests/PropertyValuesTestBase.cs +++ b/test/EFCore.Specification.Tests/PropertyValuesTestBase.cs @@ -1480,6 +1480,96 @@ private void TestDictionarySetValues( ValidateBuildingPropereties(context.Entry(building), getValue, 13, "Pine Walk"); } + [ConditionalFact] + public virtual void Current_values_can_be_set_from_dictionary_typed_int() + { + TestDictionarySetValuesTypedInt(e => e.CurrentValues, (e, n) => e.Property(n).CurrentValue); + } + + [ConditionalFact] + public virtual void Original_values_can_be_set_from_dictionary_typed_int() + { + TestDictionarySetValuesTypedInt(e => e.OriginalValues, (e, n) => e.Property(n).OriginalValue); + } + + private void TestDictionarySetValuesTypedInt( + Func getPropertyValues, + Func getValue) + { + using var context = CreateContext(); + var building = context.Set().Single(b => b.Name == "Building One"); + var buildingValues = getPropertyValues(context.Entry(building)); + + var dictionary = new Dictionary + { + { "Shadow1", 13 }, + { "PrincipalMailRoomId", 0 } + }; + + buildingValues.SetValues(dictionary); + + Assert.Equal("Building One", buildingValues["Name"]); + Assert.Equal(1500000m, buildingValues["Value"]); + Assert.Equal(13, buildingValues["Shadow1"]); + Assert.Equal("Meadow Drive", buildingValues["Shadow2"]); + + Assert.Equal("Building One", getValue(context.Entry(building), "Name")); + Assert.Equal(1500000m, getValue(context.Entry(building), "Value")); + Assert.Equal(13, getValue(context.Entry(building), "Shadow1")); + Assert.Equal("Meadow Drive", getValue(context.Entry(building), "Shadow2")); + + Assert.False(context.Entry(building).Property("Name").IsModified); + Assert.False(context.Entry(building).Property("BuildingId").IsModified); + Assert.False(context.Entry(building).Property("Value").IsModified); + Assert.True(context.Entry(building).Property("Shadow1").IsModified); + Assert.False(context.Entry(building).Property("Shadow2").IsModified); + } + + [ConditionalFact] + public virtual void Current_values_can_be_set_from_dictionary_typed_string() + { + TestDictionarySetValuesTypedString(e => e.CurrentValues, (e, n) => e.Property(n).CurrentValue); + } + + [ConditionalFact] + public virtual void Original_values_can_be_set_from_dictionary_typed_string() + { + TestDictionarySetValuesTypedString(e => e.OriginalValues, (e, n) => e.Property(n).OriginalValue); + } + + private void TestDictionarySetValuesTypedString( + Func getPropertyValues, + Func getValue) + { + using var context = CreateContext(); + var building = context.Set().Single(b => b.Name == "Building One"); + var buildingValues = getPropertyValues(context.Entry(building)); + + var dictionary = new Dictionary + { + { "Name", "Values End" }, + { "Shadow2", "Pine Walk" }, + }; + + buildingValues.SetValues(dictionary); + + Assert.Equal("Values End", buildingValues["Name"]); + Assert.Equal(1500000m, buildingValues["Value"]); + Assert.Equal(11, buildingValues["Shadow1"]); + Assert.Equal("Pine Walk", buildingValues["Shadow2"]); + + Assert.Equal("Values End", getValue(context.Entry(building), "Name")); + Assert.Equal(1500000m, getValue(context.Entry(building), "Value")); + Assert.Equal(11, getValue(context.Entry(building), "Shadow1")); + Assert.Equal("Pine Walk", getValue(context.Entry(building), "Shadow2")); + + Assert.True(context.Entry(building).Property("Name").IsModified); + Assert.False(context.Entry(building).Property("BuildingId").IsModified); + Assert.False(context.Entry(building).Property("Value").IsModified); + Assert.False(context.Entry(building).Property("Shadow1").IsModified); + Assert.True(context.Entry(building).Property("Shadow2").IsModified); + } + [ConditionalFact] public virtual void Current_values_can_be_set_from_dictionary_some_missing() { From 644422091417e7d462f9832f0f0782852270ad75 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 8 Sep 2021 07:51:15 +0100 Subject: [PATCH 053/346] Avoid stack overflow when saving multiple modified entities with the same key (#25897) Fixes #23043 --- .../Internal/InternalEntityEntry.cs | 23 +- .../GraphUpdates/GraphUpdatesTestBase.cs | 40 +- .../GraphUpdatesTestBaseMiscellaneous.cs | 55 +- .../GraphUpdatesSqlServerClientCascadeTest.cs | 41 + ...GraphUpdatesSqlServerClientNoActionTest.cs | 40 + .../GraphUpdatesSqlServerHiLoTest.cs | 31 + .../GraphUpdatesSqlServerIdentityTest.cs | 31 + .../GraphUpdatesSqlServerOwnedTest.cs | 505 +++++++++++++ .../GraphUpdates/GraphUpdatesSqlServerTest.cs | 714 ------------------ .../GraphUpdatesSqlServerTestBase.cs | 34 + .../GraphUpdatesSqlServerTptIdentityTest.cs | 81 ++ ...sSqliteChangedChangingNotificationsTest.cs | 32 + ...phUpdatesSqliteChangedNotificationsTest.cs | 32 + ...qliteFullWithOriginalsNotificationsTest.cs | 32 + ...hUpdatesSqliteSnapshotNotificationsTest.cs | 35 + .../GraphUpdates/GraphUpdatesSqliteTest.cs | 173 ----- .../GraphUpdatesSqliteTestBase.cs | 71 ++ 17 files changed, 1079 insertions(+), 891 deletions(-) create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerClientCascadeTest.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerClientNoActionTest.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerHiLoTest.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerIdentityTest.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerOwnedTest.cs delete mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTest.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTestBase.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTptIdentityTest.cs create mode 100644 test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteChangedChangingNotificationsTest.cs create mode 100644 test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteChangedNotificationsTest.cs create mode 100644 test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteFullWithOriginalsNotificationsTest.cs create mode 100644 test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteSnapshotNotificationsTest.cs delete mode 100644 test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTest.cs create mode 100644 test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTestBase.cs diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index b505052b521..8b67ffc8015 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -352,9 +352,28 @@ private void SetEntityState(EntityState oldState, EntityState newState, bool acc FireStateChanged(oldState); - if (newState == EntityState.Unchanged) + if (SharedIdentityEntry != null) { - SharedIdentityEntry?.SetEntityState(EntityState.Detached); + if (newState == EntityState.Unchanged) + { + SharedIdentityEntry.SetEntityState(EntityState.Detached); + } + else if (newState == EntityState.Modified + && SharedIdentityEntry.EntityState == EntityState.Modified) + { + if (StateManager.SensitiveLoggingEnabled) + { + throw new InvalidOperationException( + CoreStrings.IdentityConflictSensitive( + EntityType.DisplayName(), + this.BuildCurrentValuesString(EntityType.FindPrimaryKey()!.Properties))); + } + + throw new InvalidOperationException( + CoreStrings.IdentityConflict( + EntityType.DisplayName(), + EntityType.FindPrimaryKey()!.Properties.Format())); + } } if ((newState == EntityState.Deleted diff --git a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs index a859713275b..b37894d068c 100644 --- a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs +++ b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs @@ -477,6 +477,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con b.Property("EntityZId"); b.HasOne(e => e.EntityZ).WithMany().HasForeignKey("EntityZId").IsRequired(); }); + + modelBuilder.Entity(); } protected virtual object CreateFullGraph() @@ -3409,7 +3411,43 @@ protected class EntityZ : NotifyingEntity public long Id { get => _id; - set => _id = value; + set => SetWithNotify(value, ref _id); + } + } + + protected class City : NotifyingEntity + { + private int _id; + private ICollection _colleges = new ObservableHashSet(); + + public int Id + { + get => _id; + set => SetWithNotify(value, ref _id); + } + + public ICollection Colleges + { + get => _colleges; + set => SetWithNotify(value, ref _colleges); + } + } + + protected class College : NotifyingEntity + { + private int _id; + private int _cityId; + + public int Id + { + get => _id; + set => SetWithNotify(value, ref _id); + } + + public int CityId + { + get => _cityId; + set => SetWithNotify(value, ref _cityId); } } diff --git a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs index 243cceadf8b..63971570e01 100644 --- a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs +++ b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Utilities; using Xunit; // ReSharper disable AccessToDisposedClosure @@ -19,6 +18,60 @@ namespace Microsoft.EntityFrameworkCore public abstract partial class GraphUpdatesTestBase where TFixture : GraphUpdatesTestBase.GraphUpdatesFixtureBase, new() { + [ConditionalTheory] // Issue #23043 + [InlineData(false)] + [InlineData(true)] + public virtual async Task Saving_multiple_modified_entities_with_the_same_key_does_not_overflow(bool async) + { + await ExecuteWithStrategyInTransactionAsync( + async context => + { + var city = new City + { + Colleges = + { + new() + } + }; + + if (async) + { + await context.AddAsync(city); + await context.SaveChangesAsync(); + } + else + { + context.Add(city); + context.SaveChanges(); + } + }, + context => + { + var city = context.Set().Include(x => x.Colleges).Single(); + var college = city.Colleges.Single(); + + city.Colleges.Clear(); + city.Colleges.Add(new() { Id = college.Id }); + + if (Fixture.ForceClientNoAction) + { + Assert.Equal( + CoreStrings.RelationshipConceptualNullSensitive(nameof(City), nameof(College), $"{{CityId: {city.Id}}}"), + Assert.Throws( + () => context.Entry(college).State = EntityState.Modified).Message); + } + else + { + Assert.Equal( + CoreStrings.IdentityConflictSensitive(nameof(College), $"{{Id: {college.Id}}}"), + Assert.Throws( + () => context.Entry(college).State = EntityState.Modified).Message); + } + + return Task.CompletedTask; + }); + } + [ConditionalTheory] // Issue #22465 [InlineData(false)] [InlineData(true)] diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerClientCascadeTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerClientCascadeTest.cs new file mode 100644 index 00000000000..518d4b5e879 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerClientCascadeTest.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqlServerClientCascadeTest : GraphUpdatesSqlServerTestBase + { + public GraphUpdatesSqlServerClientCascadeTest(SqlServerFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + public override bool NoStoreCascades + => true; + + protected override string StoreName { get; } = "GraphClientCascadeUpdatesTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + foreach (var foreignKey in modelBuilder.Model + .GetEntityTypes() + .SelectMany(e => e.GetDeclaredForeignKeys()) + .Where(e => e.DeleteBehavior == DeleteBehavior.Cascade)) + { + foreignKey.DeleteBehavior = DeleteBehavior.ClientCascade; + } + } + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerClientNoActionTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerClientNoActionTest.cs new file mode 100644 index 00000000000..5ff422dc2a6 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerClientNoActionTest.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqlServerClientNoActionTest : GraphUpdatesSqlServerTestBase + { + public GraphUpdatesSqlServerClientNoActionTest(SqlServerFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + public override bool ForceClientNoAction + => true; + + protected override string StoreName { get; } = "GraphClientNoActionUpdatesTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + foreach (var foreignKey in modelBuilder.Model + .GetEntityTypes() + .SelectMany(e => e.GetDeclaredForeignKeys())) + { + foreignKey.DeleteBehavior = DeleteBehavior.ClientNoAction; + } + } + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerHiLoTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerHiLoTest.cs new file mode 100644 index 00000000000..36fa4be4ea7 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerHiLoTest.cs @@ -0,0 +1,31 @@ +// 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.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqlServerHiLoTest : GraphUpdatesSqlServerTestBase + { + public GraphUpdatesSqlServerHiLoTest(SqlServerFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + protected override string StoreName { get; } = "GraphHiLoUpdatesTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.UseHiLo(); + + base.OnModelCreating(modelBuilder, context); + } + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerIdentityTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerIdentityTest.cs new file mode 100644 index 00000000000..24594bef6bd --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerIdentityTest.cs @@ -0,0 +1,31 @@ +// 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.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqlServerIdentityTest : GraphUpdatesSqlServerTestBase + { + public GraphUpdatesSqlServerIdentityTest(SqlServerFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + protected override string StoreName { get; } = "GraphIdentityUpdatesTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.UseIdentityColumns(); + + base.OnModelCreating(modelBuilder, context); + } + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerOwnedTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerOwnedTest.cs new file mode 100644 index 00000000000..22a1bf23271 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerOwnedTest.cs @@ -0,0 +1,505 @@ +// 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.ChangeTracking; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqlServerOwnedTest : GraphUpdatesSqlServerTestBase + { + public GraphUpdatesSqlServerOwnedTest(SqlServerFixture fixture) + : base(fixture) + { + } + + // Owned dependents are always loaded + public override void Required_one_to_one_are_cascade_deleted_in_store( + CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) + { + } + + + public override void Required_one_to_one_with_alternate_key_are_cascade_deleted_in_store( + CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) + { + } + + public override void Required_one_to_one_relationships_are_one_to_one(CascadeTiming? deleteOrphansTiming) + { + } + + public override void Required_one_to_one_with_AK_relationships_are_one_to_one(CascadeTiming? deleteOrphansTiming) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + protected override string StoreName { get; } = "GraphOwnedUpdatesTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.Entity( + b => + { + b.Property(e => e.AlternateId).ValueGeneratedOnAdd(); + + // TODO: Owned inheritance support #9630 + b.HasMany(e => e.RequiredChildren) + .WithOne(e => e.Parent) + .HasForeignKey(e => e.ParentId); + + modelBuilder.Entity() + .HasMany(e => e.Children) + .WithOne(e => e.Parent) + .HasForeignKey(e => e.ParentId); + + modelBuilder.Entity(); + modelBuilder.Entity(); + modelBuilder.Entity(); + modelBuilder.Entity(); + + b.HasMany(e => e.OptionalChildren) + .WithOne(e => e.Parent) + .HasForeignKey(e => e.ParentId) + .OnDelete(DeleteBehavior.SetNull); + + b.OwnsOne(e => e.RequiredSingle, r => + { + r.WithOwner(e => e.Root) + .HasForeignKey(e => e.Id); + + r.OwnsOne(e => e.Single) + .WithOwner(e => e.Back) + .HasForeignKey(e => e.Id); + }); + + b.HasOne(e => e.OptionalSingle) + .WithOne(e => e.Root) + .HasForeignKey(e => e.RootId) + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne(e => e.OptionalSingleDerived) + .WithOne(e => e.DerivedRoot) + .HasForeignKey(e => e.DerivedRootId) + .OnDelete(DeleteBehavior.ClientSetNull); + + b.HasOne(e => e.OptionalSingleMoreDerived) + .WithOne(e => e.MoreDerivedRoot) + .HasForeignKey(e => e.MoreDerivedRootId) + .OnDelete(DeleteBehavior.ClientSetNull); + + // TODO: Owned inheritance support #9630 + b.HasOne(e => e.RequiredNonPkSingle) + .WithOne(e => e.Root) + .HasForeignKey(e => e.RootId); + + b.HasOne(e => e.RequiredNonPkSingleDerived) + .WithOne(e => e.DerivedRoot) + .HasForeignKey(e => e.DerivedRootId) + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne(e => e.RequiredNonPkSingleMoreDerived) + .WithOne(e => e.MoreDerivedRoot) + .HasForeignKey(e => e.MoreDerivedRootId) + .OnDelete(DeleteBehavior.Restrict); + + // TODO: Owned inheritance support #9630 + b.HasMany(e => e.RequiredChildrenAk) + .WithOne(e => e.Parent) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.ParentId); + + modelBuilder.Entity( + b => + { + b.Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + b.HasMany(e => e.Children) + .WithOne(e => e.Parent) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.ParentId); + + b.HasMany(e => e.CompositeChildren) + .WithOne(e => e.Parent) + .HasPrincipalKey( + e => new { e.Id, e.AlternateId }) + .HasForeignKey( + e => new { e.ParentId, e.ParentAlternateId }); + }); + + modelBuilder.Entity() + .Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity(); + modelBuilder.Entity(); + + b.HasMany(e => e.OptionalChildrenAk) + .WithOne(e => e.Parent) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.ParentId) + .OnDelete(DeleteBehavior.SetNull); + + b.OwnsOne(e => e.RequiredSingleAk, r => + { + r.WithOwner(e => e.Root) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.RootId); + + r.HasKey(e => e.Id); + + r.Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + r.OwnsOne(e => e.Single, r2 => + { + r2.WithOwner(e => e.Back) + .HasForeignKey(e => e.BackId) + .HasPrincipalKey(e => e.AlternateId); + + r2.HasKey(e => e.Id); + + r2.Property(e => e.Id) + .ValueGeneratedOnAdd(); + + r2.Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + r2.ToTable("RequiredSingleAk2"); + }); + + r.OwnsOne(e => e.SingleComposite, r2 => + { + r2.WithOwner(e => e.Back) + .HasForeignKey(e => new { e.BackId, e.BackAlternateId }) + .HasPrincipalKey(e => new { e.Id, e.AlternateId }); + + r2.HasKey(e => e.Id); + + r2.ToTable("RequiredSingleComposite2"); + }); + + // Table splitting using AK is not supported #23208 + r.ToTable("RequiredSingleAk1"); + }); + + b.HasOne(e => e.OptionalSingleAk) + .WithOne(e => e.Root) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.RootId) + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne(e => e.OptionalSingleAkDerived) + .WithOne(e => e.DerivedRoot) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.DerivedRootId) + .OnDelete(DeleteBehavior.ClientSetNull); + + b.HasOne(e => e.OptionalSingleAkMoreDerived) + .WithOne(e => e.MoreDerivedRoot) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.MoreDerivedRootId) + .OnDelete(DeleteBehavior.ClientSetNull); + + b.HasOne(e => e.RequiredNonPkSingleAk) + .WithOne(e => e.Root) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.RootId); + + b.HasOne(e => e.RequiredNonPkSingleAkDerived) + .WithOne(e => e.DerivedRoot) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.DerivedRootId) + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne(e => e.RequiredNonPkSingleAkMoreDerived) + .WithOne(e => e.MoreDerivedRoot) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.MoreDerivedRootId) + .OnDelete(DeleteBehavior.Restrict); + + b.HasMany(e => e.RequiredCompositeChildren) + .WithOne(e => e.Parent) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.ParentAlternateId); + }); + + modelBuilder.Entity( + b => + { + b.HasMany(e => e.Children) + .WithOne(e => e.Parent) + .HasForeignKey(e => e.ParentId) + .OnDelete(DeleteBehavior.SetNull); + + b.HasMany(e => e.CompositeChildren) + .WithOne(e => e.Parent2) + .HasForeignKey(e => new { e.Parent2Id }); + }); + + modelBuilder.Entity(); + modelBuilder.Entity(); + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity() + .HasOne(e => e.Single) + .WithOne(e => e.Back) + .HasForeignKey(e => e.BackId) + .OnDelete(DeleteBehavior.SetNull); + + modelBuilder.Entity( + b => + { + b.HasDiscriminator(e => e.Disc) + .HasValue(new MyDiscriminator(1)) + .HasValue(new MyDiscriminator(2)) + .HasValue(new MyDiscriminator(3)); + + b.Property(e => e.Disc) + .HasConversion( + v => v.Value, + v => new MyDiscriminator(v), + new ValueComparer( + (l, r) => l.Value == r.Value, + v => v.Value.GetHashCode(), + v => new MyDiscriminator(v.Value))) + .Metadata + .SetAfterSaveBehavior(PropertySaveBehavior.Save); + }); + + modelBuilder.Entity() + .HasOne(e => e.Single) + .WithOne(e => e.Back) + .HasForeignKey(e => e.BackId); + + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity( + b => + { + b.Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + b.HasOne(e => e.Single) + .WithOne(e => e.Back) + .HasForeignKey(e => e.BackId) + .HasPrincipalKey(e => e.AlternateId); + }); + + modelBuilder.Entity( + b => + { + b.Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + b.HasMany(e => e.Children) + .WithOne(e => e.Parent) + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.ParentId) + .OnDelete(DeleteBehavior.SetNull); + + b.HasMany(e => e.CompositeChildren) + .WithOne(e => e.Parent) + .HasPrincipalKey( + e => new { e.Id, e.AlternateId }) + .HasForeignKey( + e => new { e.ParentId, e.ParentAlternateId }); + }); + + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity() + .Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity() + .Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity( + b => + { + b.Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + b.HasOne(e => e.Single) + .WithOne(e => e.Back) + .HasForeignKey(e => e.BackId) + .HasPrincipalKey(e => e.AlternateId) + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne(e => e.SingleComposite) + .WithOne(e => e.Back) + .HasForeignKey( + e => new { e.BackId, e.ParentAlternateId }) + .HasPrincipalKey( + e => new { e.Id, e.AlternateId }); + }); + + modelBuilder.Entity() + .Property(e => e.AlternateId) + .ValueGeneratedOnAdd(); + + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity( + eb => + { + eb.Property(e => e.Id).ValueGeneratedNever(); + + eb.HasKey( + e => new { e.Id, e.ParentAlternateId }); + + eb.HasMany(e => e.CompositeChildren) + .WithOne(e => e.Parent) + .HasPrincipalKey( + e => new { e.Id, e.ParentAlternateId }) + .HasForeignKey( + e => new { e.ParentId, e.ParentAlternateId }); + }); + + modelBuilder.Entity( + eb => + { + eb.Property(e => e.Id).ValueGeneratedNever(); + + eb.HasKey( + e => new { e.Id, e.ParentAlternateId }); + + eb.HasOne(e => e.Root) + .WithMany() + .HasPrincipalKey(e => e.AlternateId) + .HasForeignKey(e => e.ParentAlternateId); + }); + + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity(); + + modelBuilder.Entity() + .HasMany(qt => qt.Choices) + .WithOne() + .HasForeignKey(tc => tc.QuestTaskId); + + modelBuilder.Entity() + .HasMany(hat => hat.Choices) + .WithOne() + .HasForeignKey(tc => tc.QuestTaskId); + + modelBuilder.Entity(); + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity(); + modelBuilder.Entity(); + + modelBuilder.Entity() + .HasIndex(e => e.BarCode) + .IsUnique(); + + modelBuilder.Entity(builder => + { + builder.HasMany(x => x.Dependants).WithOne(x => x.Root) + .HasForeignKey(x => new { x.RootId }) + .HasPrincipalKey(x => x.Id) + .OnDelete(DeleteBehavior.Cascade); + + builder.HasMany(x => x.Parents).WithOne(x => x.Root) + .HasForeignKey(x => new { x.RootId }) + .HasPrincipalKey(x => x.Id) + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity(builder => + { + builder.HasOne(x => x.Dependant).WithOne(x => x!.Parent).IsRequired(false) + .HasForeignKey(x => new { x.RootId, x.DependantId }) + .HasPrincipalKey(x => new { x.RootId, x.Id }) + .OnDelete(DeleteBehavior.ClientSetNull); + }); + + modelBuilder.Entity(); + + modelBuilder.Entity(); + + modelBuilder.Entity( + b => + { + b.Navigation(e => e.Owned).IsRequired(); + b.Navigation(e => e.OwnedWithKey).IsRequired(); + + b.OwnsMany( + e => e.OwnedCollectionPrivateKey, + b => b.HasKey("OwnerWithKeyedCollectionId", "PrivateKey")); + }); + + modelBuilder.Entity( + b => + { + b.Property(e => e.Id).ValueGeneratedNever(); + + b.OwnsOne( + e => e.Owned, + b => b.Property("OwnerNoKeyGenerationId").ValueGeneratedNever()); + b.OwnsMany( + e => e.OwnedCollection, + b => + { + b.Property("OwnedNoKeyGenerationId").ValueGeneratedNever(); + b.Property("OwnerNoKeyGenerationId").ValueGeneratedNever(); + }); + }); + + modelBuilder.Entity().HasData( + new Provider { Id = "prov1" }, + new Provider { Id = "prov2" }); + + modelBuilder.Entity().HasData( + new Partner { Id = "partner1" }); + + modelBuilder.Entity( + b => + { + b.HasOne(p => p.Partner).WithMany().IsRequired().HasForeignKey("PartnerId"); + b.HasOne().WithMany().IsRequired().HasForeignKey("ProviderId"); + + b.HasDiscriminator("ProviderId") + .HasValue("prov1") + .HasValue("prov2"); + + b.HasKey("PartnerId", "ProviderId"); + }); + + modelBuilder.Entity( + b => + { + b.Property("EntityZId"); + b.HasOne(e => e.EntityZ).WithMany().HasForeignKey("EntityZId").IsRequired(); + }); + + modelBuilder.Entity(); + } + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTest.cs deleted file mode 100644 index 6b53f70486a..00000000000 --- a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTest.cs +++ /dev/null @@ -1,714 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Linq; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace Microsoft.EntityFrameworkCore -{ - public class GraphUpdatesSqlServerTest - { - public class ClientCascade : GraphUpdatesSqlServerTestBase - { - public ClientCascade(SqlServerFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase - { - public override bool NoStoreCascades - => true; - - protected override string StoreName { get; } = "GraphClientCascadeUpdatesTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - - foreach (var foreignKey in modelBuilder.Model - .GetEntityTypes() - .SelectMany(e => e.GetDeclaredForeignKeys()) - .Where(e => e.DeleteBehavior == DeleteBehavior.Cascade)) - { - foreignKey.DeleteBehavior = DeleteBehavior.ClientCascade; - } - } - } - } - - public class ClientNoAction : GraphUpdatesSqlServerTestBase - { - public ClientNoAction(SqlServerFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase - { - public override bool ForceClientNoAction - => true; - - protected override string StoreName { get; } = "GraphClientNoActionUpdatesTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - - foreach (var foreignKey in modelBuilder.Model - .GetEntityTypes() - .SelectMany(e => e.GetDeclaredForeignKeys())) - { - foreignKey.DeleteBehavior = DeleteBehavior.ClientNoAction; - } - } - } - } - - public class TptIdentity : GraphUpdatesSqlServerTestBase - { - public TptIdentity(SqlServerFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase - { - protected override string StoreName { get; } = "GraphTptIdentityUpdatesTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.UseIdentityColumns(); - - base.OnModelCreating(modelBuilder, context); - - modelBuilder.Entity().ToTable(nameof(Root)); - modelBuilder.Entity().ToTable(nameof(Required1)); - modelBuilder.Entity().ToTable(nameof(Required1Derived)); - modelBuilder.Entity().ToTable(nameof(Required1MoreDerived)); - modelBuilder.Entity().ToTable(nameof(Required2Derived)); - modelBuilder.Entity().ToTable(nameof(Required2MoreDerived)); - modelBuilder.Entity().ToTable(nameof(Optional1)); - modelBuilder.Entity().ToTable(nameof(Optional1Derived)); - modelBuilder.Entity().ToTable(nameof(Optional1MoreDerived)); - modelBuilder.Entity().ToTable(nameof(Optional2Derived)); - modelBuilder.Entity().ToTable(nameof(Optional2MoreDerived)); - modelBuilder.Entity().ToTable(nameof(RequiredSingle1)); - modelBuilder.Entity().ToTable(nameof(OptionalSingle1)); - modelBuilder.Entity().ToTable(nameof(OptionalSingle2)); - modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingle1)); - modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingle2Derived)); - modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingle2MoreDerived)); - modelBuilder.Entity().ToTable(nameof(RequiredAk1)); - modelBuilder.Entity().ToTable(nameof(RequiredAk1Derived)); - modelBuilder.Entity().ToTable(nameof(RequiredAk1MoreDerived)); - modelBuilder.Entity().ToTable(nameof(OptionalAk1)); - modelBuilder.Entity().ToTable(nameof(OptionalAk1Derived)); - modelBuilder.Entity().ToTable(nameof(OptionalAk1MoreDerived)); - modelBuilder.Entity().ToTable(nameof(RequiredSingleAk1)); - modelBuilder.Entity().ToTable(nameof(OptionalSingleAk1)); - modelBuilder.Entity().ToTable(nameof(OptionalSingleAk2Derived)); - modelBuilder.Entity().ToTable(nameof(OptionalSingleAk2MoreDerived)); - modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingleAk1)); - modelBuilder.Entity().ToTable(nameof(RequiredAk2)); - modelBuilder.Entity().ToTable(nameof(RequiredAk2Derived)); - modelBuilder.Entity().ToTable(nameof(RequiredAk2MoreDerived)); - modelBuilder.Entity().ToTable(nameof(OptionalAk2)); - modelBuilder.Entity().ToTable(nameof(OptionalAk2Derived)); - modelBuilder.Entity().ToTable(nameof(OptionalAk2MoreDerived)); - modelBuilder.Entity().ToTable(nameof(RequiredSingleAk2)); - modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingleAk2)); - modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingleAk2Derived)); - modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingleAk2MoreDerived)); - modelBuilder.Entity().ToTable(nameof(OptionalSingleAk2)); - modelBuilder.Entity().ToTable(nameof(RequiredComposite1)); - modelBuilder.Entity().ToTable(nameof(OptionalOverlapping2)); - modelBuilder.Entity().ToTable(nameof(BadCustomer)); - modelBuilder.Entity().ToTable(nameof(BadOrder)); - modelBuilder.Entity().ToTable(nameof(TaskChoice)); - modelBuilder.Entity().ToTable(nameof(ParentAsAChild)); - modelBuilder.Entity().ToTable(nameof(ChildAsAParent)); - modelBuilder.Entity().ToTable(nameof(Poost)); - modelBuilder.Entity().ToTable(nameof(Bloog)); - modelBuilder.Entity().ToTable(nameof(Produce)); - } - } - } - - public class Identity : GraphUpdatesSqlServerTestBase - { - public Identity(SqlServerFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase - { - protected override string StoreName { get; } = "GraphIdentityUpdatesTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.UseIdentityColumns(); - - base.OnModelCreating(modelBuilder, context); - } - } - } - - public class HiLo : GraphUpdatesSqlServerTestBase - { - public HiLo(SqlServerFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase - { - protected override string StoreName { get; } = "GraphHiLoUpdatesTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.UseHiLo(); - - base.OnModelCreating(modelBuilder, context); - } - } - } - - public class Owned : GraphUpdatesSqlServerTestBase - { - public Owned(SqlServerFixture fixture) - : base(fixture) - { - } - - // Owned dependents are always loaded - public override void Required_one_to_one_are_cascade_deleted_in_store( - CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) - { - } - - - public override void Required_one_to_one_with_alternate_key_are_cascade_deleted_in_store( - CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) - { - } - - public override void Required_one_to_one_relationships_are_one_to_one(CascadeTiming? deleteOrphansTiming) - { - } - - public override void Required_one_to_one_with_AK_relationships_are_one_to_one(CascadeTiming? deleteOrphansTiming) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase - { - protected override string StoreName { get; } = "GraphOwnedUpdatesTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.Entity( - b => - { - b.Property(e => e.AlternateId).ValueGeneratedOnAdd(); - - // TODO: Owned inheritance support #9630 - b.HasMany(e => e.RequiredChildren) - .WithOne(e => e.Parent) - .HasForeignKey(e => e.ParentId); - - modelBuilder.Entity() - .HasMany(e => e.Children) - .WithOne(e => e.Parent) - .HasForeignKey(e => e.ParentId); - - modelBuilder.Entity(); - modelBuilder.Entity(); - modelBuilder.Entity(); - modelBuilder.Entity(); - - b.HasMany(e => e.OptionalChildren) - .WithOne(e => e.Parent) - .HasForeignKey(e => e.ParentId) - .OnDelete(DeleteBehavior.SetNull); - - b.OwnsOne(e => e.RequiredSingle, r => - { - r.WithOwner(e => e.Root) - .HasForeignKey(e => e.Id); - - r.OwnsOne(e => e.Single) - .WithOwner(e => e.Back) - .HasForeignKey(e => e.Id); - }); - - b.HasOne(e => e.OptionalSingle) - .WithOne(e => e.Root) - .HasForeignKey(e => e.RootId) - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne(e => e.OptionalSingleDerived) - .WithOne(e => e.DerivedRoot) - .HasForeignKey(e => e.DerivedRootId) - .OnDelete(DeleteBehavior.ClientSetNull); - - b.HasOne(e => e.OptionalSingleMoreDerived) - .WithOne(e => e.MoreDerivedRoot) - .HasForeignKey(e => e.MoreDerivedRootId) - .OnDelete(DeleteBehavior.ClientSetNull); - - // TODO: Owned inheritance support #9630 - b.HasOne(e => e.RequiredNonPkSingle) - .WithOne(e => e.Root) - .HasForeignKey(e => e.RootId); - - b.HasOne(e => e.RequiredNonPkSingleDerived) - .WithOne(e => e.DerivedRoot) - .HasForeignKey(e => e.DerivedRootId) - .OnDelete(DeleteBehavior.Restrict); - - b.HasOne(e => e.RequiredNonPkSingleMoreDerived) - .WithOne(e => e.MoreDerivedRoot) - .HasForeignKey(e => e.MoreDerivedRootId) - .OnDelete(DeleteBehavior.Restrict); - - // TODO: Owned inheritance support #9630 - b.HasMany(e => e.RequiredChildrenAk) - .WithOne(e => e.Parent) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.ParentId); - - modelBuilder.Entity( - b => - { - b.Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - b.HasMany(e => e.Children) - .WithOne(e => e.Parent) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.ParentId); - - b.HasMany(e => e.CompositeChildren) - .WithOne(e => e.Parent) - .HasPrincipalKey( - e => new { e.Id, e.AlternateId }) - .HasForeignKey( - e => new { e.ParentId, e.ParentAlternateId }); - }); - - modelBuilder.Entity() - .Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity(); - modelBuilder.Entity(); - - b.HasMany(e => e.OptionalChildrenAk) - .WithOne(e => e.Parent) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.ParentId) - .OnDelete(DeleteBehavior.SetNull); - - b.OwnsOne(e => e.RequiredSingleAk, r => - { - r.WithOwner(e => e.Root) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.RootId); - - r.HasKey(e => e.Id); - - r.Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - r.OwnsOne(e => e.Single, r2 => - { - r2.WithOwner(e => e.Back) - .HasForeignKey(e => e.BackId) - .HasPrincipalKey(e => e.AlternateId); - - r2.HasKey(e => e.Id); - - r2.Property(e => e.Id) - .ValueGeneratedOnAdd(); - - r2.Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - r2.ToTable("RequiredSingleAk2"); - }); - - r.OwnsOne(e => e.SingleComposite, r2 => - { - r2.WithOwner(e => e.Back) - .HasForeignKey(e => new { e.BackId, e.BackAlternateId }) - .HasPrincipalKey(e => new { e.Id, e.AlternateId }); - - r2.HasKey(e => e.Id); - - r2.ToTable("RequiredSingleComposite2"); - }); - - // Table splitting using AK is not supported #23208 - r.ToTable("RequiredSingleAk1"); - }); - - b.HasOne(e => e.OptionalSingleAk) - .WithOne(e => e.Root) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.RootId) - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne(e => e.OptionalSingleAkDerived) - .WithOne(e => e.DerivedRoot) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.DerivedRootId) - .OnDelete(DeleteBehavior.ClientSetNull); - - b.HasOne(e => e.OptionalSingleAkMoreDerived) - .WithOne(e => e.MoreDerivedRoot) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.MoreDerivedRootId) - .OnDelete(DeleteBehavior.ClientSetNull); - - b.HasOne(e => e.RequiredNonPkSingleAk) - .WithOne(e => e.Root) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.RootId); - - b.HasOne(e => e.RequiredNonPkSingleAkDerived) - .WithOne(e => e.DerivedRoot) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.DerivedRootId) - .OnDelete(DeleteBehavior.Restrict); - - b.HasOne(e => e.RequiredNonPkSingleAkMoreDerived) - .WithOne(e => e.MoreDerivedRoot) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.MoreDerivedRootId) - .OnDelete(DeleteBehavior.Restrict); - - b.HasMany(e => e.RequiredCompositeChildren) - .WithOne(e => e.Parent) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.ParentAlternateId); - }); - - modelBuilder.Entity( - b => - { - b.HasMany(e => e.Children) - .WithOne(e => e.Parent) - .HasForeignKey(e => e.ParentId) - .OnDelete(DeleteBehavior.SetNull); - - b.HasMany(e => e.CompositeChildren) - .WithOne(e => e.Parent2) - .HasForeignKey(e => new { e.Parent2Id }); - }); - - modelBuilder.Entity(); - modelBuilder.Entity(); - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity() - .HasOne(e => e.Single) - .WithOne(e => e.Back) - .HasForeignKey(e => e.BackId) - .OnDelete(DeleteBehavior.SetNull); - - modelBuilder.Entity( - b => - { - b.HasDiscriminator(e => e.Disc) - .HasValue(new MyDiscriminator(1)) - .HasValue(new MyDiscriminator(2)) - .HasValue(new MyDiscriminator(3)); - - b.Property(e => e.Disc) - .HasConversion( - v => v.Value, - v => new MyDiscriminator(v), - new ValueComparer( - (l, r) => l.Value == r.Value, - v => v.Value.GetHashCode(), - v => new MyDiscriminator(v.Value))) - .Metadata - .SetAfterSaveBehavior(PropertySaveBehavior.Save); - }); - - modelBuilder.Entity() - .HasOne(e => e.Single) - .WithOne(e => e.Back) - .HasForeignKey(e => e.BackId); - - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity( - b => - { - b.Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - b.HasOne(e => e.Single) - .WithOne(e => e.Back) - .HasForeignKey(e => e.BackId) - .HasPrincipalKey(e => e.AlternateId); - }); - - modelBuilder.Entity( - b => - { - b.Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - b.HasMany(e => e.Children) - .WithOne(e => e.Parent) - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.ParentId) - .OnDelete(DeleteBehavior.SetNull); - - b.HasMany(e => e.CompositeChildren) - .WithOne(e => e.Parent) - .HasPrincipalKey( - e => new { e.Id, e.AlternateId }) - .HasForeignKey( - e => new { e.ParentId, e.ParentAlternateId }); - }); - - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity() - .Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity() - .Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity( - b => - { - b.Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - b.HasOne(e => e.Single) - .WithOne(e => e.Back) - .HasForeignKey(e => e.BackId) - .HasPrincipalKey(e => e.AlternateId) - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne(e => e.SingleComposite) - .WithOne(e => e.Back) - .HasForeignKey( - e => new { e.BackId, e.ParentAlternateId }) - .HasPrincipalKey( - e => new { e.Id, e.AlternateId }); - }); - - modelBuilder.Entity() - .Property(e => e.AlternateId) - .ValueGeneratedOnAdd(); - - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity( - eb => - { - eb.Property(e => e.Id).ValueGeneratedNever(); - - eb.HasKey( - e => new { e.Id, e.ParentAlternateId }); - - eb.HasMany(e => e.CompositeChildren) - .WithOne(e => e.Parent) - .HasPrincipalKey( - e => new { e.Id, e.ParentAlternateId }) - .HasForeignKey( - e => new { e.ParentId, e.ParentAlternateId }); - }); - - modelBuilder.Entity( - eb => - { - eb.Property(e => e.Id).ValueGeneratedNever(); - - eb.HasKey( - e => new { e.Id, e.ParentAlternateId }); - - eb.HasOne(e => e.Root) - .WithMany() - .HasPrincipalKey(e => e.AlternateId) - .HasForeignKey(e => e.ParentAlternateId); - }); - - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity(); - - modelBuilder.Entity() - .HasMany(qt => qt.Choices) - .WithOne() - .HasForeignKey(tc => tc.QuestTaskId); - - modelBuilder.Entity() - .HasMany(hat => hat.Choices) - .WithOne() - .HasForeignKey(tc => tc.QuestTaskId); - - modelBuilder.Entity(); - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity(); - modelBuilder.Entity(); - - modelBuilder.Entity() - .HasIndex(e => e.BarCode) - .IsUnique(); - - modelBuilder.Entity(builder => - { - builder.HasMany(x => x.Dependants).WithOne(x => x.Root) - .HasForeignKey(x => new { x.RootId }) - .HasPrincipalKey(x => x.Id) - .OnDelete(DeleteBehavior.Cascade); - - builder.HasMany(x => x.Parents).WithOne(x => x.Root) - .HasForeignKey(x => new { x.RootId }) - .HasPrincipalKey(x => x.Id) - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity(builder => - { - builder.HasOne(x => x.Dependant).WithOne(x => x!.Parent).IsRequired(false) - .HasForeignKey(x => new { x.RootId, x.DependantId }) - .HasPrincipalKey(x => new { x.RootId, x.Id }) - .OnDelete(DeleteBehavior.ClientSetNull); - }); - - modelBuilder.Entity(); - - modelBuilder.Entity(); - - modelBuilder.Entity( - b => - { - b.Navigation(e => e.Owned).IsRequired(); - b.Navigation(e => e.OwnedWithKey).IsRequired(); - - b.OwnsMany( - e => e.OwnedCollectionPrivateKey, - b => b.HasKey("OwnerWithKeyedCollectionId", "PrivateKey")); - }); - - modelBuilder.Entity( - b => - { - b.Property(e => e.Id).ValueGeneratedNever(); - - b.OwnsOne( - e => e.Owned, - b => b.Property("OwnerNoKeyGenerationId").ValueGeneratedNever()); - b.OwnsMany( - e => e.OwnedCollection, - b => - { - b.Property("OwnedNoKeyGenerationId").ValueGeneratedNever(); - b.Property("OwnerNoKeyGenerationId").ValueGeneratedNever(); - }); - }); - - modelBuilder.Entity().HasData( - new Provider { Id = "prov1" }, - new Provider { Id = "prov2" }); - - modelBuilder.Entity().HasData( - new Partner { Id = "partner1" }); - - modelBuilder.Entity( - b => - { - b.HasOne(p => p.Partner).WithMany().IsRequired().HasForeignKey("PartnerId"); - b.HasOne().WithMany().IsRequired().HasForeignKey("ProviderId"); - - b.HasDiscriminator("ProviderId") - .HasValue("prov1") - .HasValue("prov2"); - - b.HasKey("PartnerId", "ProviderId"); - }); - - modelBuilder.Entity( - b => - { - b.Property("EntityZId"); - b.HasOne(e => e.EntityZ).WithMany().HasForeignKey("EntityZId").IsRequired(); - }); - } - } - } - - public abstract class GraphUpdatesSqlServerTestBase : GraphUpdatesTestBase - where TFixture : GraphUpdatesSqlServerTestBase.GraphUpdatesSqlServerFixtureBase, new() - { - protected GraphUpdatesSqlServerTestBase(TFixture fixture) - : base(fixture) - { - } - - protected override IQueryable ModifyQueryRoot(IQueryable query) - => query.AsSplitQuery(); - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public abstract class GraphUpdatesSqlServerFixtureBase : GraphUpdatesFixtureBase - { - public TestSqlLoggerFactory TestSqlLoggerFactory - => (TestSqlLoggerFactory)ListLoggerFactory; - - protected override ITestStoreFactory TestStoreFactory - => SqlServerTestStoreFactory.Instance; - } - } - } -} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTestBase.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTestBase.cs new file mode 100644 index 00000000000..f3c4ecbed18 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTestBase.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace Microsoft.EntityFrameworkCore +{ + public abstract class GraphUpdatesSqlServerTestBase : GraphUpdatesTestBase + where TFixture : GraphUpdatesSqlServerTestBase.GraphUpdatesSqlServerFixtureBase, new() + { + protected GraphUpdatesSqlServerTestBase(TFixture fixture) + : base(fixture) + { + } + + protected override IQueryable ModifyQueryRoot(IQueryable query) + => query.AsSplitQuery(); + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public abstract class GraphUpdatesSqlServerFixtureBase : GraphUpdatesFixtureBase + { + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + + protected override ITestStoreFactory TestStoreFactory + => SqlServerTestStoreFactory.Instance; + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTptIdentityTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTptIdentityTest.cs new file mode 100644 index 00000000000..16c8645d8a9 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTptIdentityTest.cs @@ -0,0 +1,81 @@ +// 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.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqlServerTptIdentityTest : GraphUpdatesSqlServerTestBase + { + public GraphUpdatesSqlServerTptIdentityTest(SqlServerFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + protected override string StoreName { get; } = "GraphTptIdentityUpdatesTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.UseIdentityColumns(); + + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity().ToTable(nameof(Root)); + modelBuilder.Entity().ToTable(nameof(Required1)); + modelBuilder.Entity().ToTable(nameof(Required1Derived)); + modelBuilder.Entity().ToTable(nameof(Required1MoreDerived)); + modelBuilder.Entity().ToTable(nameof(Required2Derived)); + modelBuilder.Entity().ToTable(nameof(Required2MoreDerived)); + modelBuilder.Entity().ToTable(nameof(Optional1)); + modelBuilder.Entity().ToTable(nameof(Optional1Derived)); + modelBuilder.Entity().ToTable(nameof(Optional1MoreDerived)); + modelBuilder.Entity().ToTable(nameof(Optional2Derived)); + modelBuilder.Entity().ToTable(nameof(Optional2MoreDerived)); + modelBuilder.Entity().ToTable(nameof(RequiredSingle1)); + modelBuilder.Entity().ToTable(nameof(OptionalSingle1)); + modelBuilder.Entity().ToTable(nameof(OptionalSingle2)); + modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingle1)); + modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingle2Derived)); + modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingle2MoreDerived)); + modelBuilder.Entity().ToTable(nameof(RequiredAk1)); + modelBuilder.Entity().ToTable(nameof(RequiredAk1Derived)); + modelBuilder.Entity().ToTable(nameof(RequiredAk1MoreDerived)); + modelBuilder.Entity().ToTable(nameof(OptionalAk1)); + modelBuilder.Entity().ToTable(nameof(OptionalAk1Derived)); + modelBuilder.Entity().ToTable(nameof(OptionalAk1MoreDerived)); + modelBuilder.Entity().ToTable(nameof(RequiredSingleAk1)); + modelBuilder.Entity().ToTable(nameof(OptionalSingleAk1)); + modelBuilder.Entity().ToTable(nameof(OptionalSingleAk2Derived)); + modelBuilder.Entity().ToTable(nameof(OptionalSingleAk2MoreDerived)); + modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingleAk1)); + modelBuilder.Entity().ToTable(nameof(RequiredAk2)); + modelBuilder.Entity().ToTable(nameof(RequiredAk2Derived)); + modelBuilder.Entity().ToTable(nameof(RequiredAk2MoreDerived)); + modelBuilder.Entity().ToTable(nameof(OptionalAk2)); + modelBuilder.Entity().ToTable(nameof(OptionalAk2Derived)); + modelBuilder.Entity().ToTable(nameof(OptionalAk2MoreDerived)); + modelBuilder.Entity().ToTable(nameof(RequiredSingleAk2)); + modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingleAk2)); + modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingleAk2Derived)); + modelBuilder.Entity().ToTable(nameof(RequiredNonPkSingleAk2MoreDerived)); + modelBuilder.Entity().ToTable(nameof(OptionalSingleAk2)); + modelBuilder.Entity().ToTable(nameof(RequiredComposite1)); + modelBuilder.Entity().ToTable(nameof(OptionalOverlapping2)); + modelBuilder.Entity().ToTable(nameof(BadCustomer)); + modelBuilder.Entity().ToTable(nameof(BadOrder)); + modelBuilder.Entity().ToTable(nameof(TaskChoice)); + modelBuilder.Entity().ToTable(nameof(ParentAsAChild)); + modelBuilder.Entity().ToTable(nameof(ChildAsAParent)); + modelBuilder.Entity().ToTable(nameof(Poost)); + modelBuilder.Entity().ToTable(nameof(Bloog)); + modelBuilder.Entity().ToTable(nameof(Produce)); + } + } + } +} diff --git a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteChangedChangingNotificationsTest.cs b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteChangedChangingNotificationsTest.cs new file mode 100644 index 00000000000..fd631e590aa --- /dev/null +++ b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteChangedChangingNotificationsTest.cs @@ -0,0 +1,32 @@ +// 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.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqliteChangedChangingNotificationsTest + : GraphUpdatesSqliteTestBase + { + public GraphUpdatesSqliteChangedChangingNotificationsTest(SqliteFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqliteFixture : GraphUpdatesSqliteFixtureBase + { + protected override string StoreName { get; } = "GraphUpdatesChangedChangingTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotifications); + + base.OnModelCreating(modelBuilder, context); + } + } + } +} diff --git a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteChangedNotificationsTest.cs b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteChangedNotificationsTest.cs new file mode 100644 index 00000000000..ace09cec039 --- /dev/null +++ b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteChangedNotificationsTest.cs @@ -0,0 +1,32 @@ +// 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.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqliteChangedNotificationsTest + : GraphUpdatesSqliteTestBase + { + public GraphUpdatesSqliteChangedNotificationsTest(SqliteFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqliteFixture : GraphUpdatesSqliteFixtureBase + { + protected override string StoreName { get; } = "GraphUpdatesChangedTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangedNotifications); + + base.OnModelCreating(modelBuilder, context); + } + } + } +} diff --git a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteFullWithOriginalsNotificationsTest.cs b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteFullWithOriginalsNotificationsTest.cs new file mode 100644 index 00000000000..1f9fe02b800 --- /dev/null +++ b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteFullWithOriginalsNotificationsTest.cs @@ -0,0 +1,32 @@ +// 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.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqliteFullWithOriginalsNotificationsTest + : GraphUpdatesSqliteTestBase + { + public GraphUpdatesSqliteFullWithOriginalsNotificationsTest(SqliteFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqliteFixture : GraphUpdatesSqliteFixtureBase + { + protected override string StoreName { get; } = "GraphUpdatesFullWithOriginalsTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotificationsWithOriginalValues); + + base.OnModelCreating(modelBuilder, context); + } + } + } +} diff --git a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteSnapshotNotificationsTest.cs b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteSnapshotNotificationsTest.cs new file mode 100644 index 00000000000..40d67a0dd5b --- /dev/null +++ b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteSnapshotNotificationsTest.cs @@ -0,0 +1,35 @@ +// 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.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqliteSnapshotNotificationsTest + : GraphUpdatesSqliteTestBase + { + public GraphUpdatesSqliteSnapshotNotificationsTest(SqliteFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class SqliteFixture : GraphUpdatesSqliteFixtureBase + { + protected override string StoreName { get; } = "GraphUpdatesSnapshotTest"; + + protected override bool AutoDetectChanges + => true; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.Snapshot); + + base.OnModelCreating(modelBuilder, context); + } + } + } +} diff --git a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTest.cs deleted file mode 100644 index f4ab032ab65..00000000000 --- a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTest.cs +++ /dev/null @@ -1,173 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Xunit; - -namespace Microsoft.EntityFrameworkCore -{ - public class GraphUpdatesSqliteTest - { - public class ChangedChangingNotifications - : GraphUpdatesSqliteTestBase - { - public ChangedChangingNotifications(SqliteFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqliteFixture : GraphUpdatesSqliteFixtureBase - { - protected override string StoreName { get; } = "GraphUpdatesChangedChangingTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotifications); - - base.OnModelCreating(modelBuilder, context); - } - } - } - - public class ChangedNotifications - : GraphUpdatesSqliteTestBase - { - public ChangedNotifications(SqliteFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqliteFixture : GraphUpdatesSqliteFixtureBase - { - protected override string StoreName { get; } = "GraphUpdatesChangedTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangedNotifications); - - base.OnModelCreating(modelBuilder, context); - } - } - } - - public class FullWithOriginalsNotifications - : GraphUpdatesSqliteTestBase - { - public FullWithOriginalsNotifications(SqliteFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqliteFixture : GraphUpdatesSqliteFixtureBase - { - protected override string StoreName { get; } = "GraphUpdatesFullWithOriginalsTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotificationsWithOriginalValues); - - base.OnModelCreating(modelBuilder, context); - } - } - } - - public class SnapshotNotifications - : GraphUpdatesSqliteTestBase - { - public SnapshotNotifications(SqliteFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public class SqliteFixture : GraphUpdatesSqliteFixtureBase - { - protected override string StoreName { get; } = "GraphUpdatesSnapshotTest"; - - protected override bool AutoDetectChanges - => true; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.Snapshot); - - base.OnModelCreating(modelBuilder, context); - } - } - } - - public abstract class GraphUpdatesSqliteTestBase : GraphUpdatesTestBase - where TFixture : GraphUpdatesSqliteTestBase.GraphUpdatesSqliteFixtureBase, new() - { - protected GraphUpdatesSqliteTestBase(TFixture fixture) - : base(fixture) - { - } - - [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] - public override Task Update_principal_with_shadow_key_owned_collection_throws(bool async) - => Task.CompletedTask; - - [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] - public override Task Delete_principal_with_shadow_key_owned_collection_throws(bool async) - => Task.CompletedTask; - - [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] - public override Task Clearing_shadow_key_owned_collection_throws(bool async, bool useUpdate, bool addNew) - => Task.CompletedTask; - - [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] - public override Task Update_principal_with_CLR_key_owned_collection(bool async) - => Task.CompletedTask; - - [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] - public override Task Delete_principal_with_CLR_key_owned_collection(bool async) - => Task.CompletedTask; - - [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] - public override Task Clearing_CLR_key_owned_collection(bool async, bool useUpdate, bool addNew) - => Task.CompletedTask; - - protected override IQueryable ModifyQueryRoot(IQueryable query) - => query.AsSplitQuery(); - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public abstract class GraphUpdatesSqliteFixtureBase : GraphUpdatesFixtureBase - { - public TestSqlLoggerFactory TestSqlLoggerFactory - => (TestSqlLoggerFactory)ListLoggerFactory; - - protected override ITestStoreFactory TestStoreFactory - => SqliteTestStoreFactory.Instance; - - protected virtual bool AutoDetectChanges - => false; - - public override PoolableDbContext CreateContext() - { - var context = base.CreateContext(); - context.ChangeTracker.AutoDetectChangesEnabled = AutoDetectChanges; - - return context; - } - } - } - } -} diff --git a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTestBase.cs b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTestBase.cs new file mode 100644 index 00000000000..ce1ce3c220e --- /dev/null +++ b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTestBase.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace Microsoft.EntityFrameworkCore +{ + public abstract class GraphUpdatesSqliteTestBase : GraphUpdatesTestBase + where TFixture : GraphUpdatesSqliteTestBase.GraphUpdatesSqliteFixtureBase, new() + { + protected GraphUpdatesSqliteTestBase(TFixture fixture) + : base(fixture) + { + } + + [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] + public override Task Update_principal_with_shadow_key_owned_collection_throws(bool async) + => Task.CompletedTask; + + [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] + public override Task Delete_principal_with_shadow_key_owned_collection_throws(bool async) + => Task.CompletedTask; + + [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] + public override Task Clearing_shadow_key_owned_collection_throws(bool async, bool useUpdate, bool addNew) + => Task.CompletedTask; + + [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] + public override Task Update_principal_with_CLR_key_owned_collection(bool async) + => Task.CompletedTask; + + [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] + public override Task Delete_principal_with_CLR_key_owned_collection(bool async) + => Task.CompletedTask; + + [ConditionalTheory(Skip = "Default owned collection pattern does not work with SQLite due to composite key.")] + public override Task Clearing_CLR_key_owned_collection(bool async, bool useUpdate, bool addNew) + => Task.CompletedTask; + + protected override IQueryable ModifyQueryRoot(IQueryable query) + => query.AsSplitQuery(); + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public abstract class GraphUpdatesSqliteFixtureBase : GraphUpdatesFixtureBase + { + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + + protected override ITestStoreFactory TestStoreFactory + => SqliteTestStoreFactory.Instance; + + protected virtual bool AutoDetectChanges + => false; + + public override PoolableDbContext CreateContext() + { + var context = base.CreateContext(); + context.ChangeTracker.AutoDetectChangesEnabled = AutoDetectChanges; + + return context; + } + } + } +} From fcd17f3dd1040e1429974d1b525f8fc747c3adbc Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 8 Sep 2021 08:25:59 +0100 Subject: [PATCH 054/346] Read double as float on SQL Server when precision is less than 25 (#25881) Fixes #22572 --- .../Internal/SqlServerDoubleTypeMapping.cs | 29 ++++++++++ .../BuiltInDataTypesSqlServerTest.cs | 58 +++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerDoubleTypeMapping.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerDoubleTypeMapping.cs index 534aa3dd550..37ea7ce3c51 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerDoubleTypeMapping.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerDoubleTypeMapping.cs @@ -4,6 +4,8 @@ using System; using System.Data; using System.Data.Common; +using System.Linq.Expressions; +using System.Reflection; using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal @@ -16,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal /// public class SqlServerDoubleTypeMapping : DoubleTypeMapping { + private static readonly MethodInfo _getFloatMethod + = typeof(DbDataReader).GetRuntimeMethod(nameof(DbDataReader.GetFloat), new[] { typeof(int) })!; + /// /// 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 @@ -73,6 +78,30 @@ protected override string GenerateNonNullSqlLiteral(object value) : literal; } + /// + /// The method to use when reading values of the given type. The method must be defined + /// on or one of its subclasses. + /// + /// The method to use to read the value. + public override MethodInfo GetDataReaderMethod() + => Precision is <= 24 ? _getFloatMethod : base.GetDataReaderMethod(); + + /// + /// Gets a custom expression tree for reading the value from the input data reader + /// expression that contains the database value. + /// + /// The input expression, containing the database value. + /// The expression with customization added. + public override Expression CustomizeDataReaderExpression(Expression expression) + { + if (Precision is <= 24) + { + expression = Expression.Convert(expression, typeof(double)); + } + + return base.CustomizeDataReaderExpression(expression); + } + /// /// 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/test/EFCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerTest.cs index 067548dc876..0cea85a2066 100644 --- a/test/EFCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/BuiltInDataTypesSqlServerTest.cs @@ -1693,6 +1693,45 @@ private static MappedScaledSeparatelyDataTypes CreateMappedScaledSeparatelyDataT DecimalAsNumeric3 = 103m }; + [ConditionalFact] + public virtual void Can_insert_and_read_back_double_types_with_precision() + { + using (var context = CreateContext()) + { + context.Set().Add(CreateDoubleDataTypes(77)); + + Assert.Equal(1, context.SaveChanges()); + } + + var parameters = DumpParameters(); + Assert.Equal( + @"@p0='77' +@p1='83.33000183105469' (Size = 25) +@p2='83.30000305175781' (Size = 3)", + parameters, + ignoreLineEndingDifferences: true); + + using (var context = CreateContext()) + { + AssertDoubleDataTypes(context.Set().Single(e => e.Id == 77), 77); + } + } + + private static void AssertDoubleDataTypes(DoubleDataTypes entity, int id) + { + Assert.Equal(id, entity.Id); + Assert.Equal(83.3f, entity.Double3); + Assert.Equal(83.33f, entity.Double25); + } + + private static DoubleDataTypes CreateDoubleDataTypes(int id) + => new() + { + Id = id, + Double3 = 83.3f, + Double25 = 83.33f + }; + [ConditionalFact] public virtual void Can_insert_and_read_back_all_mapped_data_types_with_precision_and_scale() { @@ -2965,6 +3004,9 @@ public virtual void Columns_have_expected_data_types() BuiltInNullableDataTypesShadow.TestString ---> [nullable nvarchar] [MaxLength = -1] DateTimeEnclosure.DateTimeOffset ---> [nullable datetimeoffset] [Precision = 7] DateTimeEnclosure.Id ---> [int] [Precision = 10 Scale = 0] +DoubleDataTypes.Double25 ---> [float] [Precision = 53] +DoubleDataTypes.Double3 ---> [real] [Precision = 24] +DoubleDataTypes.Id ---> [int] [Precision = 10 Scale = 0] EmailTemplate.Id ---> [uniqueidentifier] EmailTemplate.TemplateType ---> [int] [Precision = 10 Scale = 0] MappedDataTypes.BoolAsBit ---> [bit] @@ -3599,6 +3641,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con b.Property(e => e.DecimalAsNumeric3).HasPrecision(3); }); + modelBuilder.Entity( + b => + { + b.Property(e => e.Id).ValueGeneratedNever(); + b.Property(e => e.Double3).HasPrecision(3); + b.Property(e => e.Double25).HasPrecision(25); + }); + modelBuilder.Entity( b => { @@ -4118,6 +4168,14 @@ protected class MappedScaledSeparatelyDataTypes public decimal DecimalAsNumeric3 { get; set; } } + protected class DoubleDataTypes + { + public int Id { get; set; } + + public double Double3 { get; set; } + public double Double25 { get; set; } + } + protected class MappedPrecisionAndScaledDataTypes { public int Id { get; set; } From d71384a249b4a98058ca5df8fd82e0d1fabec4b8 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 08:44:43 +0000 Subject: [PATCH 055/346] Update dependencies from https://github.com/dotnet/runtime build 20210907.27 (#25923) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1fd060635f3..437ae9b1cf9 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 - + https://github.com/dotnet/runtime - 895eb99d4987654cfb18e922a00c428678394bab + c7e5075017b5efddba7c07fc0429afaceb7a0ac8 diff --git a/eng/Versions.props b/eng/Versions.props index 57a7e779c55..8fbb2c87748 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 - 6.0.0-rc.2.21457.23 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21457.27 3.7.0 From 72444920caacf948a7312fce1d9efb9792a5ebf4 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 8 Sep 2021 11:10:20 +0200 Subject: [PATCH 056/346] Support no termination in SQL Server CREATE TABLE migration operation (#25911) Fixes #24254 --- .../SqlServerMigrationsSqlGenerator.cs | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs index 73974d4ecd5..f81dc53089f 100644 --- a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs +++ b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs @@ -539,8 +539,9 @@ protected override void Generate( MigrationCommandListBuilder builder, bool terminate = true) { - if (!terminate - && operation.Comment != null) + var hasComments = operation.Comment != null || operation.Columns.Any(c => c.Comment != null); + + if (!terminate && hasComments) { throw new ArgumentException(SqlServerStrings.CannotProduceUnterminatedSQLWithComments(nameof(CreateTableOperation))); } @@ -615,34 +616,45 @@ protected override void Generate( } } - builder.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator); - - var firstDescription = true; - if (operation.Comment != null) + if (hasComments) { - AddDescription(builder, operation.Comment, operation.Schema, operation.Name); + Check.DebugAssert(terminate, "terminate is false but there are comments"); - firstDescription = false; - } + builder.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator); - foreach (var column in operation.Columns) - { - if (column.Comment == null) + var firstDescription = true; + if (operation.Comment != null) { - continue; + AddDescription(builder, operation.Comment, operation.Schema, operation.Name); + + firstDescription = false; } - AddDescription( - builder, column.Comment, - operation.Schema, - operation.Name, - column.Name, - omitVariableDeclarations: !firstDescription); + foreach (var column in operation.Columns) + { + if (column.Comment == null) + { + continue; + } - firstDescription = false; - } + AddDescription( + builder, column.Comment, + operation.Schema, + operation.Name, + column.Name, + omitVariableDeclarations: !firstDescription); + + firstDescription = false; + } - builder.EndCommand(suppressTransaction: memoryOptimized); + builder.EndCommand(suppressTransaction: memoryOptimized); + } + else if (terminate) + { + builder + .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator) + .EndCommand(suppressTransaction: memoryOptimized); + } } /// From 8d7063ca1f6cd4740560d454def94b3ba50e6722 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 11:46:18 +0000 Subject: [PATCH 057/346] Update dependencies from https://github.com/dotnet/runtime build 20210908.2 (#25930) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 437ae9b1cf9..fb3a1c4fc28 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c - + https://github.com/dotnet/runtime - c7e5075017b5efddba7c07fc0429afaceb7a0ac8 + 01c4028969fafb927762477d6991c483f3b3cc5c diff --git a/eng/Versions.props b/eng/Versions.props index 8fbb2c87748..e5792724e77 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 - 6.0.0-rc.2.21457.27 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.2 3.7.0 From 2a9f9485b803c0e97114ec486ae339e2d30e79ae Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 8 Sep 2021 16:04:48 +0100 Subject: [PATCH 058/346] Don't mark property as loaded in lazy-loader if lazy-loading fails (#25898) --- .../Infrastructure/Internal/LazyLoader.cs | 27 +++- .../LazyLoadProxyTestBase.cs | 8 +- .../LazyLoadProxySqliteTest.cs | 123 ++++++++++++++++++ 3 files changed, 152 insertions(+), 6 deletions(-) diff --git a/src/EFCore/Infrastructure/Internal/LazyLoader.cs b/src/EFCore/Infrastructure/Internal/LazyLoader.cs index ddbab77f791..ad09a680b38 100644 --- a/src/EFCore/Infrastructure/Internal/LazyLoader.cs +++ b/src/EFCore/Infrastructure/Internal/LazyLoader.cs @@ -98,7 +98,15 @@ public virtual void Load(object entity, [CallerMemberName] string navigationName if (ShouldLoad(entity, navigationName, out var entry)) { - entry.Load(); + try + { + entry.Load(); + } + catch + { + SetLoaded(entity, navigationName, false); + throw; + } } } @@ -108,7 +116,7 @@ public virtual void Load(object entity, [CallerMemberName] string navigationName /// 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 Task LoadAsync( + public virtual async Task LoadAsync( object entity, CancellationToken cancellationToken = default, [CallerMemberName] string navigationName = "") @@ -116,9 +124,18 @@ public virtual Task LoadAsync( Check.NotNull(entity, nameof(entity)); Check.NotEmpty(navigationName, nameof(navigationName)); - return ShouldLoad(entity, navigationName, out var entry) - ? entry.LoadAsync(cancellationToken) - : Task.CompletedTask; + if (ShouldLoad(entity, navigationName, out var entry)) + { + try + { + await entry.LoadAsync(cancellationToken); + } + catch + { + SetLoaded(entity, navigationName, false); + throw; + } + } } private bool ShouldLoad(object entity, string navigationName, [NotNullWhen(true)] out NavigationEntry? navigationEntry) diff --git a/test/EFCore.Specification.Tests/LazyLoadProxyTestBase.cs b/test/EFCore.Specification.Tests/LazyLoadProxyTestBase.cs index 49c4a815efd..e5dcaaad574 100644 --- a/test/EFCore.Specification.Tests/LazyLoadProxyTestBase.cs +++ b/test/EFCore.Specification.Tests/LazyLoadProxyTestBase.cs @@ -2513,6 +2513,7 @@ public abstract class Parent public virtual IEnumerable ChildrenCompositeKey { get; set; } public virtual SingleCompositeKey SingleCompositeKey { get; set; } public virtual WithRecursiveProperty WithRecursiveProperty { get; set; } + public virtual IEnumerable ManyChildren { get; set; } } public class Mother : Parent @@ -2556,6 +2557,8 @@ public class Child public int? ParentId { get; set; } public virtual Parent Parent { get; set; } + + public virtual IEnumerable ManyParents { get; set; } } public class SinglePkToPk @@ -2885,6 +2888,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con e => new { e.AlternateId, e.Id }) .HasForeignKey( e => new { e.ParentAlternateId, e.ParentId }); + + b.HasMany(e => e.ManyChildren).WithMany(e => e.ManyParents); }); modelBuilder.Entity(); @@ -3002,7 +3007,8 @@ protected override void Seed(DbContext context) ChildrenCompositeKey = new List { new() { Id = 51 }, new() { Id = 52 } }, SingleCompositeKey = new SingleCompositeKey { Id = 62 }, - WithRecursiveProperty = new WithRecursiveProperty { Id = 8086 } + WithRecursiveProperty = new WithRecursiveProperty { Id = 8086 }, + ManyChildren = new List { new() { Id = 999 } } }); context.Add( diff --git a/test/EFCore.Sqlite.FunctionalTests/LazyLoadProxySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/LazyLoadProxySqliteTest.cs index c85dc4516dd..ee735957d09 100644 --- a/test/EFCore.Sqlite.FunctionalTests/LazyLoadProxySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/LazyLoadProxySqliteTest.cs @@ -1,7 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Data.Common; +using System.Linq; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; namespace Microsoft.EntityFrameworkCore { @@ -12,8 +17,126 @@ public LazyLoadProxySqliteTest(LoadSqliteFixture fixture) { } + [ConditionalFact] + public void IsLoaded_is_not_set_if_loading_principal_collection_fails() + { + using var context = Fixture.CreateContext(); + + var principal = context.Set().Single(); + Assert.False(context.Entry(principal).Collection(e => e.Children).IsLoaded); + + Fixture.Interceptor.Throw = true; + + Assert.Equal("Bang!", Assert.Throws(() => principal.Children).Message); + Assert.False(context.Entry(principal).Collection(e => e.Children).IsLoaded); + + Fixture.Interceptor.Throw = false; + + Assert.NotEmpty(principal.Children); + Assert.True(context.Entry(principal).Collection(e => e.Children).IsLoaded); + } + + [ConditionalFact] + public void IsLoaded_is_not_set_if_loading_principal_single_reference_fails() + { + using var context = Fixture.CreateContext(); + + var principal = context.Set().Single(); + Assert.False(context.Entry(principal).Reference(e => e.Single).IsLoaded); + + Fixture.Interceptor.Throw = true; + + Assert.Equal("Bang!", Assert.Throws(() => principal.Single).Message); + Assert.False(context.Entry(principal).Reference(e => e.Single).IsLoaded); + + Fixture.Interceptor.Throw = false; + + Assert.NotNull(principal.Single); + Assert.True(context.Entry(principal).Reference(e => e.Single).IsLoaded); + } + + [ConditionalFact] + public void IsLoaded_is_not_set_if_loading_many_to_many_collection_fails() + { + using var context = Fixture.CreateContext(); + + var principal = context.Set().Single(); + Assert.False(context.Entry(principal).Collection(e => e.ManyChildren).IsLoaded); + + Fixture.Interceptor.Throw = true; + + Assert.Equal("Bang!", Assert.Throws(() => principal.ManyChildren).Message); + Assert.False(context.Entry(principal).Collection(e => e.ManyChildren).IsLoaded); + + Fixture.Interceptor.Throw = false; + + Assert.NotEmpty(principal.ManyChildren); + Assert.True(context.Entry(principal).Collection(e => e.ManyChildren).IsLoaded); + } + + [ConditionalFact] + public void IsLoaded_is_not_set_if_loading_dependent_single_reference_fails() + { + using var context = Fixture.CreateContext(); + + var dependent = context.Set().OrderBy(e => e.Id).First(); + Assert.False(context.Entry(dependent).Reference(e => e.Parent).IsLoaded); + + Fixture.Interceptor.Throw = true; + + Assert.Equal("Bang!", Assert.Throws(() => dependent.Parent).Message); + Assert.False(context.Entry(dependent).Reference(e => e.Parent).IsLoaded); + + Fixture.Interceptor.Throw = false; + + Assert.NotNull(dependent.Parent); + Assert.True(context.Entry(dependent).Reference(e => e.Parent).IsLoaded); + } + + [ConditionalFact] + public void IsLoaded_is_not_set_if_loading_dependent_collection_reference_fails() + { + using var context = Fixture.CreateContext(); + + var dependent = context.Set().OrderBy(e => e.Id).First(); + Assert.False(context.Entry(dependent).Reference(e => e.Parent).IsLoaded); + + Fixture.Interceptor.Throw = true; + + Assert.Equal("Bang!", Assert.Throws(() => dependent.Parent).Message); + Assert.False(context.Entry(dependent).Reference(e => e.Parent).IsLoaded); + + Fixture.Interceptor.Throw = false; + + Assert.NotNull(dependent.Parent); + Assert.True(context.Entry(dependent).Reference(e => e.Parent).IsLoaded); + } + + public class ThrowingInterceptor : DbCommandInterceptor + { + public bool Throw { get; set; } + + public override InterceptionResult ReaderExecuting( + DbCommand command, + CommandEventData eventData, + InterceptionResult result) + { + if (Throw) + { + throw new Exception("Bang!"); + } + + return base.ReaderExecuting(command, eventData, result); + } + } + public class LoadSqliteFixture : LoadFixtureBase { + public ThrowingInterceptor Interceptor { get; } = new(); + + public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + => base.AddOptions(builder.UseLazyLoadingProxies().AddInterceptors(Interceptor)); + protected override ITestStoreFactory TestStoreFactory => SqliteTestStoreFactory.Instance; } From 289a9fcac774a12d3ab1f54c3ecc5a7af8635eb8 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 16:11:39 +0000 Subject: [PATCH 059/346] Update dependencies from https://github.com/dotnet/runtime build 20210908.5 (#25934) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index fb3a1c4fc28..6685d440db6 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 - + https://github.com/dotnet/runtime - 01c4028969fafb927762477d6991c483f3b3cc5c + a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 diff --git a/eng/Versions.props b/eng/Versions.props index e5792724e77..48cad4a6429 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 - 6.0.0-rc.2.21458.2 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.5 3.7.0 From 1087a73c3ea38d43041ead3e72f4b65373eeb356 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 8 Sep 2021 18:32:52 +0200 Subject: [PATCH 060/346] Validate same filters in duplicate indexes (#25931) Fixes #24968 --- .../Internal/RelationalIndexExtensions.cs | 14 ++++++++++++++ .../Properties/RelationalStrings.Designer.cs | 8 ++++++++ .../Properties/RelationalStrings.resx | 3 +++ .../RelationalModelValidatorTest.cs | 17 +++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalIndexExtensions.cs b/src/EFCore.Relational/Metadata/Internal/RelationalIndexExtensions.cs index 523d29bf1d8..a40d8050dc6 100644 --- a/src/EFCore.Relational/Metadata/Internal/RelationalIndexExtensions.cs +++ b/src/EFCore.Relational/Metadata/Internal/RelationalIndexExtensions.cs @@ -85,6 +85,20 @@ public static bool AreCompatible( return false; } + if (index.GetFilter() != duplicateIndex.GetFilter()) + { + throw new InvalidOperationException( + RelationalStrings.DuplicateIndexFiltersMismatch( + index.Properties.Format(), + index.DeclaringEntityType.DisplayName(), + duplicateIndex.Properties.Format(), + duplicateIndex.DeclaringEntityType.DisplayName(), + index.DeclaringEntityType.GetSchemaQualifiedTableName(), + index.GetDatabaseName(storeObject), + index.GetFilter(), + duplicateIndex.GetFilter())); + } + return true; } } diff --git a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs index 889c91c8acd..b5fd04468d6 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs +++ b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs @@ -499,6 +499,14 @@ public static string DuplicateIndexUniquenessMismatch(object? indexProperties1, GetString("DuplicateIndexUniquenessMismatch", nameof(indexProperties1), nameof(entityType1), nameof(indexProperties2), nameof(entityType2), nameof(table), nameof(indexName)), indexProperties1, entityType1, indexProperties2, entityType2, table, indexName); + /// + /// The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different filters ('{filter1}' and '{filter2}'). + /// + public static string DuplicateIndexFiltersMismatch(object? indexProperties1, object? entityType1, object? indexProperties2, object? entityType2, object? table, object? indexName, object? filter1, object? filter2) + => string.Format( + GetString("DuplicateIndexFiltersMismatch", nameof(indexProperties1), nameof(entityType1), nameof(indexProperties2), nameof(entityType2), nameof(table), nameof(indexName), nameof(filter1), nameof(filter2)), + indexProperties1, entityType1, indexProperties2, entityType2, table, indexName, filter1, filter2); + /// /// The keys {keyProperties1} on '{entityType1}' and {keyProperties2} on '{entityType2}' are both mapped to '{table}.{keyName}', but with different columns ({columnNames1} and {columnNames2}). /// diff --git a/src/EFCore.Relational/Properties/RelationalStrings.resx b/src/EFCore.Relational/Properties/RelationalStrings.resx index 1533ef0bad3..9a1b5bc9aa8 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.resx +++ b/src/EFCore.Relational/Properties/RelationalStrings.resx @@ -303,6 +303,9 @@ The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different uniqueness configurations. + + The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different filters ('{filter1}' and '{filter2}'). + The keys {keyProperties1} on '{entityType1}' and {keyProperties2} on '{entityType2}' are both mapped to '{table}.{keyName}', but with different columns ({columnNames1} and {columnNames2}). diff --git a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs index 4f3e2330628..c3fbcedf826 100644 --- a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs +++ b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs @@ -1295,6 +1295,23 @@ public virtual void Detects_duplicate_index_names_within_hierarchy_with_differen modelBuilder); } + [ConditionalFact] + public virtual void Detects_duplicate_index_names_within_hierarchy_with_different_filters() + { + var modelBuilder = CreateConventionalModelBuilder(); + modelBuilder.Entity(); + modelBuilder.Entity().HasIndex(c => c.Name).HasFilter("Foo").HasDatabaseName("IX_Animal_Name"); + modelBuilder.Entity().HasIndex(d => d.Name).HasFilter("Bar").HasDatabaseName("IX_Animal_Name"); + + VerifyError( + RelationalStrings.DuplicateIndexFiltersMismatch( + "{'" + nameof(Dog.Name) + "'}", nameof(Dog), + "{'" + nameof(Cat.Name) + "'}", nameof(Cat), + nameof(Animal), "IX_Animal_Name", + "Bar", "Foo"), + modelBuilder); + } + [ConditionalFact] public virtual void Passes_for_incompatible_indexes_within_hierarchy_when_one_name_configured_explicitly() { From eb30e3090a9a85c913c49f75b1f27e02b437df76 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Wed, 8 Sep 2021 11:21:08 -0700 Subject: [PATCH 061/346] Query: Convert SingleResult compared to null to Any (#25914) Resolves #18476 --- .../QueryOptimizingExpressionVisitor.cs | 360 ++++++++++-------- .../Query/NorthwindWhereQueryCosmosTest.cs | 84 ++++ .../Query/NorthwindWhereQueryTestBase.cs | 150 +++++++- .../ComplexNavigationsQuerySqlServerTest.cs | 13 +- .../Query/GearsOfWarQuerySqlServerTest.cs | 7 +- ...indAggregateOperatorsQuerySqlServerTest.cs | 14 +- ...orthwindMiscellaneousQuerySqlServerTest.cs | 59 ++- .../Query/NorthwindWhereQuerySqlServerTest.cs | 189 ++++++++- .../Query/QueryBugsTest.cs | 24 +- .../Query/TPTGearsOfWarQuerySqlServerTest.cs | 7 +- 10 files changed, 678 insertions(+), 229 deletions(-) diff --git a/src/EFCore/Query/Internal/QueryOptimizingExpressionVisitor.cs b/src/EFCore/Query/Internal/QueryOptimizingExpressionVisitor.cs index 4914320cd95..226a4310bdc 100644 --- a/src/EFCore/Query/Internal/QueryOptimizingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/QueryOptimizingExpressionVisitor.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Internal; @@ -18,6 +20,24 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal /// public class QueryOptimizingExpressionVisitor : ExpressionVisitor { + private static readonly List _singleResultMethodInfos = new() + { + QueryableMethods.FirstWithPredicate, + QueryableMethods.FirstWithoutPredicate, + QueryableMethods.FirstOrDefaultWithPredicate, + QueryableMethods.FirstOrDefaultWithoutPredicate, + QueryableMethods.SingleWithPredicate, + QueryableMethods.SingleWithoutPredicate, + QueryableMethods.SingleOrDefaultWithPredicate, + QueryableMethods.SingleOrDefaultWithoutPredicate, + QueryableMethods.LastWithPredicate, + QueryableMethods.LastWithoutPredicate, + QueryableMethods.LastOrDefaultWithPredicate, + QueryableMethods.LastOrDefaultWithoutPredicate + //QueryableMethodProvider.ElementAtMethodInfo, + //QueryableMethodProvider.ElementAtOrDefaultMethodInfo + }; + private static readonly MethodInfo _stringCompareWithComparisonMethod = typeof(string).GetRequiredRuntimeMethod(nameof(string.Compare), new[] { typeof(string), typeof(string), typeof(StringComparison) }); @@ -32,6 +52,128 @@ public class QueryOptimizingExpressionVisitor : ExpressionVisitor private static readonly Expression _constantNullString = Expression.Constant(null, typeof(string)); + /// + /// 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. + /// + protected override Expression VisitBinary(BinaryExpression binaryExpression) + { + var left = Visit(binaryExpression.Left); + var right = Visit(binaryExpression.Right); + + if (binaryExpression.NodeType != ExpressionType.Coalesce + && left.Type != right.Type + && left.Type.UnwrapNullableType() == right.Type.UnwrapNullableType()) + { + if (left.Type.IsNullableValueType()) + { + right = Expression.Convert(right, left.Type); + } + else + { + left = Expression.Convert(left, right.Type); + } + } + + if (binaryExpression.NodeType == ExpressionType.Equal + || binaryExpression.NodeType == ExpressionType.NotEqual) + { + var leftNullConstant = IsNullConstant(left); + var rightNullConstant = IsNullConstant(right); + if (leftNullConstant || rightNullConstant) + { + var nonNullExpression = leftNullConstant ? right : left; + if (nonNullExpression is MethodCallExpression methodCallExpression + && methodCallExpression.Method.DeclaringType == typeof(Queryable) + && methodCallExpression.Method.IsGenericMethod + && methodCallExpression.Method.GetGenericMethodDefinition() is MethodInfo genericMethod + && _singleResultMethodInfos.Contains(genericMethod)) + { + var result = Expression.Call( + (methodCallExpression.Arguments.Count == 2 + ? QueryableMethods.AnyWithPredicate + : QueryableMethods.AnyWithoutPredicate) + .MakeGenericMethod(methodCallExpression.Type), + methodCallExpression.Arguments); + + return binaryExpression.NodeType == ExpressionType.Equal + ? Expression.Not(result) + : result; + } + } + } + + return binaryExpression.Update(left, binaryExpression.Conversion, right); + } + + /// + /// 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. + /// + protected override Expression VisitConditional(ConditionalExpression conditionalExpression) + { + var test = Visit(conditionalExpression.Test); + var ifTrue = Visit(conditionalExpression.IfTrue); + var ifFalse = Visit(conditionalExpression.IfFalse); + + if (ifTrue.Type != ifFalse.Type + && ifTrue.Type.UnwrapNullableType() == ifFalse.Type.UnwrapNullableType()) + { + if (ifTrue.Type.IsNullableValueType()) + { + ifFalse = Expression.Convert(ifFalse, ifTrue.Type); + } + else + { + ifTrue = Expression.Convert(ifTrue, ifFalse.Type); + } + + return Expression.Condition(test, ifTrue, ifFalse); + } + + return conditionalExpression.Update(test, ifTrue, ifFalse); + } + + /// + /// 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. + /// + protected override ElementInit VisitElementInit(ElementInit elementInit) + { + var arguments = new Expression[elementInit.Arguments.Count]; + for (var i = 0; i < arguments.Length; i++) + { + arguments[i] = MatchExpressionType( + Visit(elementInit.Arguments[i]), + elementInit.Arguments[i].Type); + } + + return elementInit.Update(arguments); + } + + /// + /// 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. + /// + protected override Expression VisitLambda(Expression lambdaExpression) + { + Check.NotNull(lambdaExpression, nameof(lambdaExpression)); + + var body = Visit(lambdaExpression.Body); + + return body.Type != lambdaExpression.Body.Type + ? Expression.Lambda(Expression.Convert(body, lambdaExpression.Body.Type), lambdaExpression.Parameters) + : lambdaExpression.Update(body, lambdaExpression.Parameters)!; + } + /// /// 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 @@ -51,6 +193,21 @@ protected override Expression VisitMember(MemberExpression memberExpression) return TryOptimizeMemberAccessOverConditional(visitedExpression) ?? visitedExpression; } + /// + /// 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. + /// + protected override MemberAssignment VisitMemberAssignment(MemberAssignment memberAssignment) + { + var expression = MatchExpressionType( + Visit(memberAssignment.Expression), + memberAssignment.Expression.Type); + + return memberAssignment.Update(expression); + } + /// /// 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 @@ -136,16 +293,14 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp if (methodCallExpression.Object != null) { @object = MatchExpressionType( - Visit(methodCallExpression.Object), - methodCallExpression.Object.Type); + Visit(methodCallExpression.Object), methodCallExpression.Object.Type); } var arguments = new Expression[methodCallExpression.Arguments.Count]; for (var i = 0; i < arguments.Length; i++) { arguments[i] = MatchExpressionType( - Visit(methodCallExpression.Arguments[i]), - methodCallExpression.Arguments[i].Type); + Visit(methodCallExpression.Arguments[i]), methodCallExpression.Arguments[i].Type); } var visited = methodCallExpression.Update(@object!, arguments); @@ -177,131 +332,6 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp return visited; } - private Expression MatchExpressionType(Expression expression, Type typeToMatch) - => expression.Type != typeToMatch - ? Expression.Convert(expression, typeToMatch) - : expression; - - /// - /// 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. - /// - protected override Expression VisitUnary(UnaryExpression unaryExpression) - { - Check.NotNull(unaryExpression, nameof(unaryExpression)); - - if (unaryExpression.NodeType == ExpressionType.Not - && unaryExpression.Operand is MethodCallExpression innerMethodCall - && (Equals(_startsWithMethodInfo, innerMethodCall.Method) - || Equals(_endsWithMethodInfo, innerMethodCall.Method))) - { - if (innerMethodCall.Arguments[0] is ConstantExpression constantArgument - && constantArgument.Value is string stringValue - && stringValue == string.Empty) - { - // every string starts/ends with empty string. - return Expression.Constant(false); - } - - var newObject = Visit(innerMethodCall.Object)!; - var newArgument = Visit(innerMethodCall.Arguments[0]); - - var result = Expression.AndAlso( - Expression.NotEqual(newObject, _constantNullString), - Expression.AndAlso( - Expression.NotEqual(newArgument, _constantNullString), - Expression.Not(innerMethodCall.Update(newObject, new[] { newArgument })))); - - return newArgument is ConstantExpression - ? result - : Expression.AndAlso( - Expression.NotEqual( - newArgument, - Expression.Constant(string.Empty)), - result); - } - - return unaryExpression.Update( - Visit(unaryExpression.Operand)); - } - - /// - /// 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. - /// - protected override Expression VisitBinary(BinaryExpression binaryExpression) - { - var left = Visit(binaryExpression.Left); - var right = Visit(binaryExpression.Right); - - if (binaryExpression.NodeType != ExpressionType.Coalesce - && left.Type != right.Type - && left.Type.UnwrapNullableType() == right.Type.UnwrapNullableType()) - { - if (left.Type.IsNullableValueType()) - { - right = Expression.Convert(right, left.Type); - } - else - { - left = Expression.Convert(left, right.Type); - } - } - - return binaryExpression.Update(left, binaryExpression.Conversion, right); - } - - /// - /// 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. - /// - protected override Expression VisitConditional(ConditionalExpression conditionalExpression) - { - var test = Visit(conditionalExpression.Test); - var ifTrue = Visit(conditionalExpression.IfTrue); - var ifFalse = Visit(conditionalExpression.IfFalse); - - if (ifTrue.Type != ifFalse.Type - && ifTrue.Type.UnwrapNullableType() == ifFalse.Type.UnwrapNullableType()) - { - if (ifTrue.Type.IsNullableValueType()) - { - ifFalse = Expression.Convert(ifFalse, ifTrue.Type); - } - else - { - ifTrue = Expression.Convert(ifTrue, ifFalse.Type); - } - - return Expression.Condition(test, ifTrue, ifFalse); - } - - return conditionalExpression.Update(test, ifTrue, ifFalse); - } - - /// - /// 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. - /// - protected override Expression VisitLambda(Expression lambdaExpression) - { - Check.NotNull(lambdaExpression, nameof(lambdaExpression)); - - var body = Visit(lambdaExpression.Body); - - return body.Type != lambdaExpression.Body.Type - ? Expression.Lambda(Expression.Convert(body, lambdaExpression.Body.Type), lambdaExpression.Parameters) - : lambdaExpression.Update(body, lambdaExpression.Parameters)!; - } - /// /// 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 @@ -332,17 +362,17 @@ protected override Expression VisitNew(NewExpression newExpression) /// 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. /// - protected override ElementInit VisitElementInit(ElementInit elementInit) + protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) { - var arguments = new Expression[elementInit.Arguments.Count]; - for (var i = 0; i < arguments.Length; i++) + var expressions = new Expression[newArrayExpression.Expressions.Count]; + for (var i = 0; i < expressions.Length; i++) { - arguments[i] = MatchExpressionType( - Visit(elementInit.Arguments[i]), - elementInit.Arguments[i].Type); + expressions[i] = MatchExpressionType( + Visit(newArrayExpression.Expressions[i]), + newArrayExpression.Expressions[i].Type); } - return elementInit.Update(arguments); + return newArrayExpression.Update(expressions); } /// @@ -351,34 +381,50 @@ protected override ElementInit VisitElementInit(ElementInit elementInit) /// 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. /// - protected override MemberAssignment VisitMemberAssignment(MemberAssignment memberAssignment) + protected override Expression VisitUnary(UnaryExpression unaryExpression) { - var expression = MatchExpressionType( - Visit(memberAssignment.Expression), - memberAssignment.Expression.Type); - - return memberAssignment.Update(expression); - } + Check.NotNull(unaryExpression, nameof(unaryExpression)); - /// - /// 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. - /// - protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) - { - var expressions = new Expression[newArrayExpression.Expressions.Count]; - for (var i = 0; i < expressions.Length; i++) + if (unaryExpression.NodeType == ExpressionType.Not + && unaryExpression.Operand is MethodCallExpression innerMethodCall + && (Equals(_startsWithMethodInfo, innerMethodCall.Method) + || Equals(_endsWithMethodInfo, innerMethodCall.Method))) { - expressions[i] = MatchExpressionType( - Visit(newArrayExpression.Expressions[i]), - newArrayExpression.Expressions[i].Type); + if (innerMethodCall.Arguments[0] is ConstantExpression constantArgument + && constantArgument.Value is string stringValue + && stringValue == string.Empty) + { + // every string starts/ends with empty string. + return Expression.Constant(false); + } + + var newObject = Visit(innerMethodCall.Object)!; + var newArgument = Visit(innerMethodCall.Arguments[0]); + + var result = Expression.AndAlso( + Expression.NotEqual(newObject, _constantNullString), + Expression.AndAlso( + Expression.NotEqual(newArgument, _constantNullString), + Expression.Not(innerMethodCall.Update(newObject, new[] { newArgument })))); + + return newArgument is ConstantExpression + ? result + : Expression.AndAlso( + Expression.NotEqual( + newArgument, + Expression.Constant(string.Empty)), + result); } - return newArrayExpression.Update(expressions); + return unaryExpression.Update( + Visit(unaryExpression.Operand)); } + private Expression MatchExpressionType(Expression expression, Type typeToMatch) + => expression.Type != typeToMatch + ? Expression.Convert(expression, typeToMatch) + : expression; + private bool TryExtractEqualityOperands( Expression expression, [NotNullWhen(true)] out Expression? left, diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs index 78b7ac4dad7..a6c505d7041 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs @@ -2216,6 +2216,90 @@ FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""CustomerID""] = ""ALFKI""))"); } + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task FirstOrDefault_over_scalar_projection_compared_to_null(bool async) + { + return base.FirstOrDefault_over_scalar_projection_compared_to_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task FirstOrDefault_over_scalar_projection_compared_to_not_null(bool async) + { + return base.FirstOrDefault_over_scalar_projection_compared_to_not_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task FirstOrDefault_over_custom_projection_compared_to_null(bool async) + { + return base.FirstOrDefault_over_custom_projection_compared_to_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task FirstOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + return base.FirstOrDefault_over_custom_projection_compared_to_not_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task SingleOrDefault_over_custom_projection_compared_to_null(bool async) + { + return base.SingleOrDefault_over_custom_projection_compared_to_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task SingleOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + return base.SingleOrDefault_over_custom_projection_compared_to_not_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task LastOrDefault_over_custom_projection_compared_to_null(bool async) + { + return base.LastOrDefault_over_custom_projection_compared_to_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task LastOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + return base.LastOrDefault_over_custom_projection_compared_to_not_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task First_over_custom_projection_compared_to_null(bool async) + { + return base.First_over_custom_projection_compared_to_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task First_over_custom_projection_compared_to_not_null(bool async) + { + return base.First_over_custom_projection_compared_to_not_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task Single_over_custom_projection_compared_to_null(bool async) + { + return base.Single_over_custom_projection_compared_to_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task Single_over_custom_projection_compared_to_not_null(bool async) + { + return base.Single_over_custom_projection_compared_to_not_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task Last_over_custom_projection_compared_to_null(bool async) + { + return base.Last_over_custom_projection_compared_to_null(async); + } + + [ConditionalTheory(Skip = "Issue#17246 (Cross-collection join is not supported)")] + public override Task Last_over_custom_projection_compared_to_not_null(bool async) + { + return base.Last_over_custom_projection_compared_to_not_null(async); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs index 808cb476dc5..6ded26eb0f5 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs @@ -1204,7 +1204,7 @@ public virtual Task Where_select_many_and(bool async) ss => from c in ss.Set() from e in ss.Set() - // ReSharper disable ArrangeRedundantParentheses + // ReSharper disable ArrangeRedundantParentheses #pragma warning disable RCS1032 // Remove redundant parentheses. where (c.City == "London" && c.Country == "UK") && (e.City == "London" && e.Country == "UK") @@ -2522,6 +2522,154 @@ public virtual Task Filter_with_EF_Property_using_function_for_property_name(boo entryCount: 1); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FirstOrDefault_over_scalar_projection_compared_to_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => (int?)o.OrderID).FirstOrDefault() == null), + entryCount: 2); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FirstOrDefault_over_scalar_projection_compared_to_not_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => (int?)o.OrderID).FirstOrDefault() != null), + entryCount: 89); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FirstOrDefault_over_custom_projection_compared_to_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).FirstOrDefault() == null), + entryCount: 2); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task FirstOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).FirstOrDefault() != null), + entryCount: 89); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task SingleOrDefault_over_custom_projection_compared_to_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).SingleOrDefault() == null), + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).FirstOrDefault() == null), + entryCount: 2); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task SingleOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).SingleOrDefault() != null), + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).FirstOrDefault() != null), + entryCount: 89); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task LastOrDefault_over_custom_projection_compared_to_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).LastOrDefault() == null), + entryCount: 2); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task LastOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).LastOrDefault() != null), + entryCount: 89); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task First_over_custom_projection_compared_to_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).First() == null), + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).FirstOrDefault() == null), + entryCount: 2); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task First_over_custom_projection_compared_to_not_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).First() != null), + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).FirstOrDefault() != null), + entryCount: 89); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Single_over_custom_projection_compared_to_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).Single() == null), + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).FirstOrDefault() == null), + entryCount: 2); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Single_over_custom_projection_compared_to_not_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).Single() != null), + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).FirstOrDefault() != null), + entryCount: 89); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Last_over_custom_projection_compared_to_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).Last() == null), + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).LastOrDefault() == null), + entryCount: 2); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Last_over_custom_projection_compared_to_not_null(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).Last() != null), + ss => ss.Set().Where(c => c.Orders.Select(o => new { o.OrderID }).LastOrDefault() != null), + entryCount: 89); + } + private string StringMethod(string arg) => arg; } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs index d0565e6ac2e..e4297e065c4 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs @@ -3212,11 +3212,10 @@ public override async Task Member_pushdown_with_multiple_collections(bool async) @"SELECT ( SELECT TOP(1) [l0].[Name] FROM [LevelThree] AS [l0] - WHERE ( - SELECT TOP(1) [l1].[Id] + WHERE EXISTS ( + SELECT 1 FROM [LevelTwo] AS [l1] - WHERE [l].[Id] = [l1].[OneToMany_Optional_Inverse2Id] - ORDER BY [l1].[Id]) IS NOT NULL AND ((( + WHERE [l].[Id] = [l1].[OneToMany_Optional_Inverse2Id]) AND ((( SELECT TOP(1) [l2].[Id] FROM [LevelTwo] AS [l2] WHERE [l].[Id] = [l2].[OneToMany_Optional_Inverse2Id] @@ -3701,10 +3700,10 @@ public override async Task Multiple_collection_FirstOrDefault_followed_by_member @"SELECT [l].[Id], ( SELECT TOP(1) [l0].[Name] FROM [LevelThree] AS [l0] - WHERE ( - SELECT TOP(1) [l1].[Id] + WHERE EXISTS ( + SELECT 1 FROM [LevelTwo] AS [l1] - WHERE ([l].[Id] = [l1].[OneToMany_Optional_Inverse2Id]) AND ([l1].[Name] = N'L2 02')) IS NOT NULL AND ((( + WHERE ([l].[Id] = [l1].[OneToMany_Optional_Inverse2Id]) AND ([l1].[Name] = N'L2 02')) AND ((( SELECT TOP(1) [l2].[Id] FROM [LevelTwo] AS [l2] WHERE ([l].[Id] = [l2].[OneToMany_Optional_Inverse2Id]) AND ([l2].[Name] = N'L2 02')) = [l0].[OneToMany_Optional_Inverse3Id]) OR (( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index ebe281dc370..4bc495cf9e4 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -5738,11 +5738,10 @@ public override async Task Filter_with_complex_predicate_containing_subquery(boo AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] FROM [Gears] AS [g] -WHERE ([g].[FullName] <> N'Dom') AND ( - SELECT TOP(1) [w].[Id] +WHERE ([g].[FullName] <> N'Dom') AND EXISTS ( + SELECT 1 FROM [Weapons] AS [w] - WHERE ([g].[FullName] = [w].[OwnerFullName]) AND ([w].[IsAutomatic] = CAST(1 AS bit)) - ORDER BY [w].[Id]) IS NOT NULL"); + WHERE ([g].[FullName] = [w].[OwnerFullName]) AND ([w].[IsAutomatic] = CAST(1 AS bit)))"); } public override async Task Query_with_complex_let_containing_ordering_and_filter_projecting_firstOrDefault_element_of_let( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs index 61492642b27..474dc349c7f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs @@ -591,11 +591,10 @@ FROM [Customers] AS [c] OUTER APPLY ( SELECT TOP(1) [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice] FROM [Order Details] AS [o] - WHERE ( - SELECT TOP(1) [o0].[OrderID] + WHERE EXISTS ( + SELECT 1 FROM [Orders] AS [o0] - WHERE [c].[CustomerID] = [o0].[CustomerID] - ORDER BY [o0].[OrderID]) IS NOT NULL AND (( + WHERE [c].[CustomerID] = [o0].[CustomerID]) AND (( SELECT TOP(1) [o1].[OrderID] FROM [Orders] AS [o1] WHERE [c].[CustomerID] = [o1].[CustomerID] @@ -614,11 +613,10 @@ public override async Task Multiple_collection_navigation_with_FirstOrDefault_ch @"SELECT ( SELECT TOP(1) [o].[ProductID] FROM [Order Details] AS [o] - WHERE ( - SELECT TOP(1) [o0].[OrderID] + WHERE EXISTS ( + SELECT 1 FROM [Orders] AS [o0] - WHERE [c].[CustomerID] = [o0].[CustomerID] - ORDER BY [o0].[OrderID]) IS NOT NULL AND (( + WHERE [c].[CustomerID] = [o0].[CustomerID]) AND (( SELECT TOP(1) [o1].[OrderID] FROM [Orders] AS [o1] WHERE [c].[CustomerID] = [o1].[CustomerID] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs index 322e0da4fb0..72b78dded6e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs @@ -265,10 +265,10 @@ public override async Task Entity_equality_through_subquery(bool async) AssertSql( @"SELECT [c].[CustomerID] FROM [Customers] AS [c] -WHERE ( - SELECT TOP(1) [o].[OrderID] +WHERE EXISTS ( + SELECT 1 FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID]) IS NOT NULL"); + WHERE [c].[CustomerID] = [o].[CustomerID])"); } public override async Task Entity_equality_through_include(bool async) @@ -450,10 +450,10 @@ SELECT TOP(@__p_0) [e].[EmployeeID], [e].[City], [e].[Country], [e].[FirstName], FROM [Employees] AS [e] ORDER BY [e].[EmployeeID] ) AS [t] -WHERE ( - SELECT TOP(1) [e0].[EmployeeID] +WHERE NOT (EXISTS ( + SELECT 1 FROM [Employees] AS [e0] - WHERE [e0].[EmployeeID] = [t].[ReportsTo]) IS NULL + WHERE [e0].[EmployeeID] = [t].[ReportsTo])) ORDER BY [t].[EmployeeID]"); } @@ -472,10 +472,10 @@ FROM [Employees] AS [e] ORDER BY [e].[EmployeeID] OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY ) AS [t] -WHERE ( - SELECT TOP(1) [e0].[EmployeeID] +WHERE EXISTS ( + SELECT 1 FROM [Employees] AS [e0] - WHERE [e0].[EmployeeID] = [t].[ReportsTo]) IS NOT NULL + WHERE [e0].[EmployeeID] = [t].[ReportsTo]) ORDER BY [t].[EmployeeID]"); } @@ -3889,11 +3889,10 @@ public override async Task Subquery_is_null_translated_correctly(bool async) AssertSql( @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] -WHERE ( - SELECT TOP(1) [o].[CustomerID] +WHERE NOT (EXISTS ( + SELECT 1 FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID] - ORDER BY [o].[OrderID] DESC) IS NULL"); + WHERE [c].[CustomerID] = [o].[CustomerID]))"); } public override async Task Subquery_is_not_null_translated_correctly(bool async) @@ -3903,11 +3902,10 @@ public override async Task Subquery_is_not_null_translated_correctly(bool async) AssertSql( @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] -WHERE ( - SELECT TOP(1) [o].[CustomerID] +WHERE EXISTS ( + SELECT 1 FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID] - ORDER BY [o].[OrderID] DESC) IS NOT NULL"); + WHERE [c].[CustomerID] = [o].[CustomerID])"); } public override async Task Select_take_average(bool async) @@ -4554,11 +4552,10 @@ FROM [Orders] AS [o0] WHERE [c].[CustomerID] = [o0].[CustomerID] ORDER BY [o0].[OrderDate]) AS [OrderDate] FROM [Customers] AS [c] -WHERE ([c].[CustomerID] LIKE N'A%') AND ( - SELECT TOP(1) [o].[OrderID] +WHERE ([c].[CustomerID] LIKE N'A%') AND EXISTS ( + SELECT 1 FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID] - ORDER BY [o].[OrderDate]) IS NOT NULL"); + WHERE [c].[CustomerID] = [o].[CustomerID])"); } public override async Task Let_entity_equality_to_other_entity(bool async) @@ -4604,12 +4601,11 @@ public override async Task Dependent_to_principal_navigation_equal_to_null_for_s AssertSql( @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] -WHERE ( - SELECT TOP(1) [c0].[CustomerID] +WHERE NOT (EXISTS ( + SELECT 1 FROM [Orders] AS [o] LEFT JOIN [Customers] AS [c0] ON [o].[CustomerID] = [c0].[CustomerID] - WHERE [c].[CustomerID] = [o].[CustomerID] - ORDER BY [o].[OrderID]) IS NULL"); + WHERE [c].[CustomerID] = [o].[CustomerID]))"); } public override async Task Collection_navigation_equality_rewrite_for_subquery(bool async) @@ -5132,12 +5128,11 @@ public override async Task Pending_selector_in_cardinality_reducing_method_is_ap WHEN EXISTS ( SELECT 1 FROM [Orders] AS [o] - WHERE (( - SELECT TOP(1) [c0].[CustomerID] + WHERE (EXISTS ( + SELECT 1 FROM [Orders] AS [o0] LEFT JOIN [Customers] AS [c0] ON [o0].[CustomerID] = [c0].[CustomerID] - WHERE [c].[CustomerID] = [o0].[CustomerID] - ORDER BY [o0].[OrderDate]) IS NOT NULL AND ((( + WHERE [c].[CustomerID] = [o0].[CustomerID]) AND ((( SELECT TOP(1) [c1].[CustomerID] FROM [Orders] AS [o1] LEFT JOIN [Customers] AS [c1] ON [o1].[CustomerID] = [c1].[CustomerID] @@ -5202,10 +5197,10 @@ public override async Task Entity_equality_on_subquery_with_null_check(bool asyn WHEN NOT (EXISTS ( SELECT 1 FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID])) OR ( - SELECT TOP(1) [o0].[OrderID] + WHERE [c].[CustomerID] = [o].[CustomerID])) OR NOT (EXISTS ( + SELECT 1 FROM [Orders] AS [o0] - WHERE [c].[CustomerID] = [o0].[CustomerID]) IS NULL THEN CAST(1 AS bit) + WHERE [c].[CustomerID] = [o0].[CustomerID])) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END, ( SELECT TOP(1) [o1].[OrderDate] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs index d523bf45235..b240c57bca5 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs @@ -1692,11 +1692,10 @@ public override async Task Where_subquery_FirstOrDefault_is_null(bool async) AssertSql( @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] -WHERE ( - SELECT TOP(1) [o].[OrderID] +WHERE NOT (EXISTS ( + SELECT 1 FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID] - ORDER BY [o].[OrderID]) IS NULL"); + WHERE [c].[CustomerID] = [o].[CustomerID]))"); } public override async Task Where_subquery_FirstOrDefault_compared_to_entity(bool async) @@ -2289,6 +2288,188 @@ FROM [Customers] AS [c] WHERE [c].[CustomerID] = N'ALFKI'"); } + public override async Task FirstOrDefault_over_scalar_projection_compared_to_null(bool async) + { + await base.FirstOrDefault_over_scalar_projection_compared_to_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE NOT (EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID]))"); + } + + public override async Task FirstOrDefault_over_scalar_projection_compared_to_not_null(bool async) + { + await base.FirstOrDefault_over_scalar_projection_compared_to_not_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID])"); + } + + public override async Task FirstOrDefault_over_custom_projection_compared_to_null(bool async) + { + await base.FirstOrDefault_over_custom_projection_compared_to_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE NOT (EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID]))"); + } + + public override async Task FirstOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + await base.FirstOrDefault_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID])"); + } + + public override async Task SingleOrDefault_over_custom_projection_compared_to_null(bool async) + { + await base.SingleOrDefault_over_custom_projection_compared_to_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE NOT (EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID]))"); + } + + public override async Task SingleOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + await base.SingleOrDefault_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID])"); + } + + public override async Task LastOrDefault_over_custom_projection_compared_to_null(bool async) + { + await base.LastOrDefault_over_custom_projection_compared_to_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE NOT (EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID]))"); + } + + public override async Task LastOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + await base.LastOrDefault_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID])"); + } + + public override async Task First_over_custom_projection_compared_to_null(bool async) + { + await base.First_over_custom_projection_compared_to_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE NOT (EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID]))"); + } + + public override async Task First_over_custom_projection_compared_to_not_null(bool async) + { + await base.First_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID])"); + } + + public override async Task Single_over_custom_projection_compared_to_null(bool async) + { + await base.Single_over_custom_projection_compared_to_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE NOT (EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID]))"); + } + + public override async Task Single_over_custom_projection_compared_to_not_null(bool async) + { + await base.Single_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID])"); + } + + public override async Task Last_over_custom_projection_compared_to_null(bool async) + { + await base.Last_over_custom_projection_compared_to_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE NOT (EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID]))"); + } + + public override async Task Last_over_custom_projection_compared_to_not_null(bool async) + { + await base.Last_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[CustomerID] = [o].[CustomerID])"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs index 549600a8076..f5fb891b70c 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs @@ -4061,8 +4061,8 @@ public virtual async Task Projecting_column_with_value_converter_of_ulong_byte_a { var result = context.Parents.OrderBy(e => e.Id).Select(p => (ulong?)p.Child.ULongRowVersion).FirstOrDefault(); - AssertSql( - @"SELECT TOP(1) [c].[ULongRowVersion] + AssertSql( + @"SELECT TOP(1) [c].[ULongRowVersion] FROM [Parents] AS [p] LEFT JOIN [Children] AS [c] ON [p].[ChildId] = [c].[Id] ORDER BY [p].[Id]"); @@ -5338,10 +5338,10 @@ OUTER APPLY ( SELECT [s].[ThingId], [t].[Id], [s].[Id] AS [Id0] FROM [Things] AS [t] LEFT JOIN [Subthings] AS [s] ON [t].[Id] = [s].[ThingId] - WHERE ( - SELECT TOP(1) [v].[Id] + WHERE EXISTS ( + SELECT 1 FROM [Values] AS [v] - WHERE [e].[Id] = [v].[Entity11023Id]) IS NOT NULL AND ((( + WHERE [e].[Id] = [v].[Entity11023Id]) AND ((( SELECT TOP(1) [v0].[Id] FROM [Values] AS [v0] WHERE [e].[Id] = [v0].[Entity11023Id]) = [t].[Value11023Id]) OR (( @@ -7089,10 +7089,10 @@ public virtual async Task Using_explicit_interface_implementation_as_navigation_ AssertSql( @"SELECT TOP(2) CASE - WHEN ( - SELECT TOP(1) [c].[Id] + WHEN EXISTS ( + SELECT 1 FROM [CoverIllustrations] AS [c] - WHERE ([b0].[Id] = [c].[CoverId]) AND ([c].[State] >= 2)) IS NOT NULL THEN CAST(1 AS bit) + WHERE ([b0].[Id] = [c].[CoverId]) AND ([c].[State] >= 2)) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END, ( SELECT TOP(1) [c0].[Uri] @@ -7228,8 +7228,8 @@ from t2 in context.Tests.FromSqlInterpolated($"Select * from Tests Where Type = Assert.Equal(MyContext19206.TestType19206.Unit, item.t1.Type); Assert.Equal(MyContext19206.TestType19206.Integration, item.t2.Type); - AssertSql( - @"p0='0' + AssertSql( + @"p0='0' p1='1' SELECT [m].[Id], [m].[Type], [m0].[Id], [m0].[Type] @@ -10120,8 +10120,8 @@ public virtual async Task NoTracking_split_query_creates_only_required_instances Assert.Equal(1, Test25400.ConstructorCallCount); - AssertSql( - @"SELECT TOP(1) [t].[Id], [t].[Value] + AssertSql( + @"SELECT TOP(1) [t].[Id], [t].[Value] FROM [Tests] AS [t] ORDER BY [t].[Id]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index 954d7e7f02b..7b98acf1e21 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -6704,11 +6704,10 @@ WHEN [o].[Nickname] IS NOT NULL THEN N'Officer' END AS [Discriminator] FROM [Gears] AS [g] LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[SquadId] = [o].[SquadId]) -WHERE ([g].[FullName] <> N'Dom') AND ( - SELECT TOP(1) [w].[Id] +WHERE ([g].[FullName] <> N'Dom') AND EXISTS ( + SELECT 1 FROM [Weapons] AS [w] - WHERE ([g].[FullName] = [w].[OwnerFullName]) AND ([w].[IsAutomatic] = CAST(1 AS bit)) - ORDER BY [w].[Id]) IS NOT NULL"); + WHERE ([g].[FullName] = [w].[OwnerFullName]) AND ([w].[IsAutomatic] = CAST(1 AS bit)))"); } public override async Task Query_with_complex_let_containing_ordering_and_filter_projecting_firstOrDefault_element_of_let( From 4f38f2a0c567528c3b111ff4f286007836ed8d3f Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 8 Sep 2021 19:51:50 +0100 Subject: [PATCH 062/346] Add convert node to snapshot expression when needed (#25936) Fixes #25259 --- src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs | 5 +++++ test/EFCore.Specification.Tests/CustomConvertersTestBase.cs | 2 +- .../ValueConvertersEndToEndTestBase.cs | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs index ab37b8d061d..f133466dac9 100644 --- a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs @@ -192,6 +192,11 @@ private Expression CreateSnapshotValueExpression(Expression expression, IPropert expression, comparer.SnapshotExpression.Body); + if (snapshotExpression.Type != propertyBase.ClrType) + { + snapshotExpression = Expression.Convert(snapshotExpression, propertyBase.ClrType); + } + expression = propertyBase.ClrType.IsNullableType() ? Expression.Condition( Expression.Equal(expression, Expression.Constant(null, propertyBase.ClrType)), diff --git a/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs b/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs index f450c1891e5..f1aef2d11ab 100644 --- a/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs +++ b/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs @@ -1183,7 +1183,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con new ValueComparer>( (v1, v2) => v1.SequenceEqual(v2), v => v.GetHashCode(), - v => (IDictionary)new Dictionary(v))); + v => new Dictionary(v))); }); var urlConverter = new UrlSchemeRemover(); diff --git a/test/EFCore.Specification.Tests/ValueConvertersEndToEndTestBase.cs b/test/EFCore.Specification.Tests/ValueConvertersEndToEndTestBase.cs index d2823a14dc2..d9ba187927c 100644 --- a/test/EFCore.Specification.Tests/ValueConvertersEndToEndTestBase.cs +++ b/test/EFCore.Specification.Tests/ValueConvertersEndToEndTestBase.cs @@ -918,7 +918,7 @@ public EnumerableOfIntComparer() : base( (c1, c2) => (c1 == null && c2 == null) || (c1 != null && c2 != null && c1.SequenceEqual(c2)), c => c == null ? 0 : c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())), - c => c == null ? null : (IEnumerable)c.ToList()) + c => c == null ? null : c.ToList()) { } } From 6c1694a8ce436e79b4dc3c057424dee601a5d054 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 8 Sep 2021 19:52:09 +0100 Subject: [PATCH 063/346] Remove factory from value generator cache key (#25925) Fixes #24637 --- src/EFCore/ValueGeneration/ValueGeneratorCache.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/EFCore/ValueGeneration/ValueGeneratorCache.cs b/src/EFCore/ValueGeneration/ValueGeneratorCache.cs index bb90773395f..c629df6ed0c 100644 --- a/src/EFCore/ValueGeneration/ValueGeneratorCache.cs +++ b/src/EFCore/ValueGeneration/ValueGeneratorCache.cs @@ -45,19 +45,16 @@ public ValueGeneratorCache(ValueGeneratorCacheDependencies dependencies) private readonly struct CacheKey : IEquatable { - public CacheKey(IProperty property, IEntityType entityType, Func factory) + public CacheKey(IProperty property, IEntityType entityType) { Property = property; EntityType = entityType; - Factory = factory; } public IProperty Property { get; } public IEntityType EntityType { get; } - public Func Factory { get; } - public bool Equals(CacheKey other) => Property.Equals(other.Property) && EntityType.Equals(other.EntityType); @@ -87,7 +84,7 @@ public virtual ValueGenerator GetOrAdd( Check.NotNull(property, nameof(property)); Check.NotNull(factory, nameof(factory)); - return _cache.GetOrAdd(new CacheKey(property, entityType, factory), ck => ck.Factory(ck.Property, ck.EntityType)); + return _cache.GetOrAdd(new CacheKey(property, entityType), static (ck, f) => f(ck.Property, ck.EntityType), factory); } } } From 804ff9e5512fb3a9d82ef3a6fce69a949e8f06f9 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Wed, 8 Sep 2021 11:55:07 -0700 Subject: [PATCH 064/346] Query: Use cancellationToken appropriately (#25918) --- ...ressionVisitor.ShaperProcessingExpressionVisitor.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index 314f2e75471..a67cdf1c8f2 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -1482,10 +1482,11 @@ private static async Task PopulateSplitIncludeCollectionAsync InitializeReaderAsync(tup.Item1, tup.Item2, tup.Item3, cancellationToken), - verifySucceeded: null) + verifySucceeded: null, + queryContext.CancellationToken) .ConfigureAwait(false); - async Task InitializeReaderAsync( + static async Task InitializeReaderAsync( RelationalQueryContext queryContext, RelationalCommandCache relationalCommandCache, bool detailedErrorsEnabled, @@ -1801,10 +1802,11 @@ private static async Task PopulateSplitCollectionAsync InitializeReaderAsync(tup.Item1, tup.Item2, tup.Item3, cancellationToken), - verifySucceeded: null) + verifySucceeded: null, + queryContext.CancellationToken) .ConfigureAwait(false); - async Task InitializeReaderAsync( + static async Task InitializeReaderAsync( RelationalQueryContext queryContext, RelationalCommandCache relationalCommandCache, bool detailedErrorsEnabled, From 89809750e93550c0336ec5312307ce136627ae43 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Wed, 8 Sep 2021 12:32:33 -0700 Subject: [PATCH 065/346] Query: Convert enum value to integer when printing constant as needed (#25940) Resolves #23858 --- .../Storage/RelationalTypeMapping.cs | 42 ++++++++++--------- .../Query/SimpleQueryTestBase.cs | 29 +++++++++++++ .../Query/SimpleQuerySqlServerTest.cs | 32 ++++++++++++++ 3 files changed, 84 insertions(+), 19 deletions(-) diff --git a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs index 3a183e82e53..595ec3a0c1b 100644 --- a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs +++ b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs @@ -484,16 +484,7 @@ public virtual DbParameter CreateParameter( parameter.Direction = ParameterDirection.Input; parameter.ParameterName = name; - value = ConvertUnderlyingEnumValueToEnum(value); - - // We preserve convert nodes around enum to get actual enum value for type mapping - // But when enum is cast manually to something same as implicit cast - // And type mapping is not really enum then we need to convert the enum value to current Clr Type - if (value?.GetType().IsEnum == true - && ClrType.IsInteger()) - { - value = Convert.ChangeType(value, ClrType); - } + value = NormalizeEnumValue(value); if (Converter != null) { @@ -519,14 +510,27 @@ public virtual DbParameter CreateParameter( return parameter; } - // Enum when compared to constant will always have value of integral type - // when enum would contain convert node. We remove the convert node but we also - // need to convert the integral value to enum value. - // This allows us to use converter on enum value or print enum value directly if supported by provider - private object? ConvertUnderlyingEnumValueToEnum(object? value) - => value?.GetType().IsInteger() == true && ClrType.UnwrapNullableType().IsEnum - ? Enum.ToObject(ClrType.UnwrapNullableType(), value) - : value; + private object? NormalizeEnumValue(object? value) + { + // When Enum column is compared to constant the C# compiler put a constant of integer there + // In some unknown cases for parameter we also see integer value. + // So if CLR type is enum we need to convert integer value to enum value + if (value?.GetType().IsInteger() == true + && ClrType.UnwrapNullableType().IsEnum) + { + return Enum.ToObject(ClrType.UnwrapNullableType(), value); + } + + // When Enum is cast manually our logic of removing implicit convert gives us enum value here + // So if CLR type is integer we need to convert enum value to integer value + if (value?.GetType().IsEnum == true + && ClrType.UnwrapNullableType().IsInteger()) + { + return Convert.ChangeType(value, ClrType); + } + + return value; + } /// /// Configures type information of a . @@ -545,7 +549,7 @@ protected virtual void ConfigureParameter(DbParameter parameter) /// public virtual string GenerateSqlLiteral(object? value) { - value = ConvertUnderlyingEnumValueToEnum(value); + value = NormalizeEnumValue(value); if (Converter != null) { diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs index 5cc99ed0a15..f2c623ada63 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Linq.Expressions; using System.Threading.Tasks; using Xunit; @@ -152,6 +153,27 @@ public virtual async Task Comparing_enum_casted_to_byte_with_int_constant(bool a Assert.Single(bitterIceCreams); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Comparing_byte_column_to_enum_in_vb_creating_double_cast(bool async) + { + var contextFactory = await InitializeAsync(); + using var context = contextFactory.CreateContext(); + Expression> memberAccess = (Food i) => i.Taste; + var predicate = Expression.Lambda>( + Expression.Equal( + Expression.Convert(memberAccess.Body, typeof(int?)), + Expression.Convert( + Expression.Convert(Expression.Constant(Taste.Bitter, typeof(Taste)), typeof(int)), + typeof(int?))), + memberAccess.Parameters); + var query = context.Food.Where(predicate); + + var bitterFood = async + ? await query.ToListAsync() + : query.ToList(); + } + protected class Context21770 : DbContext { public Context21770(DbContextOptions options) @@ -160,6 +182,7 @@ public Context21770(DbContextOptions options) } public DbSet IceCreams { get; set; } + public DbSet Food { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -186,5 +209,11 @@ protected class IceCream public string Name { get; set; } public int Taste { get; set; } } + + protected class Food + { + public int Id { get; set; } + public byte? Taste { get; set; } + } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs index 09cccb14fc5..4fad38a5246 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs @@ -31,5 +31,37 @@ FROM [Appraisals] AS [a] LEFT JOIN [Staff] AS [s1] ON [s].[SecondaryManagerId] = [s1].[Id] WHERE [a].[Id] = @__id_0"); } + + public override async Task Comparing_enum_casted_to_byte_with_int_parameter(bool async) + { + await base.Comparing_enum_casted_to_byte_with_int_parameter(async); + + AssertSql( + @"@__bitterTaste_0='1' + +SELECT [i].[IceCreamId], [i].[Name], [i].[Taste] +FROM [IceCreams] AS [i] +WHERE [i].[Taste] = @__bitterTaste_0"); + } + + public override async Task Comparing_enum_casted_to_byte_with_int_constant(bool async) + { + await base.Comparing_enum_casted_to_byte_with_int_constant(async); + + AssertSql( + @"SELECT [i].[IceCreamId], [i].[Name], [i].[Taste] +FROM [IceCreams] AS [i] +WHERE [i].[Taste] = 1"); + } + + public override async Task Comparing_byte_column_to_enum_in_vb_creating_double_cast(bool async) + { + await base.Comparing_byte_column_to_enum_in_vb_creating_double_cast(async); + + AssertSql( + @"SELECT [f].[Id], [f].[Taste] +FROM [Food] AS [f] +WHERE [f].[Taste] = CAST(1 AS tinyint)"); + } } } From 0ad9edf2338699393722b279b340cc762f1e1109 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 8 Sep 2021 21:57:37 +0100 Subject: [PATCH 066/346] Change logging level for non-created indexes from Info to Warn (#25928) Fixes #24981 We had decided to make these Debug, but after looking at how these are used I think it makes more sense to make them warnings. --- .../Properties/RelationalStrings.Designer.cs | 4 ++-- src/EFCore.Relational/Properties/RelationalStrings.resx | 4 ++-- .../Infrastructure/RelationalModelValidatorTest.cs | 6 ++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs index b5fd04468d6..4244c78f8db 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs +++ b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs @@ -2115,7 +2115,7 @@ public static EventDefinition LogMultipleCollectionIncludeWarning(IDiagnosticsLo static logger => new EventDefinition( logger.Options, RelationalEventId.AllIndexPropertiesNotToMappedToAnyTable, - LogLevel.Information, + LogLevel.Warning, "RelationalEventId.AllIndexPropertiesNotToMappedToAnyTable", level => LoggerMessage.Define( level, @@ -2613,7 +2613,7 @@ public static EventDefinition LogUnnamedIndexAllPropertiesNotToM static logger => new EventDefinition( logger.Options, RelationalEventId.AllIndexPropertiesNotToMappedToAnyTable, - LogLevel.Information, + LogLevel.Warning, "RelationalEventId.AllIndexPropertiesNotToMappedToAnyTable", level => LoggerMessage.Define( level, diff --git a/src/EFCore.Relational/Properties/RelationalStrings.resx b/src/EFCore.Relational/Properties/RelationalStrings.resx index 9a1b5bc9aa8..b0a1e6bada0 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.resx +++ b/src/EFCore.Relational/Properties/RelationalStrings.resx @@ -542,7 +542,7 @@ The index named '{indexName}' on the entity type '{entityType}' specifies properties {indexProperties}, but none of these properties are mapped to a column in any table. This index will not be created in the database. - Information RelationalEventId.AllIndexPropertiesNotToMappedToAnyTable string? string string + Warning RelationalEventId.AllIndexPropertiesNotToMappedToAnyTable string? string string The index named '{indexName}' on the entity type '{entityType}' specifies properties {indexProperties}. Some properties are mapped to a column in a table, but the property '{propertyName}' is not. All of the properties must be mapped for the index to be created in the database. @@ -622,7 +622,7 @@ The unnamed index on the entity type '{entityType}' specifies properties {indexProperties}, but none of these properties are mapped to a column in any table. This index will not be created in the database. - Information RelationalEventId.AllIndexPropertiesNotToMappedToAnyTable string string + Warning RelationalEventId.AllIndexPropertiesNotToMappedToAnyTable string string The unnamed index on the entity type '{entityType}' specifies properties {indexProperties}. Some properties are mapped to a column in a table, but the property '{propertyName}' is not. All of the properties must be mapped for the index to be created in the database. diff --git a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs index c3fbcedf826..9049e58ca6b 100644 --- a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs +++ b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs @@ -1947,8 +1947,7 @@ public void Passes_for_unnamed_index_with_all_properties_not_mapped_to_any_table definition.GenerateMessage( nameof(Animal), "{'Id', 'Name'}"), - modelBuilder, - LogLevel.Information); + modelBuilder); } [ConditionalFact] @@ -1970,8 +1969,7 @@ public void Passes_for_named_index_with_all_properties_not_mapped_to_any_table() "IX_AllPropertiesNotMapped", nameof(Animal), "{'Id', 'Name'}"), - modelBuilder, - LogLevel.Information); + modelBuilder); } [ConditionalFact] From c1e1a4faa4172beec734123aa467245cec805f72 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 21:05:42 +0000 Subject: [PATCH 067/346] Update dependencies from https://github.com/dotnet/runtime build 20210908.10 (#25941) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 6685d440db6..fdb10256af7 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 - + https://github.com/dotnet/runtime - a77b3910e11cd1000f9efb0e1f3e4ea5cca85266 + f037ca5bc40148550dbd9af6b2749bd5ab494a56 diff --git a/eng/Versions.props b/eng/Versions.props index 48cad4a6429..23bf1853127 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 - 6.0.0-rc.2.21458.5 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.10 3.7.0 From e0f87eb1f42c72fe9b5283fd1ea7e2c7aae2fd17 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 23:31:14 +0000 Subject: [PATCH 068/346] Update dependencies from https://github.com/dotnet/arcade build 20210827.4 (#25945) [release/3.1] Update dependencies from dotnet/arcade --- NuGet.config | 3 --- eng/Version.Details.xml | 4 ++-- eng/common/templates/job/job.yml | 2 +- eng/common/templates/phases/base.yml | 2 +- global.json | 2 +- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/NuGet.config b/NuGet.config index a5cc91700ba..c9987acc588 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,10 +4,8 @@ - - @@ -22,7 +20,6 @@ - diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5a86761a2f5..53ccaa0ced2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -321,9 +321,9 @@ - + https://github.com/dotnet/arcade - c444d7967c5b79d16f2150370504368591883268 + 98e2fbaad9f2f7bbe091bb0b9dd37d03206becc9 https://github.com/dotnet/roslyn diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index ffda80a197b..e1ae3d5be36 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -140,7 +140,7 @@ jobs: - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildSigningPlugin@2 + - task: MicroBuildSigningPlugin@3 displayName: Install MicroBuild plugin inputs: signType: $(_SignType) diff --git a/eng/common/templates/phases/base.yml b/eng/common/templates/phases/base.yml index 0123cf43b16..a87a0b2f687 100644 --- a/eng/common/templates/phases/base.yml +++ b/eng/common/templates/phases/base.yml @@ -82,7 +82,7 @@ phases: - ${{ if eq(parameters.enableMicrobuild, 'true') }}: # Internal only resource, and Microbuild signing shouldn't be applied to PRs. - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildSigningPlugin@2 + - task: MicroBuildSigningPlugin@3 displayName: Install MicroBuild plugin inputs: signType: $(_SignType) diff --git a/global.json b/global.json index c94974db385..14e148f0bd0 100644 --- a/global.json +++ b/global.json @@ -12,6 +12,6 @@ "version": "3.1.118" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.21376.2" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.21427.4" } } From 431d6db7ef11e85ba897bb0702c2a928920c603e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Sep 2021 23:55:09 +0000 Subject: [PATCH 069/346] Update dependencies from https://github.com/dotnet/arcade build 20210827.7 (#25947) [release/5.0] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 8 ++++---- eng/common/templates/job/job.yml | 2 +- eng/common/templates/phases/base.yml | 2 +- global.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 52405279530..be6848f5aed 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -51,13 +51,13 @@ - + https://github.com/dotnet/arcade - 7b8e78dced9b93e5d69fabb9fbc9a2eb5de8e95a + 2e26f9ebee3ac27803aa5f2df50192a46393d108 - + https://github.com/dotnet/arcade - 7b8e78dced9b93e5d69fabb9fbc9a2eb5de8e95a + 2e26f9ebee3ac27803aa5f2df50192a46393d108 diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 8b81a7e5143..2dcda1a8a61 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -103,7 +103,7 @@ jobs: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@2 + - task: MicroBuildSigningPlugin@3 displayName: Install MicroBuild plugin inputs: signType: $(_SignType) diff --git a/eng/common/templates/phases/base.yml b/eng/common/templates/phases/base.yml index 0123cf43b16..a87a0b2f687 100644 --- a/eng/common/templates/phases/base.yml +++ b/eng/common/templates/phases/base.yml @@ -82,7 +82,7 @@ phases: - ${{ if eq(parameters.enableMicrobuild, 'true') }}: # Internal only resource, and Microbuild signing shouldn't be applied to PRs. - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - task: MicroBuildSigningPlugin@2 + - task: MicroBuildSigningPlugin@3 displayName: Install MicroBuild plugin inputs: signType: $(_SignType) diff --git a/global.json b/global.json index 0ad6203ada8..010e707d491 100644 --- a/global.json +++ b/global.json @@ -16,7 +16,7 @@ "rollForward": "latestMajor" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.21409.4", - "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.21409.4" + "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.21427.7", + "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.21427.7" } } From d15aa76577598e7fcee1d726797cba3ea964ceed Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 9 Sep 2021 01:30:23 +0000 Subject: [PATCH 070/346] Update dependencies from https://github.com/dotnet/runtime build 20210908.16 (#25948) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index fdb10256af7..9cd426632e2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc - + https://github.com/dotnet/runtime - f037ca5bc40148550dbd9af6b2749bd5ab494a56 + 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc diff --git a/eng/Versions.props b/eng/Versions.props index 23bf1853127..12a49e57150 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 - 6.0.0-rc.2.21458.10 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21458.16 3.7.0 From 644aee487f228b293d4db30311ffb475f98dee1c Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Thu, 9 Sep 2021 13:44:06 +0200 Subject: [PATCH 071/346] Fixup to index filter validation (#25939) Follow-up to #25931 --- .../Metadata/Internal/RelationalIndexExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalIndexExtensions.cs b/src/EFCore.Relational/Metadata/Internal/RelationalIndexExtensions.cs index a40d8050dc6..020c62ce547 100644 --- a/src/EFCore.Relational/Metadata/Internal/RelationalIndexExtensions.cs +++ b/src/EFCore.Relational/Metadata/Internal/RelationalIndexExtensions.cs @@ -85,7 +85,7 @@ public static bool AreCompatible( return false; } - if (index.GetFilter() != duplicateIndex.GetFilter()) + if (index.GetFilter(storeObject) != duplicateIndex.GetFilter(storeObject)) { throw new InvalidOperationException( RelationalStrings.DuplicateIndexFiltersMismatch( From c0fca38fde1772fbe446b12ecc2891a61bb40084 Mon Sep 17 00:00:00 2001 From: Jon Fortescue Date: Thu, 9 Sep 2021 09:55:56 -0700 Subject: [PATCH 072/346] Switch to R&D pools on main (#25944) --- azure-pipelines-richnav.yml | 2 +- azure-pipelines.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-pipelines-richnav.yml b/azure-pipelines-richnav.yml index 1b520c9f450..c20391025af 100644 --- a/azure-pipelines-richnav.yml +++ b/azure-pipelines-richnav.yml @@ -18,7 +18,7 @@ stages: timeoutInMinutes: 90 enablePublishTestResults: true pool: - name: NetCore1ESPool-Svc-Public + name: NetCore1ESPool-Public demands: ImageOverride -equals Build.Server.Amd64.VS2017.Open steps: - task: NuGetCommand@2 diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 29ff118beb0..d55218769cd 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -60,10 +60,10 @@ stages: enablePublishTestResults: true pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Svc-Public + name: NetCore1ESPool-Public demands: ImageOverride -equals Build.Server.Amd64.VS2017.Open ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Svc-Internal + name: NetCore1ESPool-Internal demands: ImageOverride -equals Build.Server.Amd64.VS2017 variables: - _InternalBuildArgs: '' @@ -187,10 +187,10 @@ stages: timeoutInMinutes: 180 pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Svc-Public + name: NetCore1ESPool-Public demands: ImageOverride -equals Build.Server.Amd64.VS2017.Open ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: NetCore1ESPool-Svc-Internal + name: NetCore1ESPool-Internal demands: ImageOverride -equals Build.Server.Amd64.VS2017 variables: - name: _HelixBuildConfig From d1a2e752b3c830d2827c005eaee74b6871bb3e8b Mon Sep 17 00:00:00 2001 From: maumar Date: Thu, 9 Sep 2021 01:23:09 -0700 Subject: [PATCH 073/346] Adding regression test for #24931 - SqlNullValueException on specific combination of outer joins in LINQ The issue has been fixed earlier (already works in EF Core 5) Resolves #24931 --- ...plexNavigationsCollectionsQueryTestBase.cs | 18 +++++++++++++ ...avigationsCollectionsQuerySqlServerTest.cs | 17 +++++++++++++ ...tionsCollectionsSplitQuerySqlServerTest.cs | 25 +++++++++++++++++++ ...avigationsCollectionsQuerySqlServerTest.cs | 16 ++++++++++++ ...exNavigationsCollectionsQuerySqliteTest.cs | 6 +++++ ...onsCollectionsSharedTypeQuerySqliteTest.cs | 6 +++++ ...igationsCollectionsSplitQuerySqliteTest.cs | 6 +++++ ...llectionsSplitSharedTypeQuerySqliteTest.cs | 6 +++++ 8 files changed, 100 insertions(+) diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs index 7cab664011e..dec01800930 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs @@ -2518,5 +2518,23 @@ public virtual Task FirstOrDefault_with_predicate_on_correlated_collection_in_pr AssertEqual(e.Element, a.Element); }); } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(bool async) + { + return AssertQuery( + async, + ss => from l1 in ss.Set() + from l2 in ss.Set().Where(x => x.Level1_Required_Id == l1.Id * 2 || x.Name.Length == x.Id).DefaultIfEmpty() + select new { Root = l1, Element = l2, Collection = l1.OneToMany_Optional1 }, + elementSorter: e => (e.Root.Id, e.Element.Id), + elementAsserter: (e, a) => + { + AssertEqual(e.Root, a.Root); + AssertEqual(e.Element, a.Element); + AssertCollection(e.Collection, a.Collection); + }); + } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs index d3cf8993279..8f74e6adbde 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs @@ -2174,6 +2174,23 @@ FROM [LevelTwo] AS [l0] ) AS [t0] ON ([l].[Id] = [t0].[OneToMany_Optional_Inverse2Id]) AND ([l].[Id] = [t0].[Id])"); } + + public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(bool async) + { + await base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id] +FROM [LevelOne] AS [l] +OUTER APPLY ( + SELECT [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id] + FROM [LevelTwo] AS [l0] + WHERE ([l0].[Level1_Required_Id] = ([l].[Id] * 2)) OR (CAST(LEN([l0].[Name]) AS int) = [l0].[Id]) +) AS [t] +LEFT JOIN [LevelTwo] AS [l1] ON [l].[Id] = [l1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs index 8df6a120098..5b732bac485 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs @@ -3286,6 +3286,31 @@ FROM [LevelTwo] AS [l0] ) AS [t0] ON ([l].[Id] = [t0].[OneToMany_Optional_Inverse2Id]) AND ([l].[Id] = [t0].[Id])"); } + public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(bool async) + { + await base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id] +FROM [LevelOne] AS [l] +OUTER APPLY ( + SELECT [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id] + FROM [LevelTwo] AS [l0] + WHERE ([l0].[Level1_Required_Id] = ([l].[Id] * 2)) OR (CAST(LEN([l0].[Name]) AS int) = [l0].[Id]) +) AS [t] +ORDER BY [l].[Id], [t].[Id]", + // + @"SELECT [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [l].[Id], [t].[Id] +FROM [LevelOne] AS [l] +OUTER APPLY ( + SELECT [l0].[Id] + FROM [LevelTwo] AS [l0] + WHERE ([l0].[Level1_Required_Id] = ([l].[Id] * 2)) OR (CAST(LEN([l0].[Name]) AS int) = [l0].[Id]) +) AS [t] +INNER JOIN [LevelTwo] AS [l1] ON [l].[Id] = [l1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsCollectionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsCollectionsQuerySqlServerTest.cs index c2258a91a00..5a2c21fbe36 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsCollectionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsCollectionsQuerySqlServerTest.cs @@ -53,6 +53,22 @@ LEFT JOIN ( ORDER BY [l].[Id], [t].[Id]"); } + public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(bool async) + { + await base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [t].[PeriodEnd], [t].[PeriodStart], [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [l1].[PeriodEnd], [l1].[PeriodStart] +FROM [LevelOne] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +OUTER APPLY ( + SELECT [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], [l0].[PeriodEnd], [l0].[PeriodStart] + FROM [LevelTwo] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + WHERE ([l0].[Level1_Required_Id] = ([l].[Id] * 2)) OR (CAST(LEN([l0].[Name]) AS int) = [l0].[Id]) +) AS [t] +LEFT JOIN [LevelTwo] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l].[Id] = [l1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs index 560cca84277..89d2ec29f86 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs @@ -129,5 +129,11 @@ public override async Task Filtered_include_with_Take_without_order_by_followed_ SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async))).Message); + + public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs index 33284ace464..e399e214b5c 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs @@ -119,5 +119,11 @@ public override async Task Filtered_include_with_Take_without_order_by_followed_ SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async))).Message); + + public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs index 7cef283c14a..4ab44875707 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs @@ -105,5 +105,11 @@ public override async Task Filtered_include_with_Take_without_order_by_followed_ SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async))).Message); + + public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs index b99f5739484..e197c42d438 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs @@ -95,5 +95,11 @@ public override async Task Filtered_include_with_Take_without_order_by_followed_ SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async))).Message); + + public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async))).Message); } } From 31afd747541a5de28c58f840f4bbffb17c404bef Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 9 Sep 2021 22:33:04 +0000 Subject: [PATCH 074/346] [release/6.0] Update dependencies from dotnet/runtime (#25959) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9cd426632e2..a1945dfc97a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 - + https://github.com/dotnet/runtime - 4cf387b5af7dfba77c4a6f9b8e30bad46fc735fc + 0933d9a1d3c09fdae125831bd165f983825f77c9 diff --git a/eng/Versions.props b/eng/Versions.props index 12a49e57150..669fef8605c 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 - 6.0.0-rc.2.21458.16 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.10 3.7.0 From 2da38e0c9cbcfa64c4a68873ba83c3f7ecd94650 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Thu, 9 Sep 2021 17:09:51 -0700 Subject: [PATCH 075/346] Query: Add condition when accessing property on optional dependent which is shared (#25949) Resolves #23230 --- ...lationalSqlTranslatingExpressionVisitor.cs | 57 ++++++++++- .../Query/SqlExpressions/SelectExpression.cs | 97 ++++++++++++------- ...ctionsSharedQueryTypeRelationalTestBase.cs | 14 --- ...ctionsSharedTypeQueryRelationalTestBase.cs | 27 ++++++ ...SplitSharedTypeQueryRelationalTestBase.cs} | 14 ++- ...tionsSharedTypeQueryRelationalTestBase.cs} | 5 +- .../GraphUpdatesTestBaseOneToOne.cs | 51 +++++----- .../GraphUpdatesTestBaseOneToOneAk.cs | 85 ++++++++-------- ...CollectionsSharedTypeQuerySqlServerTest.cs | 60 +++++------- ...ctionsSplitSharedTypeQuerySqlServerTest.cs | 2 +- ...NavigationsSharedTypeQuerySqlServerTest.cs | 94 +++++++++++++----- .../Query/GearsOfWarQuerySqlServerTest.cs | 2 +- ...NorthwindQueryFiltersQuerySqlServerTest.cs | 12 +-- .../Query/OwnedQuerySqlServerTest.cs | 16 ++- .../Query/QueryBugsTest.cs | 42 +++++--- .../Query/TPTGearsOfWarQuerySqlServerTest.cs | 2 +- .../TPTTableSplittingSqlServerTest.cs | 18 +++- .../TableSplittingSqlServerTest.cs | 18 +++- ...onsCollectionsSharedTypeQuerySqliteTest.cs | 2 +- ...llectionsSplitSharedTypeQuerySqliteTest.cs | 2 +- ...lexNavigationsSharedTypeQuerySqliteTest.cs | 2 +- 21 files changed, 397 insertions(+), 225 deletions(-) delete mode 100644 test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSharedQueryTypeRelationalTestBase.cs create mode 100644 test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase.cs rename test/EFCore.Relational.Specification.Tests/Query/{ComplexNavigationsCollectionsSplitSharedQueryTypeRelationalTestBase.cs => ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase.cs} (68%) rename test/EFCore.Relational.Specification.Tests/Query/{ComplexNavigationsSharedQueryTypeRelationalTestBase.cs => ComplexNavigationsSharedTypeQueryRelationalTestBase.cs} (89%) diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index dd242f435a5..c28000bb041 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -923,8 +923,63 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) { return null; } + var entityProjectionExpression = (EntityProjectionExpression)valueBufferExpression; + var propertyAccess = entityProjectionExpression.BindProperty(property); - return ((EntityProjectionExpression)valueBufferExpression).BindProperty(property); + var entityType = entityReferenceExpression.EntityType; + var table = entityType.GetViewOrTableMappings().FirstOrDefault()?.Table; + if ((table?.IsOptional(entityType)) != true) + { + return propertyAccess; + } + + // this is optional dependent sharing table + var nonPrincipalSharedNonPkProperties = entityType.GetNonPrincipalSharedNonPkProperties(table); + if (nonPrincipalSharedNonPkProperties.Contains(property)) + { + // The column is not being shared with principal side so we can always use directly + return propertyAccess; + } + + SqlExpression? condition = null; + // Property is being shared with principal side, so we need to make it conditional access + var allRequiredNonPkPropertiesCondition = entityType.GetProperties().Where(p => !p.IsNullable && !p.IsPrimaryKey()).ToList(); + if (allRequiredNonPkPropertiesCondition.Count > 0) + { + condition = allRequiredNonPkPropertiesCondition.Select(p => entityProjectionExpression.BindProperty(p)) + .Select(c => (SqlExpression)_sqlExpressionFactory.NotEqual(c, _sqlExpressionFactory.Constant(null))) + .Aggregate((a, b) => _sqlExpressionFactory.AndAlso(a, b)); + } + + if (nonPrincipalSharedNonPkProperties.Count != 0 + && nonPrincipalSharedNonPkProperties.All(p => p.IsNullable)) + { + // If all non principal shared properties are nullable then we need additional condition + var atLeastOneNonNullValueInNullableColumnsCondition = nonPrincipalSharedNonPkProperties + .Select(p => entityProjectionExpression.BindProperty(p)) + .Select(c => (SqlExpression)_sqlExpressionFactory.NotEqual(c, _sqlExpressionFactory.Constant(null))) + .Aggregate((a, b) => _sqlExpressionFactory.OrElse(a, b)); + + condition = condition == null + ? atLeastOneNonNullValueInNullableColumnsCondition + : _sqlExpressionFactory.AndAlso(condition, atLeastOneNonNullValueInNullableColumnsCondition); + } + + if (condition == null) + { + // if we cannot compute condition then we just return property access (and hope for the best) + return propertyAccess; + } + + return _sqlExpressionFactory.Case( + new List + { + new CaseWhenClause(condition, propertyAccess) + }, + elseResult: null); + + // We don't do above processing for subquery entity since it comes from after subquery which has been + // single result so either it is regular entity or a collection which always have their own table. } if (entityReferenceExpression.SubqueryEntity != null) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index e3a75cd925a..3254d901ac7 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -2136,18 +2136,18 @@ static void GetPartitions(SelectExpression selectExpression, SqlExpression sqlEx && inner.Offset == null && inner.Predicate != null) { - var columnExpressions = new List(); + var outerColumnExpressions = new List(); var joinPredicate = TryExtractJoinKey( outer, inner, inner.Predicate, - columnExpressions, + outerColumnExpressions, allowNonEquality, out var predicate); if (joinPredicate != null) { - joinPredicate = RemoveRedundantNullChecks(joinPredicate, columnExpressions); + joinPredicate = RemoveRedundantNullChecks(joinPredicate, outerColumnExpressions); } // TODO: verify the case for GroupBy. See issue#24474 // We extract join predicate from Predicate part but GroupBy would have last Having. Changing predicate can change groupings @@ -2188,13 +2188,13 @@ static void GetPartitions(SelectExpression selectExpression, SqlExpression sqlEx SelectExpression outer, SelectExpression inner, SqlExpression predicate, - List columnExpressions, + List outerColumnExpressions, bool allowNonEquality, out SqlExpression? updatedPredicate) { if (predicate is SqlBinaryExpression sqlBinaryExpression) { - var joinPredicate = ValidateKeyComparison(outer, inner, sqlBinaryExpression, columnExpressions, allowNonEquality); + var joinPredicate = ValidateKeyComparison(outer, inner, sqlBinaryExpression, outerColumnExpressions, allowNonEquality); if (joinPredicate != null) { updatedPredicate = null; @@ -2205,9 +2205,9 @@ static void GetPartitions(SelectExpression selectExpression, SqlExpression sqlEx if (sqlBinaryExpression.OperatorType == ExpressionType.AndAlso) { var leftJoinKey = TryExtractJoinKey( - outer, inner, sqlBinaryExpression.Left, columnExpressions, allowNonEquality, out var leftPredicate); + outer, inner, sqlBinaryExpression.Left, outerColumnExpressions, allowNonEquality, out var leftPredicate); var rightJoinKey = TryExtractJoinKey( - outer, inner, sqlBinaryExpression.Right, columnExpressions, allowNonEquality, out var rightPredicate); + outer, inner, sqlBinaryExpression.Right, outerColumnExpressions, allowNonEquality, out var rightPredicate); updatedPredicate = CombineNonNullExpressions(leftPredicate, rightPredicate); @@ -2224,7 +2224,7 @@ static void GetPartitions(SelectExpression selectExpression, SqlExpression sqlEx SelectExpression outer, SelectExpression inner, SqlBinaryExpression sqlBinaryExpression, - List columnExpressions, + List outerColumnExpressions, bool allowNonEquality) { if (sqlBinaryExpression.OperatorType == ExpressionType.Equal @@ -2235,45 +2235,39 @@ static void GetPartitions(SelectExpression selectExpression, SqlExpression sqlEx || sqlBinaryExpression.OperatorType == ExpressionType.LessThan || sqlBinaryExpression.OperatorType == ExpressionType.LessThanOrEqual))) { - if (sqlBinaryExpression.Left is ColumnExpression leftColumn - && sqlBinaryExpression.Right is ColumnExpression rightColumn) + if (IsContainedColumn(outer, sqlBinaryExpression.Left) + && IsContainedColumn(inner, sqlBinaryExpression.Right)) { - if (outer.ContainsTableReference(leftColumn) - && inner.ContainsTableReference(rightColumn)) - { - columnExpressions.Add(leftColumn); + outerColumnExpressions.Add(sqlBinaryExpression.Left); - return sqlBinaryExpression; - } + return sqlBinaryExpression; + } - if (outer.ContainsTableReference(rightColumn) - && inner.ContainsTableReference(leftColumn)) - { - columnExpressions.Add(rightColumn); - - return new SqlBinaryExpression( - _mirroredOperationMap[sqlBinaryExpression.OperatorType], - sqlBinaryExpression.Right, - sqlBinaryExpression.Left, - sqlBinaryExpression.Type, - sqlBinaryExpression.TypeMapping); - } + if (IsContainedColumn(outer, sqlBinaryExpression.Right) + && IsContainedColumn(inner, sqlBinaryExpression.Left)) + { + outerColumnExpressions.Add(sqlBinaryExpression.Right); + + return new SqlBinaryExpression( + _mirroredOperationMap[sqlBinaryExpression.OperatorType], + sqlBinaryExpression.Right, + sqlBinaryExpression.Left, + sqlBinaryExpression.Type, + sqlBinaryExpression.TypeMapping); } } // null checks are considered part of join key if (sqlBinaryExpression.OperatorType == ExpressionType.NotEqual) { - if (sqlBinaryExpression.Left is ColumnExpression leftNullCheckColumn - && outer.ContainsTableReference(leftNullCheckColumn) + if (IsContainedColumn(outer, sqlBinaryExpression.Left) && sqlBinaryExpression.Right is SqlConstantExpression rightConstant && rightConstant.Value == null) { return sqlBinaryExpression; } - if (sqlBinaryExpression.Right is ColumnExpression rightNullCheckColumn - && outer.ContainsTableReference(rightNullCheckColumn) + if (IsContainedColumn(outer, sqlBinaryExpression.Right) && sqlBinaryExpression.Left is SqlConstantExpression leftConstant && leftConstant.Value == null) { @@ -2286,6 +2280,36 @@ static void GetPartitions(SelectExpression selectExpression, SqlExpression sqlEx return null; } + static bool IsContainedColumn(SelectExpression selectExpression, SqlExpression sqlExpression) + { + switch (sqlExpression) + { + case ColumnExpression columnExpression: + return selectExpression.ContainsTableReference(columnExpression); + + case SqlConstantExpression sqlConstantExpression + when sqlConstantExpression.Value == null: + return true; + + case SqlBinaryExpression sqlBinaryExpression + when sqlBinaryExpression.OperatorType == ExpressionType.AndAlso + || sqlBinaryExpression.OperatorType == ExpressionType.OrElse + || sqlBinaryExpression.OperatorType == ExpressionType.NotEqual: + return IsContainedColumn(selectExpression, sqlBinaryExpression.Left) + && IsContainedColumn(selectExpression, sqlBinaryExpression.Right); + + case CaseExpression caseExpression + when caseExpression.ElseResult == null + && caseExpression.Operand == null + && caseExpression.WhenClauses.Count == 1: + return IsContainedColumn(selectExpression, caseExpression.WhenClauses[0].Test) + && IsContainedColumn(selectExpression, caseExpression.WhenClauses[0].Result); + + default: + return false; + } + } + static void InnerKeyColumns(IEnumerable tables, SqlExpression joinPredicate, List resultColumns) { if (joinPredicate is SqlBinaryExpression sqlBinaryExpression) @@ -2334,13 +2358,12 @@ static List ExtractColumnsFromProjectionMapping(IDictionary columnExpressions) + static SqlExpression? RemoveRedundantNullChecks(SqlExpression predicate, List outerColumnExpressions) { if (predicate is SqlBinaryExpression sqlBinaryExpression) { if (sqlBinaryExpression.OperatorType == ExpressionType.NotEqual - && sqlBinaryExpression.Left is ColumnExpression leftColumn - && columnExpressions.Contains(leftColumn) + && outerColumnExpressions.Contains(sqlBinaryExpression.Left) && sqlBinaryExpression.Right is SqlConstantExpression sqlConstantExpression && sqlConstantExpression.Value == null) { @@ -2349,8 +2372,8 @@ static List ExtractColumnsFromProjectionMapping(IDictionary : ComplexNavigationsCollectionsSharedTypeQueryTestBase - where TFixture : ComplexNavigationsSharedTypeQueryRelationalFixtureBase, new() - { - protected ComplexNavigationsCollectionsSharedQueryTypeRelationalTestBase(TFixture fixture) - : base(fixture) - { - } - } -} diff --git a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase.cs new file mode 100644 index 00000000000..6afd89e1590 --- /dev/null +++ b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Xunit; + +namespace Microsoft.EntityFrameworkCore.Query +{ + public abstract class ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase : ComplexNavigationsCollectionsSharedTypeQueryTestBase + where TFixture : ComplexNavigationsSharedTypeQueryRelationalFixtureBase, new() + { + protected ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase(TFixture fixture) + : base(fixture) + { + } + + public override async Task SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(bool async) + { + Assert.Equal( + RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, + (await Assert.ThrowsAsync( + () => base.SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(async))).Message); + } + } +} diff --git a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedQueryTypeRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase.cs similarity index 68% rename from test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedQueryTypeRelationalTestBase.cs rename to test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase.cs index ffd317216cc..5a2658dcdcd 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedQueryTypeRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase.cs @@ -1,21 +1,31 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Linq.Expressions; using System.Reflection; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.Diagnostics; using Xunit; namespace Microsoft.EntityFrameworkCore.Query { - public abstract class ComplexNavigationsCollectionsSplitSharedQueryTypeRelationalTestBase : ComplexNavigationsCollectionsSharedTypeQueryTestBase + public abstract class ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase : ComplexNavigationsCollectionsSharedTypeQueryTestBase where TFixture : ComplexNavigationsSharedTypeQueryRelationalFixtureBase, new() { - protected ComplexNavigationsCollectionsSplitSharedQueryTypeRelationalTestBase(TFixture fixture) + protected ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase(TFixture fixture) : base(fixture) { } + public override async Task SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(bool async) + { + Assert.Equal( + RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, + (await Assert.ThrowsAsync( + () => base.SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(async))).Message); + } + protected override Expression RewriteServerQueryExpression(Expression serverQueryExpression) => new SplitQueryRewritingExpressionVisitor().Visit(serverQueryExpression); diff --git a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedQueryTypeRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryRelationalTestBase.cs similarity index 89% rename from test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedQueryTypeRelationalTestBase.cs rename to test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryRelationalTestBase.cs index 28011e2b087..d13de58ee20 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedQueryTypeRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryRelationalTestBase.cs @@ -6,10 +6,10 @@ namespace Microsoft.EntityFrameworkCore.Query { - public abstract class ComplexNavigationsSharedQueryTypeRelationalTestBase : ComplexNavigationsSharedTypeQueryTestBase + public abstract class ComplexNavigationsSharedTypeQueryRelationalTestBase : ComplexNavigationsSharedTypeQueryTestBase where TFixture : ComplexNavigationsSharedTypeQueryRelationalFixtureBase, new() { - protected ComplexNavigationsSharedQueryTypeRelationalTestBase(TFixture fixture) + protected ComplexNavigationsSharedTypeQueryRelationalTestBase(TFixture fixture) : base(fixture) { } @@ -19,6 +19,7 @@ public override Task Complex_query_with_optional_navigations_and_client_side_eva return AssertTranslationFailed(() => base.Complex_query_with_optional_navigations_and_client_side_evaluation(async)); } + protected virtual bool CanExecuteQueryString => false; diff --git a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseOneToOne.cs b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseOneToOne.cs index 93b0d6fc6dc..2595ccf230b 100644 --- a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseOneToOne.cs +++ b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseOneToOne.cs @@ -1242,15 +1242,14 @@ public virtual void Sever_required_one_to_one( AssertKeys(root, loadedRoot); AssertPossiblyNullNavigations(loadedRoot); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingle).Count(e => e.Id == old1.Id); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingle).Count(e => e.Id == old1.Id); + Assert.Equal(0, removedCount); Assert.False(context.Set().Any(r => r.RequiredSingle != null)); - //var orphanedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) - // .Count(e => e.Id == old2.Id); - //Assert.Equal(0, orphanedCount); + var orphanedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) + .Count(e => e.Id == old2.Id); + Assert.Equal(0, orphanedCount); Assert.False(context.Set().Select(r => r.RequiredSingle).Any(r => r.Single != null)); } @@ -1680,15 +1679,14 @@ public virtual void Required_one_to_one_are_cascade_deleted( Assert.Null(root.RequiredSingle); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingle).Count(e => e.Id == removedId); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingle).Count(e => e.Id == removedId); + Assert.Equal(0, removedCount); Assert.False(context.Set().Any(r => r.RequiredSingle != null)); - //var orphanedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) - // .Count(e => e.Id == orphanedId); - //Assert.Equal(0, orphanedCount); + var orphanedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) + .Count(e => e.Id == orphanedId); + Assert.Equal(0, orphanedCount); Assert.False(context.Set().Select(r => r.RequiredSingle).Any(r => r.Single != null)); } @@ -1750,10 +1748,9 @@ public virtual void Required_one_to_one_leaf_can_be_deleted( Assert.Null(parent.Single); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) - // .Count(e => e.Id == removedId); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) + .Count(e => e.Id == removedId); + Assert.Equal(0, removedCount); Assert.False(context.Set().Select(r => r.RequiredSingle).Any(r => r.Single != null)); }); @@ -2147,15 +2144,14 @@ public virtual void Required_one_to_one_are_cascade_deleted_starting_detached( { Assert.Null(root.RequiredSingle); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingle).Count(e => e.Id == removedId); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingle).Count(e => e.Id == removedId); + Assert.Equal(0, removedCount); Assert.False(context.Set().Any(r => r.RequiredSingle != null)); - //var orphanedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) - // .Count(e => e.Id == orphanedId); - //Assert.Equal(0, orphanedCount); + var orphanedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) + .Count(e => e.Id == orphanedId); + Assert.Equal(0, orphanedCount); Assert.False(context.Set().Select(r => r.RequiredSingle).Any(r => r.Single != null)); } @@ -2346,15 +2342,14 @@ public virtual void Required_one_to_one_are_cascade_detached_when_Added( Assert.Null(root.RequiredSingle); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingle).Count(e => e.Id == removedId); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingle).Count(e => e.Id == removedId); + Assert.Equal(0, removedCount); Assert.False(context.Set().Any(r => r.RequiredSingle != null)); - //var orphanedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) - // .Count(e => e.Id == orphanedId); - //Assert.Equal(0, orphanedCount); + var orphanedCount = context.Set().Select(r => r.RequiredSingle).Select(r => r.Single) + .Count(e => e.Id == orphanedId); + Assert.Equal(0, orphanedCount); Assert.False(context.Set().Select(r => r.RequiredSingle).Any(r => r.Single != null)); } diff --git a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseOneToOneAk.cs b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseOneToOneAk.cs index 1f9090fee06..9b9cb5a84b8 100644 --- a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseOneToOneAk.cs +++ b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseOneToOneAk.cs @@ -1145,22 +1145,21 @@ public virtual void Save_required_one_to_one_changed_by_reference_with_alternate AssertKeys(root, loadedRoot); AssertNavigations(loadedRoot); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == old1.Id); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == old1.Id); + Assert.Equal(0, removedCount); Assert.False(context.Set().Any(r => r.RequiredSingleAk != null && r.RequiredSingleAk.Id == old1.Id)); - //var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) - // .Count(e => e.Id == old2.Id); - //Assert.Equal(0, orphanedCount); + var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) + .Count(e => e.Id == old2.Id); + Assert.Equal(0, orphanedCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk) .Any(r => r.Single != null && r.Single.Id == old2.Id)); - //var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) - // .Count(e => e.Id == old2c.Id); - //Assert.Equal(0, orphanedCCount); + var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) + .Count(e => e.Id == old2c.Id); + Assert.Equal(0, orphanedCCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk) .Any(r => r.SingleComposite != null && r.SingleComposite.Id == old2c.Id)); @@ -1512,22 +1511,21 @@ public virtual void Sever_required_one_to_one_with_alternate_key( AssertKeys(root, loadedRoot); AssertPossiblyNullNavigations(loadedRoot); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == old1.Id); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == old1.Id); + Assert.Equal(0, removedCount); Assert.False(context.Set().Any(r => r.RequiredSingleAk != null && r.RequiredSingleAk.Id == old1.Id)); - //var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) - // .Count(e => e.Id == old2.Id); - //Assert.Equal(0, orphanedCount); + var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) + .Count(e => e.Id == old2.Id); + Assert.Equal(0, orphanedCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk) .Any(r => r.Single != null && r.Single.Id == old2.Id)); - //var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) - // .Count(e => e.Id == old2c.Id); - //Assert.Equal(0, orphanedCCount); + var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) + .Count(e => e.Id == old2c.Id); + Assert.Equal(0, orphanedCCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk) .Any(r => r.SingleComposite != null && r.SingleComposite.Id == old2c.Id)); @@ -2013,21 +2011,20 @@ public virtual void Required_one_to_one_with_alternate_key_are_cascade_deleted( Assert.Null(root.RequiredSingleAk); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == removedId); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == removedId); + Assert.Equal(0, removedCount); Assert.False(context.Set().Any(r => r.RequiredSingleAk != null)); - //var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) - // .Count(e => e.Id == orphanedId); - //Assert.Equal(0, orphanedCount); + var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) + .Count(e => e.Id == orphanedId); + Assert.Equal(0, orphanedCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk).Any(r => r.Single != null)); - //var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) - // .Count(e => e.Id == orphanedId); - //Assert.Equal(0, orphanedCCount); + var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) + .Count(e => e.Id == orphanedId); + Assert.Equal(0, orphanedCCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk).Any(r => r.SingleComposite != null)); } @@ -2374,21 +2371,20 @@ public virtual void Required_one_to_one_with_alternate_key_are_cascade_deleted_s Assert.Null(root.RequiredSingleAk); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == removedId); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == removedId); + Assert.Equal(0, removedCount); Assert.False(context.Set().Any(r => r.RequiredSingleAk != null)); - //var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) - // .Count(e => e.Id == orphanedId); - //Assert.Equal(0, orphanedCount); + var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) + .Count(e => e.Id == orphanedId); + Assert.Equal(0, orphanedCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk).Any(r => r.Single != null)); - //var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) - // .Count(e => e.Id == orphanedId); - //Assert.Equal(0, orphanedCCount); + var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) + .Count(e => e.Id == orphanedId); + Assert.Equal(0, orphanedCCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk).Any(r => r.SingleComposite != null)); } @@ -2591,21 +2587,20 @@ public virtual void Required_one_to_one_with_alternate_key_are_cascade_detached_ Assert.Null(root.RequiredSingleAk); - //TODO: Aggregate on optional dependent #23230 - //var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == removedId); - //Assert.Equal(0, removedCount); + var removedCount = context.Set().Select(r => r.RequiredSingleAk).Count(e => e.Id == removedId); + Assert.Equal(0, removedCount); Assert.False(context.Set().Any(r => r.RequiredSingleAk != null)); - //var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) - // .Count(e => e.Id == orphanedId); - //Assert.Equal(0, orphanedCount); + var orphanedCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.Single) + .Count(e => e.Id == orphanedId); + Assert.Equal(0, orphanedCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk).Any(r => r.Single != null)); - //var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) - // .Count(e => e.Id == orphanedId); - //Assert.Equal(0, orphanedCCount); + var orphanedCCount = context.Set().Select(r => r.RequiredSingleAk).Select(r => r.SingleComposite) + .Count(e => e.Id == orphanedId); + Assert.Equal(0, orphanedCCount); Assert.False(context.Set().Select(r => r.RequiredSingleAk).Any(r => r.SingleComposite != null)); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqlServerTest.cs index 01a5005ab02..9f64f135c0f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqlServerTest.cs @@ -6,7 +6,7 @@ namespace Microsoft.EntityFrameworkCore.Query { - public class ComplexNavigationsCollectionsSharedTypeQuerySqlServerTest : ComplexNavigationsCollectionsSharedQueryTypeRelationalTestBase< + public class ComplexNavigationsCollectionsSharedTypeQuerySqlServerTest : ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase< ComplexNavigationsSharedTypeQuerySqlServerFixture> { public ComplexNavigationsCollectionsSharedTypeQuerySqlServerTest( @@ -41,7 +41,9 @@ FROM [Level1] AS [l3] WHERE ([l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL) AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL ) AS [t1] ON [l2].[Id] = [t1].[Id] WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL -) AS [t0] ON [t].[Id] = [t0].[OneToMany_Optional_Inverse3Id] +) AS [t0] ON CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); } @@ -68,28 +70,6 @@ FROM [Level1] AS [l2] ORDER BY [l].[Id], [t].[Id], [t0].[Id]"); } - public override async Task SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(bool async) - { - await base.SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(async); - - AssertSql( - @"SELECT [l].[Id], [l].[Date], [l].[Name], [t].[Id], [t].[Name], [t].[FK], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[Id0] -FROM [Level1] AS [l] -INNER JOIN ( - SELECT DISTINCT [l0].[Id], [l0].[Level2_Name] AS [Name], [l0].[OneToMany_Optional_Inverse2Id] AS [FK] - FROM [Level1] AS [l0] - INNER JOIN [Level1] AS [l1] ON [l0].[Id] = [l1].[Id] - WHERE ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL -) AS [t] ON [l].[Id] = [t].[FK] -LEFT JOIN ( - SELECT [l2].[Id], [l2].[OneToOne_Required_PK_Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Level2_Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l3].[Id] AS [Id0] - FROM [Level1] AS [l2] - INNER JOIN [Level1] AS [l3] ON [l2].[Id] = [l3].[Id] - WHERE ([l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id] IS NOT NULL) AND [l2].[OneToMany_Required_Inverse2Id] IS NOT NULL -) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] -ORDER BY [l].[Id], [t].[Id], [t].[Name], [t].[FK], [t0].[Id]"); - } - public override async Task Take_Select_collection_Take(bool async) { await base.Take_Select_collection_Take(async); @@ -97,24 +77,30 @@ public override async Task Take_Select_collection_Take(bool async) AssertSql( @"@__p_0='1' -SELECT [t].[Id], [t].[Name], [t0].[Id], [t0].[Name], [t0].[Level1Id], [t0].[Level2Id], [t0].[Id0], [t0].[Date], [t0].[Name0], [t0].[Id00] +SELECT [t].[Id], [t].[Name], [t0].[Id], [t0].[Name], [t0].[Level1Id], [t0].[Level2Id], [t0].[Id0], [t0].[Date], [t0].[Name0], [t0].[Id1], [t0].[Id00] FROM ( SELECT TOP(@__p_0) [l].[Id], [l].[Name] FROM [Level1] AS [l] ORDER BY [l].[Id] ) AS [t] OUTER APPLY ( - SELECT [t1].[Id], [t1].[Level2_Name] AS [Name], [t1].[OneToMany_Required_Inverse2Id] AS [Level1Id], [t1].[Level1_Required_Id] AS [Level2Id], [l1].[Id] AS [Id0], [l1].[Date], [l1].[Name] AS [Name0], [t1].[Id0] AS [Id00] + SELECT CASE + WHEN ([t1].[OneToOne_Required_PK_Date] IS NOT NULL AND [t1].[Level1_Required_Id] IS NOT NULL) AND [t1].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t1].[Id] + END AS [Id], [t1].[Level2_Name] AS [Name], [t1].[OneToMany_Required_Inverse2Id] AS [Level1Id], [t1].[Level1_Required_Id] AS [Level2Id], [l1].[Id] AS [Id0], [l1].[Date], [l1].[Name] AS [Name0], [t1].[Id] AS [Id1], [t1].[Id0] AS [Id00], [t1].[c] FROM ( - SELECT TOP(3) [l0].[Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Required_Inverse2Id], [l2].[Id] AS [Id0] + SELECT TOP(3) [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Required_Inverse2Id], [l2].[Id] AS [Id0], CASE + WHEN ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] FROM [Level1] AS [l0] INNER JOIN [Level1] AS [l2] ON [l0].[Id] = [l2].[Id] WHERE (([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL) AND ([t].[Id] = [l0].[OneToMany_Required_Inverse2Id]) - ORDER BY [l0].[Id] + ORDER BY CASE + WHEN ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END ) AS [t1] INNER JOIN [Level1] AS [l1] ON [t1].[Level1_Required_Id] = [l1].[Id] ) AS [t0] -ORDER BY [t].[Id], [t0].[Id], [t0].[Id00]"); +ORDER BY [t].[Id], [t0].[c], [t0].[Id1], [t0].[Id00]"); } public override async Task Skip_Take_Select_collection_Skip_Take(bool async) @@ -124,7 +110,7 @@ public override async Task Skip_Take_Select_collection_Skip_Take(bool async) AssertSql( @"@__p_0='1' -SELECT [t].[Id], [t].[Name], [t0].[Id], [t0].[Name], [t0].[Level1Id], [t0].[Level2Id], [t0].[Id0], [t0].[Date], [t0].[Name0], [t0].[Id00] +SELECT [t].[Id], [t].[Name], [t0].[Id], [t0].[Name], [t0].[Level1Id], [t0].[Level2Id], [t0].[Id0], [t0].[Date], [t0].[Name0], [t0].[Id1], [t0].[Id00] FROM ( SELECT [l].[Id], [l].[Name] FROM [Level1] AS [l] @@ -132,18 +118,24 @@ ORDER BY [l].[Id] OFFSET @__p_0 ROWS FETCH NEXT @__p_0 ROWS ONLY ) AS [t] OUTER APPLY ( - SELECT [t1].[Id], [t1].[Level2_Name] AS [Name], [t1].[OneToMany_Required_Inverse2Id] AS [Level1Id], [t1].[Level1_Required_Id] AS [Level2Id], [l1].[Id] AS [Id0], [l1].[Date], [l1].[Name] AS [Name0], [t1].[Id0] AS [Id00] + SELECT CASE + WHEN ([t1].[OneToOne_Required_PK_Date] IS NOT NULL AND [t1].[Level1_Required_Id] IS NOT NULL) AND [t1].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t1].[Id] + END AS [Id], [t1].[Level2_Name] AS [Name], [t1].[OneToMany_Required_Inverse2Id] AS [Level1Id], [t1].[Level1_Required_Id] AS [Level2Id], [l1].[Id] AS [Id0], [l1].[Date], [l1].[Name] AS [Name0], [t1].[Id] AS [Id1], [t1].[Id0] AS [Id00], [t1].[c] FROM ( - SELECT [l0].[Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Required_Inverse2Id], [l2].[Id] AS [Id0] + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Required_Inverse2Id], [l2].[Id] AS [Id0], CASE + WHEN ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] FROM [Level1] AS [l0] INNER JOIN [Level1] AS [l2] ON [l0].[Id] = [l2].[Id] WHERE (([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL) AND ([t].[Id] = [l0].[OneToMany_Required_Inverse2Id]) - ORDER BY [l0].[Id] + ORDER BY CASE + WHEN ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END OFFSET 1 ROWS FETCH NEXT 3 ROWS ONLY ) AS [t1] INNER JOIN [Level1] AS [l1] ON [t1].[Level1_Required_Id] = [l1].[Id] ) AS [t0] -ORDER BY [t].[Id], [t0].[Id], [t0].[Id00]"); +ORDER BY [t].[Id], [t0].[c], [t0].[Id1], [t0].[Id00]"); } private void AssertSql(params string[] expected) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqlServerTest.cs index 81000353e66..b47a4cee6b9 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqlServerTest.cs @@ -5,7 +5,7 @@ namespace Microsoft.EntityFrameworkCore.Query { - public class ComplexNavigationsCollectionsSplitSharedTypeQuerySqlServerTest : ComplexNavigationsCollectionsSplitSharedQueryTypeRelationalTestBase< + public class ComplexNavigationsCollectionsSplitSharedTypeQuerySqlServerTest : ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase< ComplexNavigationsSharedTypeQuerySqlServerFixture> { public ComplexNavigationsCollectionsSplitSharedTypeQuerySqlServerTest( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqlServerTest.cs index 0373cf59881..8505db8561e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqlServerTest.cs @@ -6,7 +6,7 @@ namespace Microsoft.EntityFrameworkCore.Query { - public class ComplexNavigationsSharedTypeQuerySqlServerTest : ComplexNavigationsSharedQueryTypeRelationalTestBase< + public class ComplexNavigationsSharedTypeQuerySqlServerTest : ComplexNavigationsSharedTypeQueryRelationalTestBase< ComplexNavigationsSharedTypeQuerySqlServerFixture> { public ComplexNavigationsSharedTypeQuerySqlServerTest( @@ -30,7 +30,9 @@ LEFT JOIN ( FROM [Level1] AS [l0] INNER JOIN [Level1] AS [l1] ON [l0].[Id] = [l1].[Id] WHERE ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL -) AS [t] ON [l].[Id] = [t].[Id]"); +) AS [t] ON [l].[Id] = CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END"); } public override async Task Simple_level1(bool async) @@ -53,7 +55,9 @@ LEFT JOIN ( FROM [Level1] AS [l0] INNER JOIN [Level1] AS [l1] ON [l0].[Id] = [l1].[Id] WHERE ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL -) AS [t] ON [l].[Id] = [t].[Id] +) AS [t] ON [l].[Id] = CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END LEFT JOIN ( SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id] FROM [Level1] AS [l2] @@ -64,7 +68,11 @@ FROM [Level1] AS [l3] WHERE ([l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL) AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL ) AS [t1] ON [l2].[Id] = [t1].[Id] WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL -) AS [t0] ON [t].[Id] = [t0].[Id]"); +) AS [t0] ON CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] +END"); } public override async Task Simple_level1_level2_GroupBy_Count(bool async) @@ -75,13 +83,15 @@ public override async Task Simple_level1_level2_GroupBy_Count(bool async) @"SELECT COUNT(*) FROM [Level1] AS [l] LEFT JOIN ( - SELECT [l0].[Id] + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id] FROM [Level1] AS [l0] INNER JOIN [Level1] AS [l1] ON [l0].[Id] = [l1].[Id] WHERE ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL -) AS [t] ON [l].[Id] = [t].[Id] +) AS [t] ON [l].[Id] = CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END LEFT JOIN ( - SELECT [l2].[Id], [l2].[Level3_Name] + SELECT [l2].[Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Required_Inverse3Id] FROM [Level1] AS [l2] INNER JOIN ( SELECT [l3].[Id] @@ -90,7 +100,11 @@ FROM [Level1] AS [l3] WHERE ([l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL) AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL ) AS [t1] ON [l2].[Id] = [t1].[Id] WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL -) AS [t0] ON [t].[Id] = [t0].[Id] +) AS [t0] ON CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] +END GROUP BY [t0].[Level3_Name]"); } @@ -102,13 +116,15 @@ public override async Task Simple_level1_level2_GroupBy_Having_Count(bool async) @"SELECT COUNT(*) FROM [Level1] AS [l] LEFT JOIN ( - SELECT [l0].[Id] + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id] FROM [Level1] AS [l0] INNER JOIN [Level1] AS [l1] ON [l0].[Id] = [l1].[Id] WHERE ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL -) AS [t] ON [l].[Id] = [t].[Id] +) AS [t] ON [l].[Id] = CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END LEFT JOIN ( - SELECT [l2].[Id], [l2].[Level3_Name] + SELECT [l2].[Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Required_Inverse3Id] FROM [Level1] AS [l2] INNER JOIN ( SELECT [l3].[Id] @@ -117,15 +133,23 @@ FROM [Level1] AS [l3] WHERE ([l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL) AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL ) AS [t1] ON [l2].[Id] = [t1].[Id] WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL -) AS [t0] ON [t].[Id] = [t0].[Id] +) AS [t0] ON CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] +END LEFT JOIN ( - SELECT [l5].[Id] + SELECT [l5].[Id], [l5].[OneToOne_Required_PK_Date], [l5].[Level1_Required_Id], [l5].[OneToMany_Required_Inverse2Id] FROM [Level1] AS [l5] INNER JOIN [Level1] AS [l6] ON [l5].[Id] = [l6].[Id] WHERE ([l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL) AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL -) AS [t2] ON [l].[Id] = [t2].[Id] +) AS [t2] ON [l].[Id] = CASE + WHEN ([t2].[OneToOne_Required_PK_Date] IS NOT NULL AND [t2].[Level1_Required_Id] IS NOT NULL) AND [t2].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t2].[Id] +END GROUP BY [t0].[Level3_Name] -HAVING MIN(COALESCE([t2].[Id], 0)) > 0"); +HAVING MIN(COALESCE(CASE + WHEN ([t2].[OneToOne_Required_PK_Date] IS NOT NULL AND [t2].[Level1_Required_Id] IS NOT NULL) AND [t2].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t2].[Id] +END, 0)) > 0"); } public override async Task Simple_level1_level2_level3_include(bool async) @@ -140,7 +164,9 @@ LEFT JOIN ( FROM [Level1] AS [l0] INNER JOIN [Level1] AS [l1] ON [l0].[Id] = [l1].[Id] WHERE ([l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL) AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL -) AS [t] ON [l].[Id] = [t].[Id] +) AS [t] ON [l].[Id] = CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END LEFT JOIN ( SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id] FROM [Level1] AS [l2] @@ -151,7 +177,11 @@ FROM [Level1] AS [l3] WHERE ([l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL) AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL ) AS [t1] ON [l2].[Id] = [t1].[Id] WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL -) AS [t0] ON [t].[Id] = [t0].[Id] +) AS [t0] ON CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] +END LEFT JOIN ( SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id] FROM [Level1] AS [l5] @@ -167,7 +197,11 @@ FROM [Level1] AS [l7] WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL ) AS [t3] ON [l5].[Id] = [t3].[Id] WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL -) AS [t2] ON [t0].[Id] = [t2].[Id]"); +) AS [t2] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] +END = CASE + WHEN [t2].[Level3_Required_Id] IS NOT NULL AND [t2].[OneToMany_Required_Inverse4Id] IS NOT NULL THEN [t2].[Id] +END"); } public override async Task Nested_group_join_with_take(bool async) @@ -179,17 +213,19 @@ public override async Task Nested_group_join_with_take(bool async) SELECT [t2].[Level2_Name] FROM ( - SELECT TOP(@__p_0) [l].[Id], [t0].[Id0] AS [Id00] + SELECT TOP(@__p_0) [l].[Id], [t0].[Id0] AS [Id00], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Required_Id], [t0].[OneToMany_Required_Inverse2Id] FROM [Level1] AS [l] LEFT JOIN ( - SELECT [t].[Id] AS [Id0], [t].[Level1_Optional_Id] + SELECT [t].[Id] AS [Id0], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[OneToMany_Required_Inverse2Id] FROM [Level1] AS [l0] LEFT JOIN ( SELECT [l1].[Id], [l1].[OneToOne_Required_PK_Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[OneToMany_Required_Inverse2Id] FROM [Level1] AS [l1] INNER JOIN [Level1] AS [l2] ON [l1].[Id] = [l2].[Id] WHERE ([l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL) AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL - ) AS [t] ON [l0].[Id] = [t].[Id] + ) AS [t] ON [l0].[Id] = CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END WHERE ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL ) AS [t0] ON [l].[Id] = [t0].[Level1_Optional_Id] ORDER BY [l].[Id] @@ -202,9 +238,13 @@ LEFT JOIN ( FROM [Level1] AS [l4] INNER JOIN [Level1] AS [l5] ON [l4].[Id] = [l5].[Id] WHERE ([l4].[OneToOne_Required_PK_Date] IS NOT NULL AND [l4].[Level1_Required_Id] IS NOT NULL) AND [l4].[OneToMany_Required_Inverse2Id] IS NOT NULL - ) AS [t3] ON [l3].[Id] = [t3].[Id] + ) AS [t3] ON [l3].[Id] = CASE + WHEN ([t3].[OneToOne_Required_PK_Date] IS NOT NULL AND [t3].[Level1_Required_Id] IS NOT NULL) AND [t3].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t3].[Id] + END WHERE ([t3].[OneToOne_Required_PK_Date] IS NOT NULL AND [t3].[Level1_Required_Id] IS NOT NULL) AND [t3].[OneToMany_Required_Inverse2Id] IS NOT NULL -) AS [t2] ON [t1].[Id00] = [t2].[Level1_Optional_Id] +) AS [t2] ON CASE + WHEN ([t1].[OneToOne_Required_PK_Date] IS NOT NULL AND [t1].[Level1_Required_Id] IS NOT NULL) AND [t1].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t1].[Id00] +END = [t2].[Level1_Optional_Id] ORDER BY [t1].[Id]"); } @@ -225,7 +265,9 @@ LEFT JOIN ( FROM [Level1] AS [l1] INNER JOIN [Level1] AS [l2] ON [l1].[Id] = [l2].[Id] WHERE ([l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL) AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL - ) AS [t] ON [l0].[Id] = [t].[Id] + ) AS [t] ON [l0].[Id] = CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END WHERE ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL ) AS [t0] ON [l].[Id] = [t0].[Level1_Optional_Id] WHERE ([t0].[Level2_Name] <> N'Foo') OR [t0].[Level2_Name] IS NULL @@ -250,7 +292,9 @@ LEFT JOIN ( FROM [Level1] AS [l1] INNER JOIN [Level1] AS [l2] ON [l1].[Id] = [l2].[Id] WHERE ([l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL) AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL - ) AS [t] ON [l0].[Id] = [t].[Id] + ) AS [t] ON [l0].[Id] = CASE + WHEN ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END WHERE ([t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL) AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL ) AS [t0] ON [l].[Id] = [t0].[Level1_Optional_Id]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 4bc495cf9e4..d7d70fd8348 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -6051,7 +6051,7 @@ public override async Task Null_checks_in_correlated_predicate_are_correctly_tra AssertSql( @"SELECT [t].[Id], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] FROM [Tags] AS [t] -LEFT JOIN [Gears] AS [g] ON (([t].[GearNickName] = [g].[Nickname]) AND ([t].[GearSquadId] = [g].[SquadId])) AND [t].[Note] IS NOT NULL +LEFT JOIN [Gears] AS [g] ON ([t].[GearNickName] = [g].[Nickname]) AND ([t].[GearSquadId] = [g].[SquadId]) ORDER BY [t].[Id], [g].[Nickname]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindQueryFiltersQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindQueryFiltersQuerySqlServerTest.cs index 3dcbaf150af..fd532180a09 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindQueryFiltersQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindQueryFiltersQuerySqlServerTest.cs @@ -122,15 +122,15 @@ public override async Task Include_query(bool async) SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[CustomerID0] FROM [Customers] AS [c] LEFT JOIN ( - SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [t].[CustomerID] AS [CustomerID0] + SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [t].[CustomerID] AS [CustomerID0], [t].[CompanyName] FROM [Orders] AS [o] LEFT JOIN ( SELECT [c0].[CustomerID], [c0].[CompanyName] FROM [Customers] AS [c0] WHERE (@__ef_filter__TenantPrefix_0 = N'') OR ([c0].[CompanyName] IS NOT NULL AND (LEFT([c0].[CompanyName], LEN(@__ef_filter__TenantPrefix_0)) = @__ef_filter__TenantPrefix_0)) ) AS [t] ON [o].[CustomerID] = [t].[CustomerID] - WHERE [t].[CustomerID] IS NOT NULL AND [t].[CompanyName] IS NOT NULL -) AS [t0] ON [c].[CustomerID] = [t0].[CustomerID] + WHERE [t].[CustomerID] IS NOT NULL +) AS [t0] ON [t0].[CompanyName] IS NOT NULL AND ([c].[CustomerID] = [t0].[CustomerID]) WHERE (@__ef_filter__TenantPrefix_0 = N'') OR ([c].[CompanyName] IS NOT NULL AND (LEFT([c].[CompanyName], LEN(@__ef_filter__TenantPrefix_0)) = @__ef_filter__TenantPrefix_0)) ORDER BY [c].[CustomerID], [t0].[OrderID]"); } @@ -197,15 +197,15 @@ public override async Task Navs_query(bool async) SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] INNER JOIN ( - SELECT [o].[OrderID], [o].[CustomerID] + SELECT [o].[OrderID], [o].[CustomerID], [t].[CompanyName] FROM [Orders] AS [o] LEFT JOIN ( SELECT [c0].[CustomerID], [c0].[CompanyName] FROM [Customers] AS [c0] WHERE (@__ef_filter__TenantPrefix_0 = N'') OR ([c0].[CompanyName] IS NOT NULL AND (LEFT([c0].[CompanyName], LEN(@__ef_filter__TenantPrefix_0)) = @__ef_filter__TenantPrefix_0)) ) AS [t] ON [o].[CustomerID] = [t].[CustomerID] - WHERE [t].[CustomerID] IS NOT NULL AND [t].[CompanyName] IS NOT NULL -) AS [t0] ON [c].[CustomerID] = [t0].[CustomerID] + WHERE [t].[CustomerID] IS NOT NULL +) AS [t0] ON [t0].[CompanyName] IS NOT NULL AND ([c].[CustomerID] = [t0].[CustomerID]) INNER JOIN ( SELECT [o0].[OrderID], [o0].[Discount] FROM [Order Details] AS [o0] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs index 2ad05cf8f67..6647fb21fea 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs @@ -1114,7 +1114,9 @@ LEFT JOIN ( FROM [OwnedPerson] AS [o] INNER JOIN [OwnedPerson] AS [o0] ON [o].[Id] = [o0].[Id] WHERE [o].[PersonAddress_ZipCode] IS NOT NULL -) AS [t] ON [m].[Id] = [t].[Id] +) AS [t] ON [m].[Id] = CASE + WHEN [t].[PersonAddress_ZipCode] IS NOT NULL THEN [t].[Id] +END LEFT JOIN ( SELECT [o1].[Id], [o1].[BranchAddress_BranchName], [o1].[BranchAddress_PlaceType], [t1].[Id] AS [Id0], [o1].[Id] AS [Id1], [o1].[BranchAddress_Country_Name], [o1].[BranchAddress_Country_PlanetId] FROM [OwnedPerson] AS [o1] @@ -1124,7 +1126,9 @@ FROM [OwnedPerson] AS [o2] WHERE [o2].[Discriminator] IN (N'Branch', N'LeafA') ) AS [t1] ON [o1].[Id] = [t1].[Id] WHERE [o1].[BranchAddress_BranchName] IS NOT NULL -) AS [t0] ON [m].[Id] = [t0].[Id] +) AS [t0] ON [m].[Id] = CASE + WHEN [t0].[BranchAddress_BranchName] IS NOT NULL THEN [t0].[Id] +END LEFT JOIN ( SELECT [o3].[Id], [o3].[LeafBAddress_LeafBType], [o3].[LeafBAddress_PlaceType], [t3].[Id] AS [Id0], [o3].[Id] AS [Id1], [o3].[LeafBAddress_Country_Name], [o3].[LeafBAddress_Country_PlanetId] FROM [OwnedPerson] AS [o3] @@ -1134,7 +1138,9 @@ FROM [OwnedPerson] AS [o4] WHERE [o4].[Discriminator] = N'LeafB' ) AS [t3] ON [o3].[Id] = [t3].[Id] WHERE [o3].[LeafBAddress_LeafBType] IS NOT NULL -) AS [t2] ON [m].[Id] = [t2].[Id] +) AS [t2] ON [m].[Id] = CASE + WHEN [t2].[LeafBAddress_LeafBType] IS NOT NULL THEN [t2].[Id] +END LEFT JOIN ( SELECT [o5].[Id], [o5].[LeafAAddress_LeafType], [o5].[LeafAAddress_PlaceType], [t5].[Id] AS [Id0], [o5].[Id] AS [Id1], [o5].[LeafAAddress_Country_Name], [o5].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o5] @@ -1144,7 +1150,9 @@ FROM [OwnedPerson] AS [o6] WHERE [o6].[Discriminator] = N'LeafA' ) AS [t5] ON [o5].[Id] = [t5].[Id] WHERE [o5].[LeafAAddress_LeafType] IS NOT NULL -) AS [t4] ON [m].[Id] = [t4].[Id] +) AS [t4] ON [m].[Id] = CASE + WHEN [t4].[LeafAAddress_LeafType] IS NOT NULL THEN [t4].[Id] +END LEFT JOIN ( SELECT [o7].[ClientId], [o7].[Id], [o7].[OrderDate], [o8].[OrderClientId], [o8].[OrderId], [o8].[Id] AS [Id0], [o8].[Detail] FROM [Order] AS [o7] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs index f5fb891b70c..4aa24d68af7 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs @@ -2832,11 +2832,13 @@ from a in grouping.DefaultIfEmpty() @"SELECT [t1].[AnotherEntity11818_Name] AS [Key], COUNT(*) + 5 AS [cnt] FROM [Table] AS [t] LEFT JOIN ( - SELECT [t0].[Id], [t0].[AnotherEntity11818_Name] + SELECT [t0].[Id], [t0].[Exists], [t0].[AnotherEntity11818_Name] FROM [Table] AS [t0] INNER JOIN [Table] AS [t2] ON [t0].[Id] = [t2].[Id] WHERE [t0].[Exists] IS NOT NULL -) AS [t1] ON [t].[Id] = [t1].[Id] +) AS [t1] ON [t].[Id] = CASE + WHEN [t1].[Exists] IS NOT NULL THEN [t1].[Id] +END GROUP BY [t1].[AnotherEntity11818_Name]"); } @@ -2863,17 +2865,21 @@ from m in grouping2.DefaultIfEmpty() @"SELECT [t1].[AnotherEntity11818_Name] AS [MyKey], COUNT(*) + 5 AS [cnt] FROM [Table] AS [t] LEFT JOIN ( - SELECT [t0].[Id], [t0].[AnotherEntity11818_Name] + SELECT [t0].[Id], [t0].[Exists], [t0].[AnotherEntity11818_Name] FROM [Table] AS [t0] INNER JOIN [Table] AS [t2] ON [t0].[Id] = [t2].[Id] WHERE [t0].[Exists] IS NOT NULL -) AS [t1] ON [t].[Id] = [t1].[Id] +) AS [t1] ON [t].[Id] = CASE + WHEN [t1].[Exists] IS NOT NULL THEN [t1].[Id] +END LEFT JOIN ( - SELECT [t4].[Id], [t4].[MaumarEntity11818_Name] + SELECT [t4].[Id], [t4].[MaumarEntity11818_Exists], [t4].[MaumarEntity11818_Name] FROM [Table] AS [t4] INNER JOIN [Table] AS [t5] ON [t4].[Id] = [t5].[Id] WHERE [t4].[MaumarEntity11818_Exists] IS NOT NULL -) AS [t3] ON [t].[Id] = [t3].[Id] +) AS [t3] ON [t].[Id] = CASE + WHEN [t3].[MaumarEntity11818_Exists] IS NOT NULL THEN [t3].[Id] +END GROUP BY [t1].[AnotherEntity11818_Name], [t3].[MaumarEntity11818_Name]"); } @@ -2898,17 +2904,21 @@ from m in grouping2.DefaultIfEmpty() @"SELECT TOP(1) [t1].[AnotherEntity11818_Name] AS [MyKey], [t3].[MaumarEntity11818_Name] AS [cnt] FROM [Table] AS [t] LEFT JOIN ( - SELECT [t0].[Id], [t0].[AnotherEntity11818_Name] + SELECT [t0].[Id], [t0].[Exists], [t0].[AnotherEntity11818_Name] FROM [Table] AS [t0] INNER JOIN [Table] AS [t2] ON [t0].[Id] = [t2].[Id] WHERE [t0].[Exists] IS NOT NULL -) AS [t1] ON [t].[Id] = [t1].[Id] +) AS [t1] ON [t].[Id] = CASE + WHEN [t1].[Exists] IS NOT NULL THEN [t1].[Id] +END LEFT JOIN ( - SELECT [t4].[Id], [t4].[MaumarEntity11818_Name] + SELECT [t4].[Id], [t4].[MaumarEntity11818_Exists], [t4].[MaumarEntity11818_Name] FROM [Table] AS [t4] INNER JOIN [Table] AS [t5] ON [t4].[Id] = [t5].[Id] WHERE [t4].[MaumarEntity11818_Exists] IS NOT NULL -) AS [t3] ON [t].[Id] = [t3].[Id] +) AS [t3] ON [t].[Id] = CASE + WHEN [t3].[MaumarEntity11818_Exists] IS NOT NULL THEN [t3].[Id] +END GROUP BY [t1].[AnotherEntity11818_Name], [t3].[MaumarEntity11818_Name]"); } } @@ -7693,13 +7703,19 @@ ORDER BY [a].[Id] DESC LEFT JOIN ( SELECT [s].[Id], [s].[AggregateId], [s].[FourthValueObject_Value], [f].[Id] AS [Id0], [f].[AnyValue], [f].[SecondValueObjectId], [t1].[Id] AS [Id1], [t1].[SecondValueObjectId] AS [SecondValueObjectId0], [t1].[FourthValueObject_Value] AS [FourthValueObject_Value0], [t1].[Id0] AS [Id00], [t1].[AnyValue] AS [AnyValue0], [t1].[ThirdValueObjectId] FROM [SecondValueObjects] AS [s] - LEFT JOIN [FourthFifthValueObjects] AS [f] ON [s].[Id] = [f].[SecondValueObjectId] + LEFT JOIN [FourthFifthValueObjects] AS [f] ON CASE + WHEN [s].[FourthValueObject_Value] IS NOT NULL THEN [s].[Id] + END = [f].[SecondValueObjectId] LEFT JOIN ( SELECT [t0].[Id], [t0].[SecondValueObjectId], [t0].[FourthValueObject_Value], [t3].[Id] AS [Id0], [t3].[AnyValue], [t3].[ThirdValueObjectId] FROM [ThirdValueObjects] AS [t0] - LEFT JOIN [ThirdFifthValueObjects] AS [t3] ON [t0].[Id] = [t3].[ThirdValueObjectId] + LEFT JOIN [ThirdFifthValueObjects] AS [t3] ON CASE + WHEN [t0].[FourthValueObject_Value] IS NOT NULL THEN [t0].[Id] + END = [t3].[ThirdValueObjectId] ) AS [t1] ON [s].[Id] = [t1].[SecondValueObjectId] -) AS [t2] ON [t].[Id] = [t2].[AggregateId] +) AS [t2] ON CASE + WHEN [t].[FirstValueObject_Value] IS NOT NULL THEN [t].[Id] +END = [t2].[AggregateId] ORDER BY [t].[Id] DESC, [t2].[Id], [t2].[Id0], [t2].[Id1]"); } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index 7b98acf1e21..14dcaaf851e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -7085,7 +7085,7 @@ WHEN [o].[Nickname] IS NOT NULL THEN N'Officer' END AS [Discriminator] FROM [Gears] AS [g] LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[SquadId] = [o].[SquadId]) -) AS [t0] ON (([t].[GearNickName] = [t0].[Nickname]) AND ([t].[GearSquadId] = [t0].[SquadId])) AND [t].[Note] IS NOT NULL +) AS [t0] ON ([t].[GearNickName] = [t0].[Nickname]) AND ([t].[GearSquadId] = [t0].[SquadId]) ORDER BY [t].[Id], [t0].[Nickname]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/TPTTableSplittingSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/TPTTableSplittingSqlServerTest.cs index 74c699a466c..5e1d29cc9d0 100644 --- a/test/EFCore.SqlServer.FunctionalTests/TPTTableSplittingSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/TPTTableSplittingSqlServerTest.cs @@ -52,7 +52,9 @@ FROM [Vehicles] AS [v4] ) AS [t3] ON [v3].[Name] = [t3].[Name] ) AS [t2] ON [v2].[Name] = [t2].[Name] WHERE [v2].[Active] IS NOT NULL -) AS [t1] ON [t0].[Name] = [t1].[Name] +) AS [t1] ON [t0].[Name] = CASE + WHEN [t1].[Active] IS NOT NULL THEN [t1].[Name] +END LEFT JOIN ( SELECT [p2].[Name], [p2].[Computed], [p2].[Description], CASE WHEN [s].[VehicleName] IS NOT NULL THEN N'SolidRocket' @@ -69,7 +71,9 @@ FROM [Vehicles] AS [v5] INNER JOIN [PoweredVehicles] AS [p3] ON [v5].[Name] = [p3].[Name] ) AS [t5] ON [p2].[Name] = [t5].[Name] WHERE [p2].[Computed] IS NOT NULL -) AS [t4] ON [v].[Name] = [t4].[Name] +) AS [t4] ON [v].[Name] = CASE + WHEN [t4].[Computed] IS NOT NULL THEN [t4].[Name] +END LEFT JOIN ( SELECT [c5].[VehicleName], [c5].[Capacity], [c5].[FuelType], [s0].[GrainGeometry], CASE WHEN [s0].[VehicleName] IS NOT NULL THEN N'SolidFuelTank' @@ -82,7 +86,11 @@ FROM [PoweredVehicles] AS [p4] INNER JOIN [CombustionEngines] AS [c6] ON [p4].[Name] = [c6].[VehicleName] ) AS [t7] ON [c5].[VehicleName] = [t7].[Name] WHERE [c5].[Capacity] IS NOT NULL -) AS [t6] ON [t4].[Name] = [t6].[VehicleName] +) AS [t6] ON CASE + WHEN [t4].[Computed] IS NOT NULL THEN [t4].[Name] +END = CASE + WHEN [t6].[Capacity] IS NOT NULL THEN [t6].[VehicleName] +END ORDER BY [v].[Name]"); } @@ -285,7 +293,9 @@ FROM [Vehicles] AS [v4] ) AS [t3] ON [v3].[Name] = [t3].[Name] ) AS [t2] ON [v2].[Name] = [t2].[Name] WHERE [v2].[Active] IS NOT NULL -) AS [t1] ON [t0].[Name] = [t1].[Name] +) AS [t1] ON [t0].[Name] = CASE + WHEN [t1].[Active] IS NOT NULL THEN [t1].[Name] +END WHERE [v].[Name] = N'AIM-9M Sidewinder' ORDER BY [v].[Name]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/TableSplittingSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/TableSplittingSqlServerTest.cs index 3df55f93984..d410d8eac78 100644 --- a/test/EFCore.SqlServer.FunctionalTests/TableSplittingSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/TableSplittingSqlServerTest.cs @@ -40,7 +40,9 @@ FROM [Vehicles] AS [v3] INNER JOIN [Vehicles] AS [v4] ON [v3].[Name] = [v4].[Name] ) AS [t1] ON [v2].[Name] = [t1].[Name] WHERE [v2].[Active] IS NOT NULL -) AS [t0] ON [t].[Name] = [t0].[Name] +) AS [t0] ON [t].[Name] = CASE + WHEN [t0].[Active] IS NOT NULL THEN [t0].[Name] +END LEFT JOIN ( SELECT [v5].[Name], [v5].[Computed], [v5].[Description], [v5].[Engine_Discriminator] FROM [Vehicles] AS [v5] @@ -50,7 +52,9 @@ FROM [Vehicles] AS [v6] WHERE [v6].[Discriminator] IN (N'PoweredVehicle', N'CompositeVehicle') ) AS [t3] ON [v5].[Name] = [t3].[Name] WHERE [v5].[Computed] IS NOT NULL AND [v5].[Engine_Discriminator] IS NOT NULL -) AS [t2] ON [v].[Name] = [t2].[Name] +) AS [t2] ON [v].[Name] = CASE + WHEN [t2].[Computed] IS NOT NULL AND [t2].[Engine_Discriminator] IS NOT NULL THEN [t2].[Name] +END LEFT JOIN ( SELECT [v7].[Name], [v7].[Capacity], [v7].[FuelTank_Discriminator], [v7].[FuelType], [v7].[GrainGeometry] FROM [Vehicles] AS [v7] @@ -74,7 +78,11 @@ WHERE [v11].[Discriminator] IN (N'PoweredVehicle', N'CompositeVehicle') WHERE [v10].[Engine_Discriminator] IN (N'ContinuousCombustionEngine', N'IntermittentCombustionEngine', N'SolidRocket') ) AS [t6] ON [v9].[Name] = [t6].[Name] WHERE [v9].[Capacity] IS NOT NULL AND [v9].[FuelTank_Discriminator] IS NOT NULL -) AS [t4] ON [t2].[Name] = [t4].[Name] +) AS [t4] ON CASE + WHEN [t2].[Computed] IS NOT NULL AND [t2].[Engine_Discriminator] IS NOT NULL THEN [t2].[Name] +END = CASE + WHEN [t4].[Capacity] IS NOT NULL AND [t4].[FuelTank_Discriminator] IS NOT NULL THEN [t4].[Name] +END ORDER BY [v].[Name]"); } @@ -264,7 +272,9 @@ FROM [Vehicles] AS [v3] INNER JOIN [Vehicles] AS [v4] ON [v3].[Name] = [v4].[Name] ) AS [t1] ON [v2].[Name] = [t1].[Name] WHERE [v2].[Active] IS NOT NULL -) AS [t0] ON [t].[Name] = [t0].[Name] +) AS [t0] ON [t].[Name] = CASE + WHEN [t0].[Active] IS NOT NULL THEN [t0].[Name] +END WHERE [v].[Name] = N'AIM-9M Sidewinder' ORDER BY [v].[Name]"); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs index e399e214b5c..c653c83267e 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQuerySqliteTest.cs @@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore.Query { - public class ComplexNavigationsCollectionsSharedTypeQuerySqliteTest : ComplexNavigationsCollectionsSharedQueryTypeRelationalTestBase< + public class ComplexNavigationsCollectionsSharedTypeQuerySqliteTest : ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase< ComplexNavigationsSharedTypeQuerySqliteFixture> { public ComplexNavigationsCollectionsSharedTypeQuerySqliteTest(ComplexNavigationsSharedTypeQuerySqliteFixture fixture, ITestOutputHelper testOutputHelper) diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs index e197c42d438..b8368fed206 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest.cs @@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore.Query { - public class ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest : ComplexNavigationsCollectionsSplitSharedQueryTypeRelationalTestBase< + public class ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest : ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase< ComplexNavigationsSharedTypeQuerySqliteFixture> { public ComplexNavigationsCollectionsSplitSharedTypeQuerySqliteTest(ComplexNavigationsSharedTypeQuerySqliteFixture fixture, ITestOutputHelper testOutputHelper) diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs index 5e977d32278..56c6b9a0459 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs @@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore.Query { - public class ComplexNavigationsSharedTypeQuerySqliteTest : ComplexNavigationsSharedQueryTypeRelationalTestBase< + public class ComplexNavigationsSharedTypeQuerySqliteTest : ComplexNavigationsSharedTypeQueryRelationalTestBase< ComplexNavigationsSharedTypeQuerySqliteFixture> { public ComplexNavigationsSharedTypeQuerySqliteTest(ComplexNavigationsSharedTypeQuerySqliteFixture fixture, ITestOutputHelper testOutputHelper) From eaa06fb0e7b2936163b343d7e0037b55ce121581 Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Fri, 10 Sep 2021 00:27:44 +0000 Subject: [PATCH 076/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions --- NuGet.config | 5 +- eng/Version.Details.xml | 236 ++++++++++++++++++++-------------------- eng/Versions.props | 14 +-- 3 files changed, 128 insertions(+), 127 deletions(-) diff --git a/NuGet.config b/NuGet.config index af2bce58f31..c381bb3b1a2 100644 --- a/NuGet.config +++ b/NuGet.config @@ -7,7 +7,7 @@ - + @@ -22,13 +22,14 @@ - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 10f5b0e01a9..09c6f2a6f92 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 @@ -122,145 +122,145 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 4d7b11a63b9f3611dc7aa8ba07157dd4fb4515c5 + c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup diff --git a/eng/Versions.props b/eng/Versions.props index f95fa52fc3e..d0fef5e758b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -32,13 +32,13 @@ 1.1.3 - 3.1.19 - 3.1.19 - 3.1.19 - 3.1.19 - 3.1.19 - 3.1.19-servicing.21417.2 - 3.1.19 + 3.1.20 + 3.1.20 + 3.1.20 + 3.1.20 + 3.1.20 + 3.1.20-servicing.21459.11 + 3.1.20 1.1.1 From 80cdabeb091f0994d8b0ca29e65ae7aaa434016b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 10 Sep 2021 01:24:56 +0000 Subject: [PATCH 077/346] Update dependencies from https://github.com/dotnet/runtime build 20210909.18 (#25961) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a1945dfc97a..1d49d55450a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 - + https://github.com/dotnet/runtime - 0933d9a1d3c09fdae125831bd165f983825f77c9 + 614c782790eceb2f4247e6e380db548a58b55a69 diff --git a/eng/Versions.props b/eng/Versions.props index 669fef8605c..8255e9ce8bd 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 - 6.0.0-rc.2.21459.10 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21459.18 3.7.0 From e1de57401fcf85534a7cf1924830300b8b468730 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Thu, 9 Sep 2021 22:05:11 -0700 Subject: [PATCH 078/346] Always sort deletes before inserts for the same table to avoid deadlocks. Fixes #14371 --- .../Update/Internal/CommandBatchPreparer.cs | 31 +- src/Shared/Multigraph.cs | 282 ++++++++++-------- .../Internal/MigrationsModelDifferTest.cs | 11 +- .../BatchingTest.cs | 67 +++++ test/EFCore.Tests/Utilities/MultigraphTest.cs | 4 +- 5 files changed, 257 insertions(+), 138 deletions(-) diff --git a/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs b/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs index a70dedb1688..07f1ec9ca97 100644 --- a/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs +++ b/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs @@ -287,7 +287,9 @@ protected virtual IReadOnlyList> TopologicalS AddUniqueValueEdges(modificationCommandGraph); - return modificationCommandGraph.BatchingTopologicalSort(FormatCycle); + AddSameTableEdges(modificationCommandGraph); + + return modificationCommandGraph.BatchingTopologicalSort(static (_, _, edges) => edges.All(e => e is IEntityType), FormatCycle); } private string FormatCycle(IReadOnlyList>> data) @@ -765,5 +767,32 @@ private void AddUniqueValueEdges(Multigraph modificationCommandGraph) + { + var deletedDictionary = new Dictionary<(string, string?), List>(); + + foreach (var command in modificationCommandGraph.Vertices) + { + if (command.EntityState == EntityState.Deleted) + { + deletedDictionary.GetOrAddNew((command.TableName, command.Schema)).Add(command); + } + } + + foreach (var command in modificationCommandGraph.Vertices) + { + if (command.EntityState == EntityState.Added) + { + if (deletedDictionary.TryGetValue((command.TableName, command.Schema), out var deletedList)) + { + foreach (var deleted in deletedList) + { + modificationCommandGraph.AddEdge(deleted, command, command.Entries[0].EntityType); + } + } + } + } + } } } diff --git a/src/Shared/Multigraph.cs b/src/Shared/Multigraph.cs index 93c69e95033..f3b6a0437bb 100644 --- a/src/Shared/Multigraph.cs +++ b/src/Shared/Multigraph.cs @@ -136,123 +136,123 @@ public IReadOnlyList TopologicalSort( Func>>, string>? formatCycle, Func? formatException = null) { - var sortedQueue = new List(); - var predecessorCounts = new Dictionary(); - - foreach (var vertex in _vertices) + var queue = new List(); + var predecessorCounts = new Dictionary(_predecessorMap.Count); + foreach (var predecessor in _predecessorMap) { - foreach (var outgoingNeighbor in GetOutgoingNeighbors(vertex)) - { - if (predecessorCounts.ContainsKey(outgoingNeighbor)) - { - predecessorCounts[outgoingNeighbor]++; - } - else - { - predecessorCounts[outgoingNeighbor] = 1; - } - } + predecessorCounts[predecessor.Key] = predecessor.Value.Count; } foreach (var vertex in _vertices) { if (!predecessorCounts.ContainsKey(vertex)) { - sortedQueue.Add(vertex); + queue.Add(vertex); } } var index = 0; - while (sortedQueue.Count < _vertices.Count) + while (queue.Count < _vertices.Count) { - while (index < sortedQueue.Count) + while (index < queue.Count) { - var currentRoot = sortedQueue[index]; + var currentRoot = queue[index]; + index++; - foreach (var successor in GetOutgoingNeighbors(currentRoot).Where(neighbor => predecessorCounts.ContainsKey(neighbor))) + foreach (var successor in GetOutgoingNeighbors(currentRoot)) { - // Decrement counts for edges from sorted vertices and append any vertices that no longer have predecessors predecessorCounts[successor]--; if (predecessorCounts[successor] == 0) { - sortedQueue.Add(successor); - predecessorCounts.Remove(successor); + queue.Add(successor); } } - - index++; } // Cycle breaking - if (sortedQueue.Count < _vertices.Count) + if (queue.Count < _vertices.Count) { var broken = false; var candidateVertices = predecessorCounts.Keys.ToList(); var candidateIndex = 0; - // Iterate over the unsorted vertices while ((candidateIndex < candidateVertices.Count) && !broken && tryBreakEdge != null) { var candidateVertex = candidateVertices[candidateIndex]; + if (predecessorCounts[candidateVertex] != 1) + { + candidateIndex++; + continue; + } - // Find vertices in the unsorted portion of the graph that have edges to the candidate - var incomingNeighbors = GetIncomingNeighbors(candidateVertex) - .Where(neighbor => predecessorCounts.ContainsKey(neighbor)).ToList(); + // Find a vertex in the unsorted portion of the graph that has edges to the candidate + var incomingNeighbor = GetIncomingNeighbors(candidateVertex) + .First(neighbor => predecessorCounts.TryGetValue(neighbor, out var neighborPredecessors) + && neighborPredecessors > 0); - foreach (var incomingNeighbor in incomingNeighbors) + if (tryBreakEdge(incomingNeighbor, candidateVertex, _successorMap[incomingNeighbor][candidateVertex])) { - // Check to see if the edge can be broken - if (tryBreakEdge(incomingNeighbor, candidateVertex, _successorMap[incomingNeighbor][candidateVertex])) - { - predecessorCounts[candidateVertex]--; - if (predecessorCounts[candidateVertex] == 0) - { - sortedQueue.Add(candidateVertex); - predecessorCounts.Remove(candidateVertex); - broken = true; - break; - } - } + _successorMap[incomingNeighbor].Remove(candidateVertex); + _predecessorMap[candidateVertex].Remove(incomingNeighbor); + predecessorCounts[candidateVertex]--; + queue.Add(candidateVertex); + broken = true; + break; } candidateIndex++; } - if (!broken) + if (broken) { - // Failed to break the cycle - var currentCycleVertex = _vertices.First(v => predecessorCounts.ContainsKey(v)); - var cycle = new List { currentCycleVertex }; - var finished = false; - while (!finished) + continue; + } + + var currentCycleVertex = _vertices.First( + v => predecessorCounts.TryGetValue(v, out var predecessorCount) && predecessorCount != 0); + var cycle = new List { currentCycleVertex }; + var finished = false; + while (!finished) + { + foreach (var predecessor in GetIncomingNeighbors(currentCycleVertex)) { - // Find a cycle - foreach (var predecessor in GetIncomingNeighbors(currentCycleVertex) - .Where(neighbor => predecessorCounts.ContainsKey(neighbor))) + if (!predecessorCounts.TryGetValue(predecessor, out var predecessorCount) + || predecessorCount == 0) { - if (predecessorCounts[predecessor] != 0) - { - predecessorCounts[currentCycleVertex] = -1; - - currentCycleVertex = predecessor; - cycle.Add(currentCycleVertex); - finished = predecessorCounts[predecessor] == -1; - break; - } + continue; } + + predecessorCounts[currentCycleVertex] = -1; + + currentCycleVertex = predecessor; + cycle.Add(currentCycleVertex); + finished = predecessorCounts[predecessor] == -1; + break; } + } + + cycle.Reverse(); - cycle.Reverse(); + // Remove any tail that's not part of the cycle + var startingVertex = cycle[0]; + for (var i = cycle.Count - 1; i >= 0; i--) + { + if (cycle[i].Equals(startingVertex)) + { + break; + } - ThrowCycle(cycle, formatCycle, formatException); + cycle.RemoveAt(i); } + + ThrowCycle(cycle, formatCycle, formatException); } } - return sortedQueue; + return queue; } private void ThrowCycle( @@ -287,27 +287,17 @@ private void ThrowCycle( => vertex.ToString(); public IReadOnlyList> BatchingTopologicalSort() - => BatchingTopologicalSort(null); + => BatchingTopologicalSort(null, null); public IReadOnlyList> BatchingTopologicalSort( + Func, bool>? tryBreakEdge, Func>>, string>? formatCycle) { var currentRootsQueue = new List(); - var predecessorCounts = new Dictionary(); - - foreach (var vertex in _vertices) + var predecessorCounts = new Dictionary(_predecessorMap.Count); + foreach (var predecessor in _predecessorMap) { - foreach (var outgoingNeighbor in GetOutgoingNeighbors(vertex)) - { - if (predecessorCounts.ContainsKey(outgoingNeighbor)) - { - predecessorCounts[outgoingNeighbor]++; - } - else - { - predecessorCounts[outgoingNeighbor] = 1; - } - } + predecessorCounts[predecessor.Key] = predecessor.Value.Count; } foreach (var vertex in _vertices) @@ -320,85 +310,121 @@ public IReadOnlyList> BatchingTopologicalSort( var result = new List>(); var nextRootsQueue = new List(); - var currentRootIndex = 0; - while (currentRootIndex < currentRootsQueue.Count) + while (result.Sum(b => b.Count) != _vertices.Count) { - var currentRoot = currentRootsQueue[currentRootIndex]; - currentRootIndex++; - - // Remove edges from current root and add any exposed vertices to the next batch - foreach (var successor in GetOutgoingNeighbors(currentRoot)) + var currentRootIndex = 0; + while (currentRootIndex < currentRootsQueue.Count) { - predecessorCounts[successor]--; - if (predecessorCounts[successor] == 0) + var currentRoot = currentRootsQueue[currentRootIndex]; + currentRootIndex++; + + foreach (var successor in GetOutgoingNeighbors(currentRoot)) { - nextRootsQueue.Add(successor); + predecessorCounts[successor]--; + if (predecessorCounts[successor] == 0) + { + nextRootsQueue.Add(successor); + } } - } - // Roll lists over for next batch - if (currentRootIndex == currentRootsQueue.Count) - { - result.Add(currentRootsQueue); + // Roll lists over for next batch + if (currentRootIndex == currentRootsQueue.Count) + { + result.Add(currentRootsQueue); - currentRootsQueue = nextRootsQueue; - currentRootIndex = 0; + currentRootsQueue = nextRootsQueue; + currentRootIndex = 0; - if (currentRootsQueue.Count != 0) - { - nextRootsQueue = new List(); + if (currentRootsQueue.Count != 0) + { + nextRootsQueue = new List(); + } } } - } - if (result.Sum(b => b.Count) != _vertices.Count) - { - var currentCycleVertex = _vertices.First( - v => predecessorCounts.TryGetValue(v, out var predecessorNumber) && predecessorNumber != 0); - var cyclicWalk = new List { currentCycleVertex }; - var finished = false; - while (!finished) + // Cycle breaking + if (result.Sum(b => b.Count) != _vertices.Count) { - foreach (var predecessor in GetIncomingNeighbors(currentCycleVertex)) + var broken = false; + + var candidateVertices = predecessorCounts.Keys.ToList(); + var candidateIndex = 0; + + while ((candidateIndex < candidateVertices.Count) + && !broken + && tryBreakEdge != null) { - if (!predecessorCounts.TryGetValue(predecessor, out var predecessorCount)) + var candidateVertex = candidateVertices[candidateIndex]; + if (predecessorCounts[candidateVertex] != 1) { + candidateIndex++; continue; } - if (predecessorCount != 0) + // Find a vertex in the unsorted portion of the graph that has edges to the candidate + var incomingNeighbor = GetIncomingNeighbors(candidateVertex) + .First(neighbor => predecessorCounts.TryGetValue(neighbor, out var neighborPredecessors) + && neighborPredecessors > 0); + + if (tryBreakEdge(incomingNeighbor, candidateVertex, _successorMap[incomingNeighbor][candidateVertex])) + { + _successorMap[incomingNeighbor].Remove(candidateVertex); + _predecessorMap[candidateVertex].Remove(incomingNeighbor); + predecessorCounts[candidateVertex]--; + currentRootsQueue.Add(candidateVertex); + nextRootsQueue = new List(); + broken = true; + break; + } + + candidateIndex++; + } + + if (broken) + { + continue; + } + + var currentCycleVertex = _vertices.First( + v => predecessorCounts.TryGetValue(v, out var predecessorCount) && predecessorCount != 0); + var cycle = new List { currentCycleVertex }; + var finished = false; + while (!finished) + { + foreach (var predecessor in GetIncomingNeighbors(currentCycleVertex)) { + if (!predecessorCounts.TryGetValue(predecessor, out var predecessorCount) + || predecessorCount == 0) + { + continue; + } + predecessorCounts[currentCycleVertex] = -1; currentCycleVertex = predecessor; - cyclicWalk.Add(currentCycleVertex); + cycle.Add(currentCycleVertex); finished = predecessorCounts[predecessor] == -1; break; } } - } - cyclicWalk.Reverse(); + cycle.Reverse(); - var cycle = new List(); - var startingVertex = cyclicWalk.First(); - cycle.Add(startingVertex); - foreach (var vertex in cyclicWalk.Skip(1)) - { - if (!vertex.Equals(startingVertex)) - { - cycle.Add(vertex); - } - else + // Remove any tail that's not part of the cycle + var startingVertex = cycle[0]; + for (var i = cycle.Count - 1; i >= 0; i--) { - break; - } - } + if (cycle[i].Equals(startingVertex)) + { + break; + } - cycle.Add(startingVertex); + cycle.RemoveAt(i); + } - ThrowCycle(cycle, formatCycle); + ThrowCycle(cycle, formatCycle); + } } return result; diff --git a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs index 69c96bd73e2..45aec7aaa3b 100644 --- a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs +++ b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs @@ -333,13 +333,10 @@ public void Model_differ_breaks_double_foreign_key_cycles_in_create_table_operat }, result => { - Assert.Equal(14, result.Count); - - var createBankTableOperation = Assert.IsType(result[0]); - Assert.Equal("Banks", createBankTableOperation.Name); - Assert.Empty(createBankTableOperation.ForeignKeys); - - Assert.Equal(4, result.OfType().Count()); + Assert.Equal(3, result.OfType().Count()); + Assert.Equal(7, result.OfType().Count()); + Assert.Equal(7, result.OfType().SelectMany(t => t.ForeignKeys).Count() + + result.OfType().Count()); }); } diff --git a/test/EFCore.SqlServer.FunctionalTests/BatchingTest.cs b/test/EFCore.SqlServer.FunctionalTests/BatchingTest.cs index 4fa323a94c0..889e056dc92 100644 --- a/test/EFCore.SqlServer.FunctionalTests/BatchingTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/BatchingTest.cs @@ -169,6 +169,73 @@ public void Insertion_order_is_preserved(int maxBatchSize) }); } + [ConditionalFact] + public void Deadlock_on_inserts_and_deletes_with_dependents_is_handled_correctly() + { + var blogs = new List(); + + using (var context = CreateContext()) + { + var owner1 = new Owner { Name = "0" }; + var owner2 = new Owner { Name = "1" }; + context.Owners.Add(owner1); + context.Owners.Add(owner2); + + blogs.Add(new Blog + { + Id = Guid.NewGuid(), + Owner = owner1, + Order = 1 + }); + blogs.Add(new Blog + { + Id = Guid.NewGuid(), + Owner = owner2, + Order = 2 + }); + blogs.Add(new Blog + { + Id = Guid.NewGuid(), + Owner = owner1, + Order = 3 + }); + blogs.Add(new Blog + { + Id = Guid.NewGuid(), + Owner = owner2, + Order = 4 + }); + + context.AddRange(blogs); + + context.SaveChanges(); + } + + for (var i = 0; i < 10; i++) + { + Parallel.ForEach(blogs, blog => + { + RemoveAndAddPosts(blog); + }); + } + + void RemoveAndAddPosts(Blog blog) + { + using var context = (BloggingContext)Fixture.CreateContext(useConnectionString: true); + + context.Attach(blog); + blog.Posts.Clear(); + + blog.Posts.Add(new Post { Comments = { new Comment() } }); + blog.Posts.Add(new Post { Comments = { new Comment() } }); + blog.Posts.Add(new Post { Comments = { new Comment() } }); + + context.SaveChanges(); + } + + Fixture.Reseed(); + } + [ConditionalFact] public void Deadlock_on_deletes_with_dependents_is_handled_correctly() { diff --git a/test/EFCore.Tests/Utilities/MultigraphTest.cs b/test/EFCore.Tests/Utilities/MultigraphTest.cs index 1ed04245ed3..3310ab14ffe 100644 --- a/test/EFCore.Tests/Utilities/MultigraphTest.cs +++ b/test/EFCore.Tests/Utilities/MultigraphTest.cs @@ -434,7 +434,7 @@ string formatter(IEnumerable>> data) Assert.Equal( CoreStrings.CircularDependency(message), - Assert.Throws(() => graph.BatchingTopologicalSort(formatter)).Message); + Assert.Throws(() => graph.BatchingTopologicalSort(null, formatter)).Message); Assert.Equal(3, cycleData.Count()); @@ -485,7 +485,7 @@ string formatter(IEnumerable>> data) Assert.Equal( CoreStrings.CircularDependency(message), - Assert.Throws(() => graph.BatchingTopologicalSort(formatter)).Message); + Assert.Throws(() => graph.BatchingTopologicalSort(null, formatter)).Message); Assert.Equal(2, cycleData.Count); From 65bc52812872b0aed9324c8094e11c2fca4b38cd Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Thu, 9 Sep 2021 22:06:31 -0700 Subject: [PATCH 079/346] Make sure navigations on property bag entity types don't use CLR properties. Make GetIdentifyingMemberInfo() return null for indexer properties since it doesn't uniquely identify them Replaced some usages of GetIdentifyingMemberInfo() with more appropriate code. Fixes #25501 Fixes #25459 --- .../Internal/SnapshotFactoryFactory.cs | 2 +- src/EFCore/Metadata/IReadOnlyNavigation.cs | 19 +---- .../Metadata/IReadOnlyNavigationBase.cs | 4 ++ src/EFCore/Metadata/IReadOnlyPropertyBase.cs | 5 +- .../Metadata/IReadOnlySkipNavigation.cs | 19 +---- .../Internal/ClrCollectionAccessorFactory.cs | 4 +- src/EFCore/Metadata/Internal/EntityType.cs | 61 +++++++++++----- .../Metadata/Internal/EntityTypeExtensions.cs | 18 +++-- src/EFCore/Metadata/Internal/ForeignKey.cs | 44 +++++++----- .../Internal/InternalEntityTypeBuilder.cs | 18 +++-- .../Internal/InternalForeignKeyBuilder.cs | 25 ++----- .../Internal/InternalPropertyBuilder.cs | 10 +-- src/EFCore/Metadata/Internal/Navigation.cs | 7 +- .../Metadata/Internal/NavigationExtensions.cs | 9 ++- .../Internal/PropertyBaseExtensions.cs | 7 +- .../Metadata/Internal/SkipNavigation.cs | 5 +- .../Internal/SkipNavigationExtensions.cs | 9 ++- .../Migrations/ModelSnapshotSqlServerTest.cs | 2 + .../ClrCollectionAccessorFactoryTest.cs | 71 ++----------------- .../Internal/InternalEntityTypeBuilderTest.cs | 31 ++++++++ .../ModelBuilding/NonRelationshipTestBase.cs | 3 +- test/EFCore.Tests/ModelBuilding/TestModel.cs | 6 ++ 22 files changed, 190 insertions(+), 189 deletions(-) diff --git a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs index f133466dac9..aca7852abfe 100644 --- a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs @@ -228,7 +228,7 @@ protected virtual Expression CreateReadShadowValueExpression( IPropertyBase property) => Expression.Call( parameter, - InternalEntityEntry.ReadShadowValueMethod.MakeGenericMethod(property.ClrType), + InternalEntityEntry.ReadShadowValueMethod.MakeGenericMethod((property as IProperty)?.ClrType ?? typeof(object)), Expression.Constant(property.GetShadowIndex())); /// diff --git a/src/EFCore/Metadata/IReadOnlyNavigation.cs b/src/EFCore/Metadata/IReadOnlyNavigation.cs index bc3136096b1..4062f99de35 100644 --- a/src/EFCore/Metadata/IReadOnlyNavigation.cs +++ b/src/EFCore/Metadata/IReadOnlyNavigation.cs @@ -144,24 +144,7 @@ string ToDebugString(MetadataDebugStringOptions options = MetadataDebugStringOpt builder.Append(" ("); } - if (this.GetIdentifyingMemberInfo() == null) - { - // Shadow navigation - if (IsCollection) - { - builder.Append("IEnumerable<"); - } - builder.Append(TargetEntityType.ClrType.ShortDisplayName()); - if (IsCollection) - { - builder.Append(">"); - } - builder.Append(")"); - } - else - { - builder.Append(ClrType.ShortDisplayName()).Append(")"); - } + builder.Append(ClrType.ShortDisplayName()).Append(")"); if (IsCollection) { diff --git a/src/EFCore/Metadata/IReadOnlyNavigationBase.cs b/src/EFCore/Metadata/IReadOnlyNavigationBase.cs index c93804aa668..e752b37f71d 100644 --- a/src/EFCore/Metadata/IReadOnlyNavigationBase.cs +++ b/src/EFCore/Metadata/IReadOnlyNavigationBase.cs @@ -38,5 +38,9 @@ public interface IReadOnlyNavigationBase : IReadOnlyPropertyBase /// bool IsEagerLoaded => (bool?)this[CoreAnnotationNames.EagerLoaded] ?? false; + + /// + // TODO: Remove when #3864 is implemented + bool IReadOnlyPropertyBase.IsShadowProperty() => this.GetIdentifyingMemberInfo() == null; } } diff --git a/src/EFCore/Metadata/IReadOnlyPropertyBase.cs b/src/EFCore/Metadata/IReadOnlyPropertyBase.cs index 741b33d24c2..c0b70c75e1d 100644 --- a/src/EFCore/Metadata/IReadOnlyPropertyBase.cs +++ b/src/EFCore/Metadata/IReadOnlyPropertyBase.cs @@ -5,7 +5,6 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata { @@ -60,7 +59,7 @@ public interface IReadOnlyPropertyBase : IReadOnlyAnnotatable /// /// if the property is a shadow property, otherwise . /// - bool IsShadowProperty() => this.GetIdentifyingMemberInfo() == null; + bool IsShadowProperty() => PropertyInfo == null && FieldInfo == null; /// /// Gets a value indicating whether this is an indexer property. An indexer property is one that is accessed through @@ -70,7 +69,7 @@ public interface IReadOnlyPropertyBase : IReadOnlyAnnotatable /// if the property is an indexer property, otherwise . /// bool IsIndexerProperty() - => this.GetIdentifyingMemberInfo() is PropertyInfo propertyInfo + => PropertyInfo is PropertyInfo propertyInfo && propertyInfo == DeclaringType.FindIndexerPropertyInfo(); /// diff --git a/src/EFCore/Metadata/IReadOnlySkipNavigation.cs b/src/EFCore/Metadata/IReadOnlySkipNavigation.cs index d57a6c84442..3f35f58abfb 100644 --- a/src/EFCore/Metadata/IReadOnlySkipNavigation.cs +++ b/src/EFCore/Metadata/IReadOnlySkipNavigation.cs @@ -89,24 +89,7 @@ string ToDebugString(MetadataDebugStringOptions options = MetadataDebugStringOpt builder.Append(" ("); } - if (this.GetIdentifyingMemberInfo() == null) - { - // Shadow navigation - if (IsCollection) - { - builder.Append("IEnumerable<"); - } - builder.Append(TargetEntityType.ClrType.ShortDisplayName()); - if (IsCollection) - { - builder.Append(">"); - } - builder.Append(")"); - } - else - { - builder.Append(ClrType.ShortDisplayName()).Append(")"); - } + builder.Append(ClrType.ShortDisplayName()).Append(")"); if (IsCollection) { diff --git a/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs b/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs index 8c2d90aec6c..a0c9021c914 100644 --- a/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs +++ b/src/EFCore/Metadata/Internal/ClrCollectionAccessorFactory.cs @@ -65,7 +65,7 @@ private static readonly MethodInfo _createObservableHashSet } var memberInfo = GetMostDerivedMemberInfo(); - var propertyType = memberInfo.GetMemberType(); + var propertyType = navigation.IsIndexerProperty() ? navigation.ClrType : memberInfo.GetMemberType(); var elementType = propertyType.TryGetElementType(typeof(IEnumerable<>)); if (elementType == null) @@ -110,7 +110,7 @@ MemberInfo GetMostDerivedMemberInfo() : propertyInfo == null ? fieldInfo : fieldInfo.FieldType.IsAssignableFrom(propertyInfo.PropertyType) - ? (MemberInfo)propertyInfo + ? propertyInfo : fieldInfo; } } diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs index c07a89021a8..34b8bac7f6a 100644 --- a/src/EFCore/Metadata/Internal/EntityType.cs +++ b/src/EFCore/Metadata/Internal/EntityType.cs @@ -13,6 +13,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Utilities; @@ -1460,7 +1461,13 @@ public virtual Navigation AddNavigation( return AddNavigation(new MemberIdentity(navigationMember), foreignKey, pointsToPrincipal); } - private Navigation AddNavigation(MemberIdentity navigationMember, ForeignKey foreignKey, bool pointsToPrincipal) + /// + /// 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 Navigation AddNavigation(MemberIdentity navigationMember, ForeignKey foreignKey, bool pointsToPrincipal) { EnsureMutable(); @@ -1504,7 +1511,7 @@ private Navigation AddNavigation(MemberIdentity navigationMember, ForeignKey for { ValidateClrMember(name, memberInfo); } - else + else if (!IsPropertyBag) { memberInfo = ClrType.GetMembersInHierarchy(name).FirstOrDefault(); } @@ -1519,6 +1526,10 @@ private Navigation AddNavigation(MemberIdentity navigationMember, ForeignKey for !pointsToPrincipal && !foreignKey.IsUnique, shouldThrow: true); } + else if (IsPropertyBag) + { + memberInfo = FindIndexerPropertyInfo()!; + } var navigation = new Navigation(name, memberInfo as PropertyInfo, memberInfo as FieldInfo, foreignKey); @@ -1665,7 +1676,7 @@ public virtual IEnumerable GetNavigations() { ValidateClrMember(name, memberInfo); } - else + else if (!IsPropertyBag) { memberInfo = ClrType.GetMembersInHierarchy(name).FirstOrDefault(); } @@ -1680,6 +1691,10 @@ public virtual IEnumerable GetNavigations() collection, shouldThrow: true); } + else if (IsPropertyBag) + { + memberInfo = FindIndexerPropertyInfo()!; + } var skipNavigation = new SkipNavigation( name, @@ -1725,7 +1740,9 @@ public virtual IEnumerable GetNavigations() return memberInfo.GetMemberType(); } - var clashingMemberInfo = ClrType.GetMembersInHierarchy(name).FirstOrDefault(); + var clashingMemberInfo = IsPropertyBag + ? null + : ClrType.GetMembersInHierarchy(name).FirstOrDefault(); if (clashingMemberInfo != null) { throw new InvalidOperationException( @@ -2301,7 +2318,7 @@ public virtual IEnumerable GetIndexes() return AddProperty( name, propertyType, - ClrType.GetMembersInHierarchy(name).FirstOrDefault(), + null, typeConfigurationSource, configurationSource); } @@ -2332,10 +2349,18 @@ public virtual IEnumerable GetIndexes() string name, ConfigurationSource configurationSource) { - var clrMember = ClrType.GetMembersInHierarchy(name).FirstOrDefault(); - if (clrMember == null) + MemberInfo? clrMember; + if (IsPropertyBag) + { + clrMember = FindIndexerPropertyInfo()!; + } + else { - throw new InvalidOperationException(CoreStrings.NoPropertyType(name, DisplayName())); + clrMember = ClrType.GetMembersInHierarchy(name).FirstOrDefault(); + if (clrMember == null) + { + throw new InvalidOperationException(CoreStrings.NoPropertyType(name, DisplayName())); + } } return AddProperty(clrMember, configurationSource); @@ -2386,9 +2411,7 @@ public virtual IEnumerable GetIndexes() } else { - Check.DebugAssert( - ClrType.GetMembersInHierarchy(name).FirstOrDefault() == null, - "MemberInfo not supplied for non-shadow property"); + memberInfo = ClrType.GetMembersInHierarchy(name).FirstOrDefault(); } if (memberInfo != null @@ -3013,7 +3036,7 @@ public virtual IEnumerable GetDerivedServiceProperties() var data = new List>(); var valueConverters = new Dictionary(StringComparer.Ordinal); var properties = GetProperties() - .Concat(GetNavigations()) + .Concat(GetNavigations()) .Concat(GetSkipNavigations()) .ToDictionary(p => p.Name); foreach (var rawSeed in _data) @@ -3029,15 +3052,17 @@ public virtual IEnumerable GetDerivedServiceProperties() { ValueConverter? valueConverter = null; if (providerValues - && propertyBase is IReadOnlyProperty property + && propertyBase is IProperty property && !valueConverters.TryGetValue(propertyBase.Name, out valueConverter)) { valueConverter = property.GetTypeMapping().Converter; valueConverters[propertyBase.Name] = valueConverter; } + propertyBase.TryGetMemberInfo(forConstruction: false, forSet: false, out var memberInfo, out _); + object? value = null; - switch (propertyBase.GetIdentifyingMemberInfo()) + switch (memberInfo) { case PropertyInfo propertyInfo: if (propertyBase.IsIndexerProperty()) @@ -4828,7 +4853,7 @@ IMutableProperty IMutableEntityType.AddProperty(string name, Type propertyType) propertyType, setTypeConfigurationSource ? fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention - : (ConfigurationSource?)null, + : null, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// @@ -4840,7 +4865,7 @@ IMutableProperty IMutableEntityType.AddProperty(string name, Type propertyType) [DebuggerStepThrough] IMutableProperty IMutableEntityType.AddProperty(string name, Type propertyType, MemberInfo? memberInfo) => AddProperty( - name, propertyType, memberInfo ?? ClrType.GetMembersInHierarchy(name).FirstOrDefault(), + name, propertyType, memberInfo, ConfigurationSource.Explicit, ConfigurationSource.Explicit)!; /// @@ -4859,10 +4884,10 @@ IMutableProperty IMutableEntityType.AddProperty(string name, Type propertyType, => AddProperty( name, propertyType, - memberInfo ?? ClrType.GetMembersInHierarchy(name).FirstOrDefault(), + memberInfo, setTypeConfigurationSource ? fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention - : (ConfigurationSource?)null, + : null, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention); /// diff --git a/src/EFCore/Metadata/Internal/EntityTypeExtensions.cs b/src/EFCore/Metadata/Internal/EntityTypeExtensions.cs index dd82e94ddad..fa9ad69e842 100644 --- a/src/EFCore/Metadata/Internal/EntityTypeExtensions.cs +++ b/src/EFCore/Metadata/Internal/EntityTypeExtensions.cs @@ -51,12 +51,20 @@ public static MemberInfo GetNavigationMemberInfo( this IReadOnlyEntityType entityType, string navigationName) { - var memberInfo = entityType.ClrType.GetMembersInHierarchy(navigationName).FirstOrDefault(); - - if (memberInfo == null) + MemberInfo? memberInfo; + if (entityType.IsPropertyBag) { - throw new InvalidOperationException( - CoreStrings.NoClrNavigation(navigationName, entityType.DisplayName())); + memberInfo = entityType.FindIndexerPropertyInfo()!; + } + else + { + memberInfo = entityType.ClrType.GetMembersInHierarchy(navigationName).FirstOrDefault(); + + if (memberInfo == null) + { + throw new InvalidOperationException( + CoreStrings.NoClrNavigation(navigationName, entityType.DisplayName())); + } } return memberInfo; diff --git a/src/EFCore/Metadata/Internal/ForeignKey.cs b/src/EFCore/Metadata/Internal/ForeignKey.cs index f83120adcee..46c5b5f3fe1 100644 --- a/src/EFCore/Metadata/Internal/ForeignKey.cs +++ b/src/EFCore/Metadata/Internal/ForeignKey.cs @@ -357,6 +357,17 @@ public virtual void UpdatePrincipalEndConfigurationSource(ConfigurationSource co ConfigurationSource configurationSource) => Navigation(MemberIdentity.Create(property), configurationSource, pointsToPrincipal: 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 Navigation? SetDependentToPrincipal( + MemberIdentity? property, + ConfigurationSource configurationSource) + => Navigation(property, configurationSource, pointsToPrincipal: 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 @@ -402,6 +413,15 @@ public virtual void UpdateDependentToPrincipalConfigurationSource(ConfigurationS public virtual Navigation? SetPrincipalToDependent(MemberInfo? property, ConfigurationSource configurationSource) => Navigation(MemberIdentity.Create(property), configurationSource, pointsToPrincipal: 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. + /// + public virtual Navigation? SetPrincipalToDependent(MemberIdentity? property, ConfigurationSource configurationSource) + => Navigation(property, configurationSource, pointsToPrincipal: 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 @@ -497,18 +517,11 @@ public virtual void UpdatePrincipalToDependentConfigurationSource(ConfigurationS } Navigation? navigation = null; - var property = propertyIdentity?.MemberInfo; - if (property != null) - { - navigation = pointsToPrincipal - ? DeclaringEntityType.AddNavigation(property, this, pointsToPrincipal: true) - : PrincipalEntityType.AddNavigation(property, this, pointsToPrincipal: false); - } - else if (name != null) + if (propertyIdentity?.Name != null) { navigation = pointsToPrincipal - ? DeclaringEntityType.AddNavigation(name, this, pointsToPrincipal: true) - : PrincipalEntityType.AddNavigation(name, this, pointsToPrincipal: false); + ? DeclaringEntityType.AddNavigation(propertyIdentity.Value, this, pointsToPrincipal: true) + : PrincipalEntityType.AddNavigation(propertyIdentity.Value, this, pointsToPrincipal: false); } if (pointsToPrincipal) @@ -595,14 +608,13 @@ public virtual bool IsUnique CoreStrings.NonUniqueRequiredDependentForeignKey(Properties.Format(), DeclaringEntityType.DisplayName())); } + var navigationMember = PrincipalToDependent?.GetIdentifyingMemberInfo(); if (unique.HasValue - && PrincipalEntityType.ClrType != Model.DefaultPropertyBagType - && DeclaringEntityType.ClrType != Model.DefaultPropertyBagType - && PrincipalToDependent != null) + && navigationMember != null) { if (!Internal.Navigation.IsCompatible( - PrincipalToDependent.Name, - PrincipalToDependent.GetIdentifyingMemberInfo()!, + PrincipalToDependent!.Name, + navigationMember, PrincipalEntityType, DeclaringEntityType, !unique, @@ -618,7 +630,7 @@ public virtual bool IsUnique _isUniqueConfigurationSource = unique == null ? null - : (ConfigurationSource?)configurationSource.Max(_isUniqueConfigurationSource); + : configurationSource.Max(_isUniqueConfigurationSource); return IsUnique != oldUnique ? DeclaringEntityType.Model.ConventionDispatcher.OnForeignKeyUniquenessChanged(Builder) diff --git a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs index 48907e1e106..a1220fdc53a 100644 --- a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs @@ -553,7 +553,7 @@ public virtual bool CanRemoveKey(ConfigurationSource configurationSource) return null; } - memberInfo ??= existingProperty.GetIdentifyingMemberInfo(); + memberInfo ??= existingProperty.PropertyInfo ?? (MemberInfo?)existingProperty.FieldInfo; } else if (!configurationSource.Overrides(existingProperty.GetConfigurationSource())) { @@ -727,7 +727,7 @@ private bool IsCompatible(MemberInfo? newMemberInfo, Property existingProperty) var existingMemberInfo = existingProperty.GetIdentifyingMemberInfo(); if (existingMemberInfo == null) { - return false; + return newMemberInfo == existingProperty.DeclaringType.FindIndexerPropertyInfo(); } if (newMemberInfo == existingMemberInfo) @@ -4181,7 +4181,9 @@ private bool Contains(IReadOnlyForeignKey? inheritedFk, IReadOnlyForeignKey deri if (existingNavigation != null) { Check.DebugAssert( - memberInfo == null || memberInfo.IsSameAs(existingNavigation.GetIdentifyingMemberInfo()), + memberInfo == null + || existingNavigation.IsIndexerProperty() + || memberInfo.IsSameAs(existingNavigation.GetIdentifyingMemberInfo()), "Expected memberInfo to be the same on the existing navigation"); Check.DebugAssert( @@ -4230,9 +4232,9 @@ private bool Contains(IReadOnlyForeignKey? inheritedFk, IReadOnlyForeignKey deri } if (collection == null - && navigationProperty.MemberInfo != null) + && memberInfo != null) { - var navigationType = navigationProperty.MemberInfo.GetMemberType(); + var navigationType = memberInfo.GetMemberType(); var navigationTargetClrType = navigationType.TryGetSequenceType(); collection = navigationTargetClrType != null && navigationType != targetEntityType.ClrType @@ -4294,7 +4296,7 @@ private bool Contains(IReadOnlyForeignKey? inheritedFk, IReadOnlyForeignKey deri } builder = Metadata.AddSkipNavigation( - navigationName, navigationProperty.MemberInfo, + navigationName, memberInfo, targetEntityType, collection ?? true, onDependent ?? false, configurationSource.Value)!.Builder; if (detachedNavigations != null) @@ -4994,7 +4996,9 @@ private bool CanAddDiscriminatorProperty( return false; } - var memberInfo = Metadata.ClrType.GetMembersInHierarchy(name).FirstOrDefault(); + var memberInfo = Metadata.IsPropertyBag + ? null + : Metadata.ClrType.GetMembersInHierarchy(name).FirstOrDefault(); if (memberInfo != null && propertyType != memberInfo.GetMemberType() && typeConfigurationSource != null) diff --git a/src/EFCore/Metadata/Internal/InternalForeignKeyBuilder.cs b/src/EFCore/Metadata/Internal/InternalForeignKeyBuilder.cs index 82428395b83..d4d409d435a 100644 --- a/src/EFCore/Metadata/Internal/InternalForeignKeyBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalForeignKeyBuilder.cs @@ -410,14 +410,7 @@ public InternalForeignKeyBuilder( } } - if (navigationProperty != null) - { - Metadata.SetDependentToPrincipal(navigationProperty, configurationSource); - } - else - { - Metadata.SetDependentToPrincipal(navigationToPrincipalName, configurationSource); - } + Metadata.SetDependentToPrincipal(navigationToPrincipal, configurationSource); } if (navigationToDependent != null) @@ -438,14 +431,7 @@ public InternalForeignKeyBuilder( } } - if (navigationProperty != null) - { - Metadata.SetPrincipalToDependent(navigationProperty, configurationSource); - } - else - { - Metadata.SetPrincipalToDependent(navigationToDependentName, configurationSource); - } + Metadata.SetPrincipalToDependent(navigationToDependent, configurationSource); } builder = batch.Run(builder); @@ -1362,10 +1348,11 @@ private bool CanSetIsUnique(bool? unique, ConfigurationSource? configurationSour return false; } - if (Metadata.PrincipalToDependent?.IsShadowProperty() == false + var navigationMember = Metadata.PrincipalToDependent?.GetIdentifyingMemberInfo(); + if (navigationMember != null && !Navigation.IsCompatible( - Metadata.PrincipalToDependent.Name, - Metadata.PrincipalToDependent.GetIdentifyingMemberInfo()!, + Metadata.PrincipalToDependent!.Name, + navigationMember, Metadata.PrincipalEntityType, Metadata.DeclaringEntityType, !unique, diff --git a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs index a589d912986..2eb9e420786 100644 --- a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs @@ -703,11 +703,11 @@ public virtual bool CanSetKeyValueComparer(ValueComparer? comparer, Configuratio { var identifyingMemberInfo = Metadata.GetIdentifyingMemberInfo(); - newPropertyBuilder = identifyingMemberInfo == null - ? entityTypeBuilder.Property( - Metadata.ClrType, Metadata.Name, Metadata.GetTypeConfigurationSource(), configurationSource) - : (identifyingMemberInfo as PropertyInfo)?.IsIndexerProperty() == true - ? entityTypeBuilder.IndexerProperty(Metadata.ClrType, Metadata.Name, configurationSource) + newPropertyBuilder = Metadata.IsIndexerProperty() + ? entityTypeBuilder.IndexerProperty(Metadata.ClrType, Metadata.Name, configurationSource) + : identifyingMemberInfo == null + ? entityTypeBuilder.Property( + Metadata.ClrType, Metadata.Name, Metadata.GetTypeConfigurationSource(), configurationSource) : entityTypeBuilder.Property(identifyingMemberInfo, configurationSource!); if (newPropertyBuilder is null) diff --git a/src/EFCore/Metadata/Internal/Navigation.cs b/src/EFCore/Metadata/Internal/Navigation.cs index e1725086333..cfab1ba12da 100644 --- a/src/EFCore/Metadata/Internal/Navigation.cs +++ b/src/EFCore/Metadata/Internal/Navigation.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -42,7 +43,6 @@ public Navigation( Check.NotNull(foreignKey, nameof(foreignKey)); ForeignKey = foreignKey; - ClrType = this.GetIdentifyingMemberInfo()?.GetMemberType() ?? typeof(object); _builder = new InternalNavigationBuilder(this, foreignKey.DeclaringEntityType.Model.Builder); } @@ -53,7 +53,10 @@ public Navigation( /// 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 Type ClrType { get; } + public override Type ClrType => this.GetIdentifyingMemberInfo()?.GetMemberType() + ?? (((IReadOnlyNavigation)this).IsCollection + ? typeof(IEnumerable<>).MakeGenericType(TargetEntityType.ClrType) + : TargetEntityType.ClrType); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Metadata/Internal/NavigationExtensions.cs b/src/EFCore/Metadata/Internal/NavigationExtensions.cs index 54f6055b0f3..650df30bfae 100644 --- a/src/EFCore/Metadata/Internal/NavigationExtensions.cs +++ b/src/EFCore/Metadata/Internal/NavigationExtensions.cs @@ -18,8 +18,11 @@ public static class NavigationExtensions /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public static MemberIdentity CreateMemberIdentity(this IReadOnlyNavigation? navigation) - => navigation?.GetIdentifyingMemberInfo() == null - ? MemberIdentity.Create(navigation?.Name) - : MemberIdentity.Create(navigation.GetIdentifyingMemberInfo()); + { + var memberInfo = navigation?.GetIdentifyingMemberInfo(); + return memberInfo == null + ? MemberIdentity.Create(navigation?.Name) + : MemberIdentity.Create(memberInfo); + } } } diff --git a/src/EFCore/Metadata/Internal/PropertyBaseExtensions.cs b/src/EFCore/Metadata/Internal/PropertyBaseExtensions.cs index 0ad3daa8343..fd6da1bbdc9 100644 --- a/src/EFCore/Metadata/Internal/PropertyBaseExtensions.cs +++ b/src/EFCore/Metadata/Internal/PropertyBaseExtensions.cs @@ -98,7 +98,12 @@ public static bool IsIndexerProperty(this PropertyBase propertyBase) // GetMemberInfo to get the property/field to use, which may be different. public static MemberInfo? GetIdentifyingMemberInfo( this IReadOnlyPropertyBase propertyBase) - => propertyBase.PropertyInfo ?? (MemberInfo?)propertyBase.FieldInfo; + { + var indexerPropertyInfo = propertyBase.DeclaringType.FindIndexerPropertyInfo(); + return indexerPropertyInfo != null && propertyBase.PropertyInfo == indexerPropertyInfo + ? null + : (propertyBase.PropertyInfo ?? (MemberInfo?)propertyBase.FieldInfo); + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Metadata/Internal/SkipNavigation.cs b/src/EFCore/Metadata/Internal/SkipNavigation.cs index c8ecfa10036..4b5bbe41fcc 100644 --- a/src/EFCore/Metadata/Internal/SkipNavigation.cs +++ b/src/EFCore/Metadata/Internal/SkipNavigation.cs @@ -78,7 +78,10 @@ private void ProcessForeignKey(ForeignKey foreignKey) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override Type ClrType - => this.GetIdentifyingMemberInfo()!.GetMemberType(); + => this.GetIdentifyingMemberInfo()?.GetMemberType() + ?? (IsCollection + ? typeof(IEnumerable<>).MakeGenericType(TargetEntityType.ClrType) + : TargetEntityType.ClrType); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Metadata/Internal/SkipNavigationExtensions.cs b/src/EFCore/Metadata/Internal/SkipNavigationExtensions.cs index c1ffffa951d..adc3643d730 100644 --- a/src/EFCore/Metadata/Internal/SkipNavigationExtensions.cs +++ b/src/EFCore/Metadata/Internal/SkipNavigationExtensions.cs @@ -18,8 +18,11 @@ public static class SkipNavigationExtensions /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public static MemberIdentity CreateMemberIdentity(this IReadOnlySkipNavigation? navigation) - => navigation?.GetIdentifyingMemberInfo() == null - ? MemberIdentity.Create(navigation?.Name) - : MemberIdentity.Create(navigation.GetIdentifyingMemberInfo()); + { + var memberInfo = navigation?.GetIdentifyingMemberInfo(); + return memberInfo == null + ? MemberIdentity.Create(navigation?.Name) + : MemberIdentity.Create(memberInfo); + } } } diff --git a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs index 687d5724439..c031d6f994d 100644 --- a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs +++ b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs @@ -1518,11 +1518,13 @@ public virtual void Can_override_table_name_for_many_to_many_join_table_stored_i { Assert.Equal("LeftsId", p.Name); Assert.False(p.IsShadowProperty()); + Assert.True(p.IsIndexerProperty()); }, p => { Assert.Equal("RightsId", p.Name); Assert.False(p.IsShadowProperty()); + Assert.True(p.IsIndexerProperty()); }); Assert.Collection( joinEntity.FindDeclaredPrimaryKey().Properties, diff --git a/test/EFCore.Tests/Metadata/Internal/ClrCollectionAccessorFactoryTest.cs b/test/EFCore.Tests/Metadata/Internal/ClrCollectionAccessorFactoryTest.cs index 55051a526d0..8426defa920 100644 --- a/test/EFCore.Tests/Metadata/Internal/ClrCollectionAccessorFactoryTest.cs +++ b/test/EFCore.Tests/Metadata/Internal/ClrCollectionAccessorFactoryTest.cs @@ -30,72 +30,6 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Internal { public class ClrCollectionAccessorFactoryTest { - [ConditionalFact] - public void Navigation_is_returned_if_it_implements_IClrCollectionAccessor() - { - var navigation = new FakeNavigation(); - - var fk = new FakeForeignKey { PrincipalToDependent = navigation }; - navigation.ForeignKey = fk; - navigation.PropertyInfo = MyEntity.AsICollectionProperty; - - Assert.Same(navigation, new ClrCollectionAccessorFactory().Create(navigation)); - } - - private class FakeNavigation : Annotatable, INavigation, IClrCollectionAccessor - { - public string Name { get; } - public IReadOnlyTypeBase DeclaringType { get; } - public Type ClrType { get; } - public PropertyInfo PropertyInfo { get; set; } - public FieldInfo FieldInfo { get; } - public IEntityType DeclaringEntityType { get; } - public IReadOnlyForeignKey ForeignKey { get; set; } - - public bool Add(object entity, object value, bool forMaterialization) - => throw new NotImplementedException(); - - public bool Contains(object entity, object value) - => throw new NotImplementedException(); - - public bool Remove(object entity, object value) - => throw new NotImplementedException(); - - public object Create() - => throw new NotImplementedException(); - - public object GetOrCreate(object entity, bool forMaterialization) - => throw new NotImplementedException(); - - public IClrPropertyGetter GetGetter() => throw new NotImplementedException(); - - public IComparer GetCurrentValueComparer() - => throw new NotImplementedException(); - - public IClrCollectionAccessor GetCollectionAccessor() - => throw new NotImplementedException(); - - public PropertyAccessMode GetPropertyAccessMode() - => throw new NotImplementedException(); - - public Type CollectionType { get; } - } - - public class FakeForeignKey : Annotatable, IReadOnlyForeignKey - { - public IReadOnlyEntityType DeclaringEntityType { get; } - public IReadOnlyList Properties { get; } - public IReadOnlyEntityType PrincipalEntityType { get; } - public IReadOnlyKey PrincipalKey { get; } - public IReadOnlyNavigation DependentToPrincipal { get; set; } - public IReadOnlyNavigation PrincipalToDependent { get; set; } - public bool IsUnique { get; } - public bool IsRequired { get; } - public bool IsRequiredDependent { get; } - public bool IsOwnership { get; } - public DeleteBehavior DeleteBehavior { get; } - } - [ConditionalFact] public void Delegate_accessor_is_returned_for_IEnumerable_navigation() { @@ -492,6 +426,11 @@ private class MyEntity private readonly IEnumerable _readOnlyPropNoFieldNotFound; private IEnumerable _writeOnlyPropNoFieldNotFound; + public MyEntity() + : this(false) + { + } + public MyEntity(bool initialize) { if (initialize) diff --git a/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs b/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs index 8d5445de49d..d633ae4af57 100644 --- a/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs +++ b/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs @@ -153,6 +153,35 @@ public void Can_add_relationship_if_navigation_to_principal_ignored_at_lower_sou ConfigurationSource.DataAnnotation)); } + [ConditionalFact] + public void Can_add_relationship_on_property_bag() + { + var modelBuilder = CreateModelBuilder(); + var principalEntityBuilder = modelBuilder.Entity("Count", ConfigurationSource.Explicit); + var dependentEntityBuilder = modelBuilder.Entity("Value", ConfigurationSource.Explicit); + + var relationshipBuilder = dependentEntityBuilder.HasRelationship(principalEntityBuilder.Metadata, ConfigurationSource.Explicit) + .HasNavigation( + "Count", + pointsToPrincipal: true, + ConfigurationSource.Explicit) + .HasNavigation( + "Values", + pointsToPrincipal: false, + ConfigurationSource.Explicit); + + var fk = relationshipBuilder.Metadata; + Assert.Same(dependentEntityBuilder.Metadata.FindIndexerPropertyInfo(), fk.DependentToPrincipal.PropertyInfo); + Assert.Same(principalEntityBuilder.Metadata.FindIndexerPropertyInfo(), fk.PrincipalToDependent.PropertyInfo); + + var skipNavigationBuilder = principalEntityBuilder.HasSkipNavigation( + MemberIdentity.Create("Keys"), + dependentEntityBuilder.Metadata, + ConfigurationSource.Explicit); + + Assert.Same(dependentEntityBuilder.Metadata.FindIndexerPropertyInfo(), skipNavigationBuilder.Metadata.PropertyInfo); + } + [ConditionalFact] public void ForeignKey_creates_shadow_properties_if_corresponding_principal_key_property_is_non_shadow() { @@ -1641,6 +1670,8 @@ public void Property_removes_existing_index_property_for_higher_source_if_type_m typeof(string), IndexedClass.IndexerPropertyName, ConfigurationSource.Convention); Assert.NotNull(propertyBuilder); + Assert.True(propertyBuilder.Metadata.IsIndexerProperty()); + Assert.False(propertyBuilder.Metadata.IsShadowProperty()); var replacedPropertyBuilder = entityBuilder.Property( typeof(int), IndexedClass.IndexerPropertyName, ConfigurationSource.DataAnnotation); diff --git a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs index 492d8cc3042..748007356b8 100644 --- a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs @@ -1911,7 +1911,7 @@ public virtual void Can_add_seed_data_objects() c => { c.HasData( - new Beta { Id = -1 }); + new Beta { Id = -1, Name = " -1" }); var customers = new List { new() { Id = -2 } }; c.HasData(customers); }); @@ -1922,6 +1922,7 @@ public virtual void Can_add_seed_data_objects() var data = customer.GetSeedData(); Assert.Equal(2, data.Count()); Assert.Equal(-1, data.First()[nameof(Beta.Id)]); + Assert.Equal(" -1", data.First()[nameof(Beta.Name)]); Assert.Equal(-2, data.Last()[nameof(Beta.Id)]); var _ = finalModel.ToDebugString(); diff --git a/test/EFCore.Tests/ModelBuilding/TestModel.cs b/test/EFCore.Tests/ModelBuilding/TestModel.cs index 508a1da6b62..3f33ca6fd0e 100644 --- a/test/EFCore.Tests/ModelBuilding/TestModel.cs +++ b/test/EFCore.Tests/ModelBuilding/TestModel.cs @@ -450,7 +450,13 @@ protected class Alpha protected class Beta { + private string? _name; public int Id { get; set; } + public string? Name + { + get => "Beta: " + _name; + set => _name = value; + } public Alpha? FirstNav { get; set; } public Alpha? SecondNav { get; set; } From fc57581836e8ad52045681272714a95990bac3da Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Fri, 10 Sep 2021 06:11:03 +0100 Subject: [PATCH 080/346] More links to conceptual docs (#25937) Part of #17508 --- .../IDependentKeyValueFactory.cs | 3 +- .../IPrincipalKeyValueFactory.cs | 3 +- src/EFCore/Design/AttributeCodeFragment.cs | 3 +- .../DesignTimeProviderServicesAttribute.cs | 3 +- .../DesignTimeServicesReferenceAttribute.cs | 3 +- .../EntityFrameworkDesignServicesBuilder.cs | 3 +- src/EFCore/Design/ICSharpHelper.cs | 3 +- .../Design/IDesignTimeDbContextFactory.cs | 3 +- src/EFCore/Design/IDesignTimeServices.cs | 3 +- src/EFCore/Design/MethodCallCodeFragment.cs | 3 +- .../Design/NestedClosureCodeFragment.cs | 3 +- .../Diagnostics/CoreLoggerExtensions.cs | 3 +- src/EFCore/Diagnostics/EventDefinition.cs | 3 +- src/EFCore/Diagnostics/EventDefinitionBase.cs | 3 +- src/EFCore/Diagnostics/EventDefinition`.cs | 3 +- src/EFCore/Diagnostics/EventDefinition``.cs | 3 +- src/EFCore/Diagnostics/EventDefinition```.cs | 3 +- src/EFCore/Diagnostics/EventDefinition````.cs | 3 +- .../Diagnostics/EventDefinition`````.cs | 3 +- .../Diagnostics/EventDefinition``````.cs | 3 +- .../Diagnostics/FallbackEventDefinition.cs | 3 +- src/EFCore/Diagnostics/IDiagnosticsLogger.cs | 3 +- src/EFCore/Diagnostics/IDiagnosticsLogger`.cs | 3 +- src/EFCore/Diagnostics/LoggingDefinitions.cs | 3 +- src/EFCore/Infrastructure/Annotatable.cs | 3 +- src/EFCore/Infrastructure/AnnotatableBase.cs | 3 +- .../Infrastructure/AnnotatableBuilder.cs | 3 +- src/EFCore/Infrastructure/Annotation.cs | 3 +- ...currencyDetectorCriticalSectionDisposer.cs | 3 +- .../Infrastructure/ConventionAnnotatable.cs | 3 +- .../Infrastructure/CoreOptionsExtension.cs | 3 +- src/EFCore/Infrastructure/DatabaseFacade.cs | 6 +- .../DbContextOptionsExtensionInfo.cs | 24 ++-- .../EntityFrameworkServicesBuilder.cs | 42 ++++--- .../Infrastructure/ExpressionExtensions.cs | 3 +- src/EFCore/Infrastructure/IAnnotatable.cs | 3 +- src/EFCore/Infrastructure/IAnnotation.cs | 3 +- .../Infrastructure/IConcurrencyDetector.cs | 3 +- .../Infrastructure/ICoreSingletonOptions.cs | 3 +- .../Infrastructure/ICurrentDbContext.cs | 3 +- .../Infrastructure/IDbContextOptions.cs | 3 +- .../IDbContextOptionsBuilderInfrastructure.cs | 6 +- .../IDbContextOptionsExtension.cs | 3 +- src/EFCore/Infrastructure/IInfrastructure.cs | 3 +- .../IInternalServiceCollectionMap.cs | 3 +- src/EFCore/Infrastructure/IModelCustomizer.cs | 3 +- .../IModelRuntimeInitializer.cs | 3 +- src/EFCore/Infrastructure/IModelSource.cs | 3 +- src/EFCore/Infrastructure/IModelValidator.cs | 3 +- .../Infrastructure/IReadOnlyAnnotatable.cs | 3 +- .../Infrastructure/IResettableService.cs | 3 +- .../Infrastructure/ISingletonOptions.cs | 3 +- .../Infrastructure/IndentedStringBuilder.cs | 3 +- .../Infrastructure/MethodInfoExtensions.cs | 3 +- src/EFCore/Infrastructure/ModelCustomizer.cs | 3 +- .../Infrastructure/ModelRuntimeInitializer.cs | 3 +- src/EFCore/Infrastructure/ModelSource.cs | 3 +- src/EFCore/Infrastructure/ModelValidator.cs | 3 +- .../Infrastructure/ServiceCharacteristics.cs | 3 +- .../Infrastructure/ServiceCollectionMap.cs | 3 +- src/EFCore/Infrastructure/TypeExtensions.cs | 3 +- src/EFCore/Infrastructure/Uniquifier.cs | 3 +- .../Metadata/EntityTypeFullNameComparer.cs | 3 +- src/EFCore/Metadata/ForeignKeyComparer.cs | 3 +- src/EFCore/Metadata/IClrCollectionAccessor.cs | 3 +- src/EFCore/Metadata/IClrPropertyGetter.cs | 3 +- src/EFCore/Metadata/IClrPropertySetter.cs | 3 +- src/EFCore/Metadata/IDesignTimeModel.cs | 3 +- src/EFCore/Metadata/IndexComparer.cs | 3 +- src/EFCore/Metadata/KeyComparer.cs | 3 +- src/EFCore/Metadata/SimpleModelFactory.cs | 3 +- src/EFCore/Storage/CoreTypeMapping.cs | 4 + src/EFCore/Storage/Database.cs | 4 + src/EFCore/Storage/DatabaseProvider.cs | 4 + src/EFCore/Storage/ExecutionResult.cs | 4 + src/EFCore/Storage/ExecutionStrategy.cs | 72 ++++++++++++ .../Storage/ExecutionStrategyExtensions.cs | 104 ++++++++++++++++++ src/EFCore/Storage/IDatabase.cs | 4 + src/EFCore/Storage/IDatabaseCreator.cs | 4 + .../Storage/IDatabaseFacadeDependencies.cs | 4 + .../IDatabaseFacadeDependenciesAccessor.cs | 4 + src/EFCore/Storage/IDatabaseProvider.cs | 4 + src/EFCore/Storage/IDbContextTransaction.cs | 39 +++++++ .../Storage/IDbContextTransactionManager.cs | 4 + src/EFCore/Storage/IExecutionStrategy.cs | 16 +++ .../Storage/IExecutionStrategyFactory.cs | 8 ++ .../Storage/ITransactionEnlistmentManager.cs | 4 + src/EFCore/Storage/ITypeMappingSource.cs | 4 + .../Storage/ITypeMappingSourcePlugin.cs | 4 + src/EFCore/Storage/MaterializationContext.cs | 4 + .../Storage/NonRetryingExecutionStrategy.cs | 16 +++ .../Storage/RetryLimitExceededException.cs | 4 + src/EFCore/Storage/TypeMappingInfo.cs | 4 + src/EFCore/Storage/TypeMappingSource.cs | 4 + src/EFCore/Storage/TypeMappingSourceBase.cs | 4 + src/EFCore/Storage/ValueBuffer.cs | 4 + .../ValueConversion/BoolToStringConverter.cs | 6 + .../BoolToTwoValuesConverter.cs | 6 + .../ValueConversion/BoolToZeroOneConverter.cs | 9 ++ .../ValueConversion/BytesToStringConverter.cs | 9 ++ .../ValueConversion/CastingConverter.cs | 9 ++ .../ValueConversion/CharToStringConverter.cs | 9 ++ .../ValueConversion/ConverterMappingHints.cs | 9 ++ .../DateTimeOffsetToBinaryConverter.cs | 9 ++ .../DateTimeOffsetToBytesConverter.cs | 9 ++ .../DateTimeOffsetToStringConverter.cs | 9 ++ .../DateTimeToBinaryConverter.cs | 9 ++ .../DateTimeToStringConverter.cs | 9 ++ .../DateTimeToTicksConverter.cs | 9 ++ .../ValueConversion/EnumToNumberConverter.cs | 9 ++ .../ValueConversion/EnumToStringConverter.cs | 9 ++ .../ValueConversion/GuidToBytesConverter.cs | 9 ++ .../ValueConversion/GuidToStringConverter.cs | 9 ++ .../IPAddressToBytesConverter.cs | 9 ++ .../IPAddressToStringConverter.cs | 6 + .../IValueConverterSelector.cs | 6 + .../ValueConversion/NumberToBytesConverter.cs | 9 ++ .../NumberToStringConverter.cs | 9 ++ .../PhysicalAddressToBytesConverter.cs | 9 ++ .../PhysicalAddressToStringConverter.cs | 9 ++ .../ValueConversion/StringToBoolConverter.cs | 9 ++ .../ValueConversion/StringToBytesConverter.cs | 6 + .../ValueConversion/StringToCharConverter.cs | 9 ++ .../StringToDateTimeConverter.cs | 9 ++ .../StringToDateTimeOffsetConverter.cs | 9 ++ .../ValueConversion/StringToEnumConverter.cs | 9 ++ .../ValueConversion/StringToGuidConverter.cs | 9 ++ .../StringToNumberConverter.cs | 9 ++ .../StringToTimeSpanConverter.cs | 9 ++ .../ValueConversion/StringToUriConverter.cs | 9 ++ .../TimeSpanToStringConverter.cs | 9 ++ .../TimeSpanToTicksConverter.cs | 9 ++ .../ValueConversion/UriToStringConverter.cs | 9 ++ .../Storage/ValueConversion/ValueConverter.cs | 36 ++++++ .../ValueConversion/ValueConverterInfo.cs | 6 + .../ValueConversion/ValueConverterSelector.cs | 3 + .../ValueConversion/ValueConverter`.cs | 27 +++++ src/EFCore/Update/IUpdateAdapter.cs | 4 + src/EFCore/Update/IUpdateAdapterFactory.cs | 4 + src/EFCore/Update/IUpdateEntry.cs | 4 + src/EFCore/Update/UpdateEntryExtensions.cs | 7 ++ .../ValueGeneration/BinaryValueGenerator.cs | 3 + .../DiscriminatorValueGeneratorFactory.cs | 3 + .../ValueGeneration/GuidValueGenerator.cs | 3 + .../ValueGeneration/HiLoValueGenerator.cs | 3 + .../HiLoValueGeneratorState.cs | 3 + .../ValueGeneration/IValueGeneratorCache.cs | 4 + .../IValueGeneratorSelector.cs | 4 + .../SequentialGuidValueGenerator.cs | 3 + .../ValueGeneration/StringValueGenerator.cs | 3 + .../TemporaryGuidValueGenerator.cs | 3 + .../TemporaryNumberValueGeneratorFactory.cs | 3 + src/EFCore/ValueGeneration/ValueGenerator.cs | 21 ++++ .../ValueGeneration/ValueGeneratorCache.cs | 4 + .../ValueGeneration/ValueGeneratorFactory.cs | 9 ++ .../ValueGeneration/ValueGeneratorSelector.cs | 4 + src/EFCore/ValueGeneration/ValueGenerator`.cs | 15 +++ 157 files changed, 1014 insertions(+), 93 deletions(-) diff --git a/src/EFCore/ChangeTracking/IDependentKeyValueFactory.cs b/src/EFCore/ChangeTracking/IDependentKeyValueFactory.cs index 98286b05b57..6a38d0e3444 100644 --- a/src/EFCore/ChangeTracking/IDependentKeyValueFactory.cs +++ b/src/EFCore/ChangeTracking/IDependentKeyValueFactory.cs @@ -19,7 +19,8 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The generic type of the key. public interface IDependentKeyValueFactory diff --git a/src/EFCore/ChangeTracking/IPrincipalKeyValueFactory.cs b/src/EFCore/ChangeTracking/IPrincipalKeyValueFactory.cs index 6b4e1c3e8bd..963eb1dfb0c 100644 --- a/src/EFCore/ChangeTracking/IPrincipalKeyValueFactory.cs +++ b/src/EFCore/ChangeTracking/IPrincipalKeyValueFactory.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The key type. public interface IPrincipalKeyValueFactory diff --git a/src/EFCore/Design/AttributeCodeFragment.cs b/src/EFCore/Design/AttributeCodeFragment.cs index 70a448deb52..fd37cb576af 100644 --- a/src/EFCore/Design/AttributeCodeFragment.cs +++ b/src/EFCore/Design/AttributeCodeFragment.cs @@ -11,7 +11,8 @@ namespace Microsoft.EntityFrameworkCore.Design /// Represents usage of an attribute. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class AttributeCodeFragment { diff --git a/src/EFCore/Design/DesignTimeProviderServicesAttribute.cs b/src/EFCore/Design/DesignTimeProviderServicesAttribute.cs index 32147cabcfd..c2170e5660b 100644 --- a/src/EFCore/Design/DesignTimeProviderServicesAttribute.cs +++ b/src/EFCore/Design/DesignTimeProviderServicesAttribute.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Design /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// [AttributeUsage(AttributeTargets.Assembly)] public sealed class DesignTimeProviderServicesAttribute : Attribute diff --git a/src/EFCore/Design/DesignTimeServicesReferenceAttribute.cs b/src/EFCore/Design/DesignTimeServicesReferenceAttribute.cs index 0cb071e26d5..dc5bd37edc7 100644 --- a/src/EFCore/Design/DesignTimeServicesReferenceAttribute.cs +++ b/src/EFCore/Design/DesignTimeServicesReferenceAttribute.cs @@ -16,7 +16,8 @@ namespace Microsoft.EntityFrameworkCore.Design /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class DesignTimeServicesReferenceAttribute : Attribute diff --git a/src/EFCore/Design/EntityFrameworkDesignServicesBuilder.cs b/src/EFCore/Design/EntityFrameworkDesignServicesBuilder.cs index 95c19c74212..053afce5f4d 100644 --- a/src/EFCore/Design/EntityFrameworkDesignServicesBuilder.cs +++ b/src/EFCore/Design/EntityFrameworkDesignServicesBuilder.cs @@ -27,7 +27,8 @@ namespace Microsoft.EntityFrameworkCore.Design /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class EntityFrameworkDesignServicesBuilder : EntityFrameworkServicesBuilder { diff --git a/src/EFCore/Design/ICSharpHelper.cs b/src/EFCore/Design/ICSharpHelper.cs index 9caaff072e9..045cefffa01 100644 --- a/src/EFCore/Design/ICSharpHelper.cs +++ b/src/EFCore/Design/ICSharpHelper.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Design /// Helper for generating C# code. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface ICSharpHelper { diff --git a/src/EFCore/Design/IDesignTimeDbContextFactory.cs b/src/EFCore/Design/IDesignTimeDbContextFactory.cs index 4f3adae7cb7..0e68eafd366 100644 --- a/src/EFCore/Design/IDesignTimeDbContextFactory.cs +++ b/src/EFCore/Design/IDesignTimeDbContextFactory.cs @@ -11,7 +11,8 @@ namespace Microsoft.EntityFrameworkCore.Design /// this interface that are in the startup assembly or the same assembly as the derived context. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The type of the context. public interface IDesignTimeDbContextFactory diff --git a/src/EFCore/Design/IDesignTimeServices.cs b/src/EFCore/Design/IDesignTimeServices.cs index 90fd54c6f01..3b35098f820 100644 --- a/src/EFCore/Design/IDesignTimeServices.cs +++ b/src/EFCore/Design/IDesignTimeServices.cs @@ -10,7 +10,8 @@ namespace Microsoft.EntityFrameworkCore.Design /// interface that are in the startup assembly. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IDesignTimeServices { diff --git a/src/EFCore/Design/MethodCallCodeFragment.cs b/src/EFCore/Design/MethodCallCodeFragment.cs index b2628ae9aaa..2b415ca5f56 100644 --- a/src/EFCore/Design/MethodCallCodeFragment.cs +++ b/src/EFCore/Design/MethodCallCodeFragment.cs @@ -13,7 +13,8 @@ namespace Microsoft.EntityFrameworkCore.Design /// Represents a call to a method. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class MethodCallCodeFragment { diff --git a/src/EFCore/Design/NestedClosureCodeFragment.cs b/src/EFCore/Design/NestedClosureCodeFragment.cs index 814b9fc0b8e..86bb6d41b70 100644 --- a/src/EFCore/Design/NestedClosureCodeFragment.cs +++ b/src/EFCore/Design/NestedClosureCodeFragment.cs @@ -10,7 +10,8 @@ namespace Microsoft.EntityFrameworkCore.Design /// Represents a nested closure code fragment. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class NestedClosureCodeFragment { diff --git a/src/EFCore/Diagnostics/CoreLoggerExtensions.cs b/src/EFCore/Diagnostics/CoreLoggerExtensions.cs index 4011841a73d..3e232a0a3ea 100644 --- a/src/EFCore/Diagnostics/CoreLoggerExtensions.cs +++ b/src/EFCore/Diagnostics/CoreLoggerExtensions.cs @@ -35,7 +35,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public static class CoreLoggerExtensions { diff --git a/src/EFCore/Diagnostics/EventDefinition.cs b/src/EFCore/Diagnostics/EventDefinition.cs index b9629c4be3b..4af7920b483 100644 --- a/src/EFCore/Diagnostics/EventDefinition.cs +++ b/src/EFCore/Diagnostics/EventDefinition.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// event with reduced allocations. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class EventDefinition : EventDefinitionBase { diff --git a/src/EFCore/Diagnostics/EventDefinitionBase.cs b/src/EFCore/Diagnostics/EventDefinitionBase.cs index 81f3c5b94fd..2fda72d0c14 100644 --- a/src/EFCore/Diagnostics/EventDefinitionBase.cs +++ b/src/EFCore/Diagnostics/EventDefinitionBase.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// Base class for event definitions. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public abstract class EventDefinitionBase { diff --git a/src/EFCore/Diagnostics/EventDefinition`.cs b/src/EFCore/Diagnostics/EventDefinition`.cs index 565f594ad52..56725736699 100644 --- a/src/EFCore/Diagnostics/EventDefinition`.cs +++ b/src/EFCore/Diagnostics/EventDefinition`.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// event with reduced allocations. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class EventDefinition : EventDefinitionBase { diff --git a/src/EFCore/Diagnostics/EventDefinition``.cs b/src/EFCore/Diagnostics/EventDefinition``.cs index 017d45c2558..00818b170d7 100644 --- a/src/EFCore/Diagnostics/EventDefinition``.cs +++ b/src/EFCore/Diagnostics/EventDefinition``.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// event with reduced allocations. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class EventDefinition : EventDefinitionBase { diff --git a/src/EFCore/Diagnostics/EventDefinition```.cs b/src/EFCore/Diagnostics/EventDefinition```.cs index b92903053d3..9dc228088ce 100644 --- a/src/EFCore/Diagnostics/EventDefinition```.cs +++ b/src/EFCore/Diagnostics/EventDefinition```.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// event with reduced allocations. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class EventDefinition : EventDefinitionBase { diff --git a/src/EFCore/Diagnostics/EventDefinition````.cs b/src/EFCore/Diagnostics/EventDefinition````.cs index 5a5d741b736..45d811dd27c 100644 --- a/src/EFCore/Diagnostics/EventDefinition````.cs +++ b/src/EFCore/Diagnostics/EventDefinition````.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// event with reduced allocations. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class EventDefinition : EventDefinitionBase { diff --git a/src/EFCore/Diagnostics/EventDefinition`````.cs b/src/EFCore/Diagnostics/EventDefinition`````.cs index 086149864e8..e3c6b746cb6 100644 --- a/src/EFCore/Diagnostics/EventDefinition`````.cs +++ b/src/EFCore/Diagnostics/EventDefinition`````.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// event with reduced allocations. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class EventDefinition : EventDefinitionBase { diff --git a/src/EFCore/Diagnostics/EventDefinition``````.cs b/src/EFCore/Diagnostics/EventDefinition``````.cs index 7556a2c3409..841fb150345 100644 --- a/src/EFCore/Diagnostics/EventDefinition``````.cs +++ b/src/EFCore/Diagnostics/EventDefinition``````.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// event with reduced allocations. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class EventDefinition : EventDefinitionBase { diff --git a/src/EFCore/Diagnostics/FallbackEventDefinition.cs b/src/EFCore/Diagnostics/FallbackEventDefinition.cs index 2c7f908f908..bd2bda500eb 100644 --- a/src/EFCore/Diagnostics/FallbackEventDefinition.cs +++ b/src/EFCore/Diagnostics/FallbackEventDefinition.cs @@ -12,7 +12,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// special handling. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class FallbackEventDefinition : EventDefinitionBase { diff --git a/src/EFCore/Diagnostics/IDiagnosticsLogger.cs b/src/EFCore/Diagnostics/IDiagnosticsLogger.cs index 0ab4121a9cb..9bef529dcfe 100644 --- a/src/EFCore/Diagnostics/IDiagnosticsLogger.cs +++ b/src/EFCore/Diagnostics/IDiagnosticsLogger.cs @@ -21,7 +21,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IDiagnosticsLogger { diff --git a/src/EFCore/Diagnostics/IDiagnosticsLogger`.cs b/src/EFCore/Diagnostics/IDiagnosticsLogger`.cs index 08d61f8649c..5ced2e01a4c 100644 --- a/src/EFCore/Diagnostics/IDiagnosticsLogger`.cs +++ b/src/EFCore/Diagnostics/IDiagnosticsLogger`.cs @@ -26,7 +26,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IDiagnosticsLogger : IDiagnosticsLogger where TLoggerCategory : LoggerCategory, new() diff --git a/src/EFCore/Diagnostics/LoggingDefinitions.cs b/src/EFCore/Diagnostics/LoggingDefinitions.cs index aaca3f6969b..223846f02f8 100644 --- a/src/EFCore/Diagnostics/LoggingDefinitions.cs +++ b/src/EFCore/Diagnostics/LoggingDefinitions.cs @@ -16,7 +16,8 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public abstract class LoggingDefinitions { diff --git a/src/EFCore/Infrastructure/Annotatable.cs b/src/EFCore/Infrastructure/Annotatable.cs index 0abecee4e68..00f11f50ac4 100644 --- a/src/EFCore/Infrastructure/Annotatable.cs +++ b/src/EFCore/Infrastructure/Annotatable.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class Annotatable : AnnotatableBase, IMutableAnnotatable { diff --git a/src/EFCore/Infrastructure/AnnotatableBase.cs b/src/EFCore/Infrastructure/AnnotatableBase.cs index 39d3196ffd3..b3959cf1397 100644 --- a/src/EFCore/Infrastructure/AnnotatableBase.cs +++ b/src/EFCore/Infrastructure/AnnotatableBase.cs @@ -22,7 +22,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class AnnotatableBase : IAnnotatable { diff --git a/src/EFCore/Infrastructure/AnnotatableBuilder.cs b/src/EFCore/Infrastructure/AnnotatableBuilder.cs index 0d9251d59da..5c2ccbda055 100644 --- a/src/EFCore/Infrastructure/AnnotatableBuilder.cs +++ b/src/EFCore/Infrastructure/AnnotatableBuilder.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// [DebuggerDisplay("Builder {" + nameof(Metadata) + ",nq}")] public abstract class AnnotatableBuilder : IConventionAnnotatableBuilder diff --git a/src/EFCore/Infrastructure/Annotation.cs b/src/EFCore/Infrastructure/Annotation.cs index b81fabf498f..ba2bfdcf55b 100644 --- a/src/EFCore/Infrastructure/Annotation.cs +++ b/src/EFCore/Infrastructure/Annotation.cs @@ -15,7 +15,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class Annotation : IAnnotation { diff --git a/src/EFCore/Infrastructure/ConcurrencyDetectorCriticalSectionDisposer.cs b/src/EFCore/Infrastructure/ConcurrencyDetectorCriticalSectionDisposer.cs index 39bb7bb74b8..86bbb36be4c 100644 --- a/src/EFCore/Infrastructure/ConcurrencyDetectorCriticalSectionDisposer.cs +++ b/src/EFCore/Infrastructure/ConcurrencyDetectorCriticalSectionDisposer.cs @@ -10,7 +10,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// critical section when disposed. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public readonly struct ConcurrencyDetectorCriticalSectionDisposer : IDisposable { diff --git a/src/EFCore/Infrastructure/ConventionAnnotatable.cs b/src/EFCore/Infrastructure/ConventionAnnotatable.cs index 3eeec59168b..a0b3a9c7986 100644 --- a/src/EFCore/Infrastructure/ConventionAnnotatable.cs +++ b/src/EFCore/Infrastructure/ConventionAnnotatable.cs @@ -21,7 +21,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public abstract class ConventionAnnotatable : Annotatable, IConventionAnnotatable, IMutableAnnotatable { diff --git a/src/EFCore/Infrastructure/CoreOptionsExtension.cs b/src/EFCore/Infrastructure/CoreOptionsExtension.cs index 4e2a8ed48b2..e3759ab436f 100644 --- a/src/EFCore/Infrastructure/CoreOptionsExtension.cs +++ b/src/EFCore/Infrastructure/CoreOptionsExtension.cs @@ -26,7 +26,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class CoreOptionsExtension : IDbContextOptionsExtension { diff --git a/src/EFCore/Infrastructure/DatabaseFacade.cs b/src/EFCore/Infrastructure/DatabaseFacade.cs index 6dd018ca6e2..4ddd75b1c23 100644 --- a/src/EFCore/Infrastructure/DatabaseFacade.cs +++ b/src/EFCore/Infrastructure/DatabaseFacade.cs @@ -354,7 +354,8 @@ public virtual Task RollbackTransactionAsync(CancellationToken cancellationToken /// Creates an instance of the configured . /// /// - /// See EF Core Connection Resiliency for more information. + /// See Connection resiliency and database retries + /// for more information. /// /// An instance. public virtual IExecutionStrategy CreateExecutionStrategy() @@ -463,7 +464,8 @@ public virtual string? ProviderName /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// IServiceProvider IInfrastructure.Instance => ((IInfrastructure)_context).Instance; diff --git a/src/EFCore/Infrastructure/DbContextOptionsExtensionInfo.cs b/src/EFCore/Infrastructure/DbContextOptionsExtensionInfo.cs index 3416a17ff63..a0c74c93024 100644 --- a/src/EFCore/Infrastructure/DbContextOptionsExtensionInfo.cs +++ b/src/EFCore/Infrastructure/DbContextOptionsExtensionInfo.cs @@ -11,7 +11,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// Information/metadata for an . /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public abstract class DbContextOptionsExtensionInfo { @@ -20,7 +21,8 @@ public abstract class DbContextOptionsExtensionInfo /// info/metadata for the given extension. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The extension. protected DbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) @@ -34,7 +36,8 @@ protected DbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) /// The extension for which this instance contains metadata. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public virtual IDbContextOptionsExtension Extension { get; } @@ -42,7 +45,8 @@ protected DbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) /// if the extension is a database provider; otherwise. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public abstract bool IsDatabaseProvider { get; } @@ -51,7 +55,8 @@ protected DbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) /// any useful non-default options that have been configured. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public abstract string LogFragment { get; } @@ -61,7 +66,8 @@ protected DbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) /// have any such options and should return zero. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// A hash over options that require a new service provider when changed. public abstract int GetServiceProviderHashCode(); @@ -71,7 +77,8 @@ protected DbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) /// are the same as in the given extension. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The other extension. /// A value indicating whether all of the options that require a new service provider are the same. @@ -84,7 +91,8 @@ protected DbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) /// extension name. For example, "SqlServer:". /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The dictionary to populate. public abstract void PopulateDebugInfo(IDictionary debugInfo); diff --git a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs index aae0e145b4e..65a4870b205 100644 --- a/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs +++ b/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs @@ -49,7 +49,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class EntityFrameworkServicesBuilder { @@ -160,7 +161,8 @@ public static readonly IDictionary CoreServices /// 'EntityFrameworkRelationalServicesBuilder'. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The collection to which services will be registered. public EntityFrameworkServicesBuilder(IServiceCollection serviceCollection) @@ -174,7 +176,8 @@ public EntityFrameworkServicesBuilder(IServiceCollection serviceCollection) /// Access to the underlying . /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// protected virtual ServiceCollectionMap ServiceCollectionMap { get; } @@ -182,7 +185,8 @@ public EntityFrameworkServicesBuilder(IServiceCollection serviceCollection) /// Gets the for the given service type. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The type that defines the service API. /// The for the type. @@ -199,7 +203,8 @@ protected virtual ServiceCharacteristics GetServiceCharacteristics(Type serviceT /// Gets the for the given service type. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The type that defines the service API. /// The for the type or if it's not an EF service. @@ -215,7 +220,8 @@ protected virtual ServiceCharacteristics GetServiceCharacteristics(Type serviceT /// and not through this method. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The underlying map to which provider services should be added. /// This builder, such that further calls can be chained. @@ -244,7 +250,8 @@ public virtual EntityFrameworkServicesBuilder TryAddProviderSpecificServices(Act /// after all provider services have been registered. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// This builder, such that further calls can be chained. public virtual EntityFrameworkServicesBuilder TryAddCoreServices() @@ -368,7 +375,8 @@ private static IDbContextServices GetContextServices(IServiceProvider servicePro /// The scope of the service is automatically defined by Entity Framework. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The contract for the service. /// The concrete type that implements the service. @@ -383,7 +391,8 @@ public virtual EntityFrameworkServicesBuilder TryAdd( /// The scope of the service is automatically defined by Entity Framework. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The contract for the service. /// The concrete type that implements the service. @@ -412,7 +421,8 @@ public virtual EntityFrameworkServicesBuilder TryAdd(Type serviceType, Type impl /// The scope of the service is automatically defined by Entity Framework. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The contract for the service. /// The factory that will create the service instance. @@ -426,7 +436,8 @@ public virtual EntityFrameworkServicesBuilder TryAdd(Func /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The contract for the service. /// The concrete type that implements the service. @@ -443,7 +454,8 @@ public virtual EntityFrameworkServicesBuilder TryAdd( /// The scope of the service is automatically defined by Entity Framework. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The contract for the service. /// The concrete type that implements the service. @@ -483,7 +495,8 @@ public virtual EntityFrameworkServicesBuilder TryAdd( /// This method can only be used for singleton services. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The contract for the service. /// The implementation of the service. @@ -497,7 +510,8 @@ public virtual EntityFrameworkServicesBuilder TryAdd(TService implemen /// This method can only be used for singleton services. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The contract for the service. /// The implementation of the service. diff --git a/src/EFCore/Infrastructure/ExpressionExtensions.cs b/src/EFCore/Infrastructure/ExpressionExtensions.cs index 4c614134439..4edbfc6cece 100644 --- a/src/EFCore/Infrastructure/ExpressionExtensions.cs +++ b/src/EFCore/Infrastructure/ExpressionExtensions.cs @@ -27,7 +27,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public static class ExpressionExtensions { diff --git a/src/EFCore/Infrastructure/IAnnotatable.cs b/src/EFCore/Infrastructure/IAnnotatable.cs index e12b9f010fe..85adcec58c6 100644 --- a/src/EFCore/Infrastructure/IAnnotatable.cs +++ b/src/EFCore/Infrastructure/IAnnotatable.cs @@ -16,7 +16,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IAnnotatable : IReadOnlyAnnotatable { diff --git a/src/EFCore/Infrastructure/IAnnotation.cs b/src/EFCore/Infrastructure/IAnnotation.cs index f1f20a0fc94..eca38298353 100644 --- a/src/EFCore/Infrastructure/IAnnotation.cs +++ b/src/EFCore/Infrastructure/IAnnotation.cs @@ -13,7 +13,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IAnnotation { diff --git a/src/EFCore/Infrastructure/IConcurrencyDetector.cs b/src/EFCore/Infrastructure/IConcurrencyDetector.cs index 5f31758870c..648e0865e73 100644 --- a/src/EFCore/Infrastructure/IConcurrencyDetector.cs +++ b/src/EFCore/Infrastructure/IConcurrencyDetector.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IConcurrencyDetector { diff --git a/src/EFCore/Infrastructure/ICoreSingletonOptions.cs b/src/EFCore/Infrastructure/ICoreSingletonOptions.cs index 8334439c79a..8126a97b91e 100644 --- a/src/EFCore/Infrastructure/ICoreSingletonOptions.cs +++ b/src/EFCore/Infrastructure/ICoreSingletonOptions.cs @@ -17,7 +17,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface ICoreSingletonOptions : ISingletonOptions { diff --git a/src/EFCore/Infrastructure/ICurrentDbContext.cs b/src/EFCore/Infrastructure/ICurrentDbContext.cs index 3bfeddbd070..14bef09ea61 100644 --- a/src/EFCore/Infrastructure/ICurrentDbContext.cs +++ b/src/EFCore/Infrastructure/ICurrentDbContext.cs @@ -22,7 +22,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface ICurrentDbContext { diff --git a/src/EFCore/Infrastructure/IDbContextOptions.cs b/src/EFCore/Infrastructure/IDbContextOptions.cs index f82b331d108..56321d3e4e0 100644 --- a/src/EFCore/Infrastructure/IDbContextOptions.cs +++ b/src/EFCore/Infrastructure/IDbContextOptions.cs @@ -21,7 +21,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IDbContextOptions { diff --git a/src/EFCore/Infrastructure/IDbContextOptionsBuilderInfrastructure.cs b/src/EFCore/Infrastructure/IDbContextOptionsBuilderInfrastructure.cs index fc68a3494ea..003973bcbc9 100644 --- a/src/EFCore/Infrastructure/IDbContextOptionsBuilderInfrastructure.cs +++ b/src/EFCore/Infrastructure/IDbContextOptionsBuilderInfrastructure.cs @@ -14,7 +14,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IDbContextOptionsBuilderInfrastructure { @@ -28,7 +29,8 @@ public interface IDbContextOptionsBuilderInfrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The type of extension to be added. /// The extension to be added. diff --git a/src/EFCore/Infrastructure/IDbContextOptionsExtension.cs b/src/EFCore/Infrastructure/IDbContextOptionsExtension.cs index 0b0d24e72b0..49120837da2 100644 --- a/src/EFCore/Infrastructure/IDbContextOptionsExtension.cs +++ b/src/EFCore/Infrastructure/IDbContextOptionsExtension.cs @@ -16,7 +16,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IDbContextOptionsExtension { diff --git a/src/EFCore/Infrastructure/IInfrastructure.cs b/src/EFCore/Infrastructure/IInfrastructure.cs index 52363b1cfb5..8f66749193c 100644 --- a/src/EFCore/Infrastructure/IInfrastructure.cs +++ b/src/EFCore/Infrastructure/IInfrastructure.cs @@ -14,7 +14,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// /// The type of the property being hidden. public interface IInfrastructure diff --git a/src/EFCore/Infrastructure/IInternalServiceCollectionMap.cs b/src/EFCore/Infrastructure/IInternalServiceCollectionMap.cs index 303712c8a0e..d9f051996a1 100644 --- a/src/EFCore/Infrastructure/IInternalServiceCollectionMap.cs +++ b/src/EFCore/Infrastructure/IInternalServiceCollectionMap.cs @@ -15,7 +15,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IInternalServiceCollectionMap { diff --git a/src/EFCore/Infrastructure/IModelCustomizer.cs b/src/EFCore/Infrastructure/IModelCustomizer.cs index 6eda21fcc00..78aa03f165d 100644 --- a/src/EFCore/Infrastructure/IModelCustomizer.cs +++ b/src/EFCore/Infrastructure/IModelCustomizer.cs @@ -24,7 +24,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IModelCustomizer { diff --git a/src/EFCore/Infrastructure/IModelRuntimeInitializer.cs b/src/EFCore/Infrastructure/IModelRuntimeInitializer.cs index 8546a7671f2..6a3d1546ffa 100644 --- a/src/EFCore/Infrastructure/IModelRuntimeInitializer.cs +++ b/src/EFCore/Infrastructure/IModelRuntimeInitializer.cs @@ -24,7 +24,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IModelRuntimeInitializer { diff --git a/src/EFCore/Infrastructure/IModelSource.cs b/src/EFCore/Infrastructure/IModelSource.cs index 190221475af..cf50c4882f4 100644 --- a/src/EFCore/Infrastructure/IModelSource.cs +++ b/src/EFCore/Infrastructure/IModelSource.cs @@ -24,7 +24,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IModelSource { diff --git a/src/EFCore/Infrastructure/IModelValidator.cs b/src/EFCore/Infrastructure/IModelValidator.cs index 877b8338e67..5f523d48c5f 100644 --- a/src/EFCore/Infrastructure/IModelValidator.cs +++ b/src/EFCore/Infrastructure/IModelValidator.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IModelValidator { diff --git a/src/EFCore/Infrastructure/IReadOnlyAnnotatable.cs b/src/EFCore/Infrastructure/IReadOnlyAnnotatable.cs index a6e073efdd1..14e31be0593 100644 --- a/src/EFCore/Infrastructure/IReadOnlyAnnotatable.cs +++ b/src/EFCore/Infrastructure/IReadOnlyAnnotatable.cs @@ -17,7 +17,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IReadOnlyAnnotatable { diff --git a/src/EFCore/Infrastructure/IResettableService.cs b/src/EFCore/Infrastructure/IResettableService.cs index be25179fd4e..0fcc6a3cd23 100644 --- a/src/EFCore/Infrastructure/IResettableService.cs +++ b/src/EFCore/Infrastructure/IResettableService.cs @@ -26,7 +26,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IResettableService { diff --git a/src/EFCore/Infrastructure/ISingletonOptions.cs b/src/EFCore/Infrastructure/ISingletonOptions.cs index 90b506e6fea..373f8563e83 100644 --- a/src/EFCore/Infrastructure/ISingletonOptions.cs +++ b/src/EFCore/Infrastructure/ISingletonOptions.cs @@ -19,7 +19,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface ISingletonOptions { diff --git a/src/EFCore/Infrastructure/IndentedStringBuilder.cs b/src/EFCore/Infrastructure/IndentedStringBuilder.cs index 234aeb2c633..24f26da35c8 100644 --- a/src/EFCore/Infrastructure/IndentedStringBuilder.cs +++ b/src/EFCore/Infrastructure/IndentedStringBuilder.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class IndentedStringBuilder { diff --git a/src/EFCore/Infrastructure/MethodInfoExtensions.cs b/src/EFCore/Infrastructure/MethodInfoExtensions.cs index 4971331be91..54dc7b02524 100644 --- a/src/EFCore/Infrastructure/MethodInfoExtensions.cs +++ b/src/EFCore/Infrastructure/MethodInfoExtensions.cs @@ -15,7 +15,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public static class MethodInfoExtensions { diff --git a/src/EFCore/Infrastructure/ModelCustomizer.cs b/src/EFCore/Infrastructure/ModelCustomizer.cs index e95d8379607..7ea168f103d 100644 --- a/src/EFCore/Infrastructure/ModelCustomizer.cs +++ b/src/EFCore/Infrastructure/ModelCustomizer.cs @@ -22,7 +22,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class ModelCustomizer : IModelCustomizer { diff --git a/src/EFCore/Infrastructure/ModelRuntimeInitializer.cs b/src/EFCore/Infrastructure/ModelRuntimeInitializer.cs index 5652cf10d17..ff11340f17a 100644 --- a/src/EFCore/Infrastructure/ModelRuntimeInitializer.cs +++ b/src/EFCore/Infrastructure/ModelRuntimeInitializer.cs @@ -24,7 +24,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class ModelRuntimeInitializer : IModelRuntimeInitializer { diff --git a/src/EFCore/Infrastructure/ModelSource.cs b/src/EFCore/Infrastructure/ModelSource.cs index 009e089103b..ed10798f50c 100644 --- a/src/EFCore/Infrastructure/ModelSource.cs +++ b/src/EFCore/Infrastructure/ModelSource.cs @@ -28,7 +28,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class ModelSource : IModelSource { diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index 0cc1676b50e..e8b7eccba1f 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -27,7 +27,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class ModelValidator : IModelValidator { diff --git a/src/EFCore/Infrastructure/ServiceCharacteristics.cs b/src/EFCore/Infrastructure/ServiceCharacteristics.cs index 7b2b2b9378f..8a520865aed 100644 --- a/src/EFCore/Infrastructure/ServiceCharacteristics.cs +++ b/src/EFCore/Infrastructure/ServiceCharacteristics.cs @@ -9,7 +9,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// Characteristics of a given EF service. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public readonly struct ServiceCharacteristics { diff --git a/src/EFCore/Infrastructure/ServiceCollectionMap.cs b/src/EFCore/Infrastructure/ServiceCollectionMap.cs index 0b4cbe3ed54..67618e5bb19 100644 --- a/src/EFCore/Infrastructure/ServiceCollectionMap.cs +++ b/src/EFCore/Infrastructure/ServiceCollectionMap.cs @@ -22,7 +22,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class ServiceCollectionMap : IInfrastructure { diff --git a/src/EFCore/Infrastructure/TypeExtensions.cs b/src/EFCore/Infrastructure/TypeExtensions.cs index 8e970f7f8ad..828cc3fe413 100644 --- a/src/EFCore/Infrastructure/TypeExtensions.cs +++ b/src/EFCore/Infrastructure/TypeExtensions.cs @@ -15,7 +15,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public static class TypeExtensions { diff --git a/src/EFCore/Infrastructure/Uniquifier.cs b/src/EFCore/Infrastructure/Uniquifier.cs index 8ed21684487..7adc4bfbd14 100644 --- a/src/EFCore/Infrastructure/Uniquifier.cs +++ b/src/EFCore/Infrastructure/Uniquifier.cs @@ -11,7 +11,8 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// Provides methods for manipulating string identifiers. /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public static class Uniquifier { diff --git a/src/EFCore/Metadata/EntityTypeFullNameComparer.cs b/src/EFCore/Metadata/EntityTypeFullNameComparer.cs index d2fe6135fa9..6a4b2448e02 100644 --- a/src/EFCore/Metadata/EntityTypeFullNameComparer.cs +++ b/src/EFCore/Metadata/EntityTypeFullNameComparer.cs @@ -17,7 +17,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public sealed class EntityTypeFullNameComparer : IComparer, IEqualityComparer { diff --git a/src/EFCore/Metadata/ForeignKeyComparer.cs b/src/EFCore/Metadata/ForeignKeyComparer.cs index b7ff1be4a67..acb6575b9b0 100644 --- a/src/EFCore/Metadata/ForeignKeyComparer.cs +++ b/src/EFCore/Metadata/ForeignKeyComparer.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public sealed class ForeignKeyComparer : IEqualityComparer, IComparer { diff --git a/src/EFCore/Metadata/IClrCollectionAccessor.cs b/src/EFCore/Metadata/IClrCollectionAccessor.cs index 7c637d60b2b..c0d7e781b3f 100644 --- a/src/EFCore/Metadata/IClrCollectionAccessor.cs +++ b/src/EFCore/Metadata/IClrCollectionAccessor.cs @@ -16,7 +16,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IClrCollectionAccessor { diff --git a/src/EFCore/Metadata/IClrPropertyGetter.cs b/src/EFCore/Metadata/IClrPropertyGetter.cs index 2a6ffd24597..57c26a7fa00 100644 --- a/src/EFCore/Metadata/IClrPropertyGetter.cs +++ b/src/EFCore/Metadata/IClrPropertyGetter.cs @@ -14,7 +14,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IClrPropertyGetter { diff --git a/src/EFCore/Metadata/IClrPropertySetter.cs b/src/EFCore/Metadata/IClrPropertySetter.cs index 62984df561f..fbb2968b33f 100644 --- a/src/EFCore/Metadata/IClrPropertySetter.cs +++ b/src/EFCore/Metadata/IClrPropertySetter.cs @@ -14,7 +14,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IClrPropertySetter { diff --git a/src/EFCore/Metadata/IDesignTimeModel.cs b/src/EFCore/Metadata/IDesignTimeModel.cs index c055ad3b867..b5e33ce0afe 100644 --- a/src/EFCore/Metadata/IDesignTimeModel.cs +++ b/src/EFCore/Metadata/IDesignTimeModel.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public interface IDesignTimeModel { diff --git a/src/EFCore/Metadata/IndexComparer.cs b/src/EFCore/Metadata/IndexComparer.cs index 80daa3da51d..768437e20b0 100644 --- a/src/EFCore/Metadata/IndexComparer.cs +++ b/src/EFCore/Metadata/IndexComparer.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public sealed class IndexComparer : IEqualityComparer, IComparer { diff --git a/src/EFCore/Metadata/KeyComparer.cs b/src/EFCore/Metadata/KeyComparer.cs index 34b8dee3507..242d25b31c3 100644 --- a/src/EFCore/Metadata/KeyComparer.cs +++ b/src/EFCore/Metadata/KeyComparer.cs @@ -18,7 +18,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public sealed class KeyComparer : IEqualityComparer, IComparer { diff --git a/src/EFCore/Metadata/SimpleModelFactory.cs b/src/EFCore/Metadata/SimpleModelFactory.cs index 85a657d155b..a9b14701e67 100644 --- a/src/EFCore/Metadata/SimpleModelFactory.cs +++ b/src/EFCore/Metadata/SimpleModelFactory.cs @@ -17,7 +17,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// /// - /// See Implementation of database providers and extensions for more information. + /// See Implementation of database providers and extensions + /// for more information. /// public class SimpleModelFactory { diff --git a/src/EFCore/Storage/CoreTypeMapping.cs b/src/EFCore/Storage/CoreTypeMapping.cs index 5de231426e9..3b2dc928ddc 100644 --- a/src/EFCore/Storage/CoreTypeMapping.cs +++ b/src/EFCore/Storage/CoreTypeMapping.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class CoreTypeMapping { /// diff --git a/src/EFCore/Storage/Database.cs b/src/EFCore/Storage/Database.cs index 0b1a1b4ed5b..c326c8af349 100644 --- a/src/EFCore/Storage/Database.cs +++ b/src/EFCore/Storage/Database.cs @@ -28,6 +28,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class Database : IDatabase { /// diff --git a/src/EFCore/Storage/DatabaseProvider.cs b/src/EFCore/Storage/DatabaseProvider.cs index 5c3b7963260..9aaa850f435 100644 --- a/src/EFCore/Storage/DatabaseProvider.cs +++ b/src/EFCore/Storage/DatabaseProvider.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// /// /// The type of options that the database provider will add to /// to identify that is has been selected (and to store its database specific settings). diff --git a/src/EFCore/Storage/ExecutionResult.cs b/src/EFCore/Storage/ExecutionResult.cs index 6c429530d43..387200074d8 100644 --- a/src/EFCore/Storage/ExecutionResult.cs +++ b/src/EFCore/Storage/ExecutionResult.cs @@ -6,6 +6,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// Represents the execution state of an operation. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The type of the result. public class ExecutionResult { diff --git a/src/EFCore/Storage/ExecutionStrategy.cs b/src/EFCore/Storage/ExecutionStrategy.cs index 12aac0f7cbf..cd6849430b2 100644 --- a/src/EFCore/Storage/ExecutionStrategy.cs +++ b/src/EFCore/Storage/ExecutionStrategy.cs @@ -15,11 +15,19 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// The base class for implementations. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public abstract class ExecutionStrategy : IExecutionStrategy { /// /// The default number of retry attempts. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// protected static readonly int DefaultMaxRetryCount = 6; /// @@ -45,6 +53,10 @@ public abstract class ExecutionStrategy : IExecutionStrategy /// /// Creates a new instance of . /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The context on which the operations will be invoked. /// The maximum number of retry attempts. /// The maximum delay between retries. @@ -62,6 +74,10 @@ protected ExecutionStrategy( /// /// Creates a new instance of . /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// Parameter object containing service dependencies. /// The maximum number of retry attempts. /// The maximum delay between retries. @@ -88,6 +104,10 @@ protected ExecutionStrategy( /// /// The list of exceptions that caused the operation to be retried so far. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// protected virtual List ExceptionsEncountered { get; } = new(); /// @@ -98,11 +118,19 @@ protected ExecutionStrategy( /// /// The maximum number of retry attempts. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// protected virtual int MaxRetryCount { get; } /// /// The maximum delay between retries. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// protected virtual TimeSpan MaxRetryDelay { get; } /// @@ -116,6 +144,10 @@ protected ExecutionStrategy( /// Indicates whether the strategy is suspended. The strategy is typically suspending while executing to avoid /// recursive execution from nested operations. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// [Obsolete("Use Current instead")] protected static bool Suspended { @@ -126,6 +158,10 @@ protected static bool Suspended /// /// Gets or sets the currently executing strategy. All nested calls will be handled by the outermost strategy. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public static ExecutionStrategy? Current { get => _current.Value; @@ -135,6 +171,10 @@ public static ExecutionStrategy? Current /// /// Indicates whether this might retry the execution after a failure. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public virtual bool RetriesOnFailure { get @@ -147,6 +187,10 @@ public virtual bool RetriesOnFailure /// /// Executes the specified operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The state that will be passed to the operation. /// /// A delegate representing an executable operation that returns the result of type . @@ -237,6 +281,10 @@ private ExecutionResult ExecuteImplementation( /// /// Executes the specified asynchronous operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The state that will be passed to the operation. /// /// A function that returns a started task of type . @@ -343,6 +391,10 @@ private async Task> ExecuteImplementationAsync /// Method called before the first operation execution /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// protected virtual void OnFirstExecution() { if (RetriesOnFailure && @@ -368,6 +420,10 @@ protected virtual void OnFirstExecution() /// /// Method called before retrying the operation execution /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// protected virtual void OnRetry() { } @@ -375,6 +431,10 @@ protected virtual void OnRetry() /// /// Determines whether the operation should be retried and the delay before the next attempt. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The exception thrown during the last execution attempt. /// /// Returns the delay indicating how long to wait for before the next execution attempt if the operation should be retried; @@ -401,6 +461,10 @@ protected virtual void OnRetry() /// /// Determines whether the specified exception could be thrown after a successful execution. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The exception object to be verified. /// /// if the specified exception could be thrown after a successful execution, otherwise . @@ -411,6 +475,10 @@ protected internal virtual bool ShouldVerifySuccessOn(Exception exception) /// /// Determines whether the specified exception represents a transient failure that can be compensated by a retry. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The exception object to be verified. /// /// if the specified exception is considered as transient, otherwise . @@ -421,6 +489,10 @@ protected internal virtual bool ShouldVerifySuccessOn(Exception exception) /// Recursively gets InnerException from as long as it is an /// exception created by Entity Framework and calls on the innermost one. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The exception to be unwrapped. /// A delegate that will be called with the unwrapped exception. /// The return type of . diff --git a/src/EFCore/Storage/ExecutionStrategyExtensions.cs b/src/EFCore/Storage/ExecutionStrategyExtensions.cs index c02d833c0c0..f28966a0692 100644 --- a/src/EFCore/Storage/ExecutionStrategyExtensions.cs +++ b/src/EFCore/Storage/ExecutionStrategyExtensions.cs @@ -13,11 +13,19 @@ namespace Microsoft.EntityFrameworkCore /// /// Extension methods for /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public static class ExecutionStrategyExtensions { /// /// Executes the specified operation. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// A delegate representing an executable operation that doesn't return any results. public static void Execute( @@ -37,6 +45,10 @@ public static void Execute( /// /// Executes the specified operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// /// A delegate representing an executable operation that returns the result of type . @@ -55,6 +67,10 @@ public static TResult Execute( /// /// Executes the specified operation. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// A delegate representing an executable operation that doesn't return any results. @@ -77,6 +93,10 @@ public static void Execute( /// /// Executes the specified asynchronous operation. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// A function that returns a started task. /// @@ -101,6 +121,10 @@ public static Task ExecuteAsync( /// /// Executes the specified asynchronous operation. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// A function that returns a started task. /// @@ -131,6 +155,10 @@ public static Task ExecuteAsync( /// /// Executes the specified asynchronous operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// /// A function that returns a started task of type . @@ -155,6 +183,10 @@ public static Task ExecuteAsync( /// /// Executes the specified asynchronous operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// /// A function that returns a started task of type . @@ -185,6 +217,10 @@ public static Task ExecuteAsync( /// /// Executes the specified asynchronous operation. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// A function that returns a started task. @@ -212,6 +248,10 @@ public static Task ExecuteAsync( /// /// Executes the specified asynchronous operation. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// A function that returns a started task. @@ -245,6 +285,10 @@ public static Task ExecuteAsync( /// /// Executes the specified asynchronous operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -273,6 +317,10 @@ public static Task ExecuteAsync( /// /// Executes the specified operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -290,6 +338,10 @@ public static TResult Execute( /// /// Executes the specified asynchronous operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -319,6 +371,10 @@ public static Task ExecuteAsync( /// /// Executes the specified operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// /// A delegate representing an executable operation that returns the result of type . @@ -344,6 +400,10 @@ public static TResult Execute( /// /// Executes the specified asynchronous operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -382,6 +442,10 @@ public static Task ExecuteAsync( /// Executes the specified operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// /// A delegate representing an executable operation. @@ -403,6 +467,10 @@ public static void ExecuteInTransaction( /// Executes the specified asynchronous operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// /// A function that returns a started task. @@ -429,6 +497,10 @@ public static Task ExecuteInTransactionAsync( /// Executes the specified asynchronous operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// /// A function that returns a started task. @@ -462,6 +534,10 @@ public static Task ExecuteInTransactionAsync( /// Executes the specified operation in a transaction and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// /// A delegate representing an executable operation that returns the result of type . @@ -485,6 +561,10 @@ public static TResult ExecuteInTransaction( /// Executes the specified asynchronous operation in a transaction and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// /// A function that returns a started task of type . @@ -519,6 +599,10 @@ public static Task ExecuteInTransactionAsync( /// Executes the specified operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -548,6 +632,10 @@ public static void ExecuteInTransaction( /// Executes the specified asynchronous operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -588,6 +676,10 @@ public static Task ExecuteInTransactionAsync( /// Executes the specified operation in a transaction and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -617,6 +709,10 @@ public static TResult ExecuteInTransaction( /// Executes the specified asynchronous operation in a transaction and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -657,6 +753,10 @@ public static Task ExecuteInTransactionAsync( /// Executes the specified operation in a transaction and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -700,6 +800,10 @@ public static TResult ExecuteInTransaction( /// Executes the specified asynchronous operation in a transaction and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// diff --git a/src/EFCore/Storage/IDatabase.cs b/src/EFCore/Storage/IDatabase.cs index ce3023e90bb..172d3996142 100644 --- a/src/EFCore/Storage/IDatabase.cs +++ b/src/EFCore/Storage/IDatabase.cs @@ -27,6 +27,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IDatabase { /// diff --git a/src/EFCore/Storage/IDatabaseCreator.cs b/src/EFCore/Storage/IDatabaseCreator.cs index 7e9f0fddf03..ac49a971933 100644 --- a/src/EFCore/Storage/IDatabaseCreator.cs +++ b/src/EFCore/Storage/IDatabaseCreator.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IDatabaseCreator { /// diff --git a/src/EFCore/Storage/IDatabaseFacadeDependencies.cs b/src/EFCore/Storage/IDatabaseFacadeDependencies.cs index b13076cb80f..c78c3bc23a5 100644 --- a/src/EFCore/Storage/IDatabaseFacadeDependencies.cs +++ b/src/EFCore/Storage/IDatabaseFacadeDependencies.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IDatabaseFacadeDependencies { /// diff --git a/src/EFCore/Storage/IDatabaseFacadeDependenciesAccessor.cs b/src/EFCore/Storage/IDatabaseFacadeDependenciesAccessor.cs index 173a1ae1c66..014c4ef27b0 100644 --- a/src/EFCore/Storage/IDatabaseFacadeDependenciesAccessor.cs +++ b/src/EFCore/Storage/IDatabaseFacadeDependenciesAccessor.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IDatabaseFacadeDependenciesAccessor { /// diff --git a/src/EFCore/Storage/IDatabaseProvider.cs b/src/EFCore/Storage/IDatabaseProvider.cs index 25fb8fe3504..c10f543af3d 100644 --- a/src/EFCore/Storage/IDatabaseProvider.cs +++ b/src/EFCore/Storage/IDatabaseProvider.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IDatabaseProvider { /// diff --git a/src/EFCore/Storage/IDbContextTransaction.cs b/src/EFCore/Storage/IDbContextTransaction.cs index 8784b2c6894..d3af812bd1a 100644 --- a/src/EFCore/Storage/IDbContextTransaction.cs +++ b/src/EFCore/Storage/IDbContextTransaction.cs @@ -18,21 +18,33 @@ namespace Microsoft.EntityFrameworkCore.Storage /// to be directly constructed in your application code. /// /// + /// + /// See Transactions in EF Core for more information. + /// public interface IDbContextTransaction : IDisposable, IAsyncDisposable { /// /// Gets the transaction identifier. /// + /// + /// See Transactions in EF Core for more information. + /// Guid TransactionId { get; } /// /// Commits all changes made to the database in the current transaction. /// + /// + /// See Transactions in EF Core for more information. + /// void Commit(); /// /// Commits all changes made to the database in the current transaction asynchronously. /// + /// + /// See Transactions in EF Core for more information. + /// /// A to observe while waiting for the task to complete. /// A representing the asynchronous operation. /// If the is canceled. @@ -41,11 +53,17 @@ public interface IDbContextTransaction : IDisposable, IAsyncDisposable /// /// Discards all changes made to the database in the current transaction. /// + /// + /// See Transactions in EF Core for more information. + /// void Rollback(); /// /// Discards all changes made to the database in the current transaction asynchronously. /// + /// + /// See Transactions in EF Core for more information. + /// /// A to observe while waiting for the task to complete. /// A representing the asynchronous operation. /// If the is canceled. @@ -56,6 +74,9 @@ public interface IDbContextTransaction : IDisposable, IAsyncDisposable /// was established to be rolled back, restoring the transaction state to what it was at the time of the /// savepoint. /// + /// + /// See Transactions in EF Core for more information. + /// /// The name of the savepoint to be created. void CreateSavepoint(string name) => throw new NotSupportedException(CoreStrings.SavepointsNotSupported); @@ -65,6 +86,9 @@ void CreateSavepoint(string name) /// was established to be rolled back, restoring the transaction state to what it was at the time of the /// savepoint. /// + /// + /// See Transactions in EF Core for more information. + /// /// The name of the savepoint to be created. /// A to observe while waiting for the task to complete. /// A representing the asynchronous operation. @@ -75,6 +99,9 @@ Task CreateSavepointAsync(string name, CancellationToken cancellationToken = def /// /// Rolls back all commands that were executed after the specified savepoint was established. /// + /// + /// See Transactions in EF Core for more information. + /// /// The name of the savepoint to roll back to. void RollbackToSavepoint(string name) => throw new NotSupportedException(CoreStrings.SavepointsNotSupported); @@ -82,6 +109,9 @@ void RollbackToSavepoint(string name) /// /// Rolls back all commands that were executed after the specified savepoint was established. /// + /// + /// See Transactions in EF Core for more information. + /// /// The name of the savepoint to roll back to. /// A to observe while waiting for the task to complete. /// A representing the asynchronous operation. @@ -99,6 +129,9 @@ Task RollbackToSavepointAsync(string name, CancellationToken cancellationToken = /// do nothing rather than throw. This is the default behavior. /// /// + /// + /// See Transactions in EF Core for more information. + /// /// The name of the savepoint to release. void ReleaseSavepoint(string name) { } @@ -112,6 +145,9 @@ void ReleaseSavepoint(string name) { } /// do nothing rather than throw. This is the default behavior. /// /// + /// + /// See Transactions in EF Core for more information. + /// /// The name of the savepoint to release. /// A to observe while waiting for the task to complete. /// A representing the asynchronous operation. @@ -126,6 +162,9 @@ Task ReleaseSavepointAsync(string name, CancellationToken cancellationToken = de /// and as well as their synchronous counterparts are expected to throw /// . /// + /// + /// See Transactions in EF Core for more information. + /// /// /// if this instance supports database savepoints; /// otherwise, . diff --git a/src/EFCore/Storage/IDbContextTransactionManager.cs b/src/EFCore/Storage/IDbContextTransactionManager.cs index f212fb254d2..f4574499f94 100644 --- a/src/EFCore/Storage/IDbContextTransactionManager.cs +++ b/src/EFCore/Storage/IDbContextTransactionManager.cs @@ -24,6 +24,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// and Transactions in EF Core for more information. + /// public interface IDbContextTransactionManager : IResettableService { /// diff --git a/src/EFCore/Storage/IExecutionStrategy.cs b/src/EFCore/Storage/IExecutionStrategy.cs index 3335f355035..863d4621453 100644 --- a/src/EFCore/Storage/IExecutionStrategy.cs +++ b/src/EFCore/Storage/IExecutionStrategy.cs @@ -19,16 +19,28 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public interface IExecutionStrategy { /// /// Indicates whether this might retry the execution after a failure. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// bool RetriesOnFailure { get; } /// /// Executes the specified operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The state that will be passed to the operation. /// /// A delegate representing an executable operation that returns the result of type . @@ -48,6 +60,10 @@ TResult Execute( /// /// Executes the specified asynchronous operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The state that will be passed to the operation. /// /// A function that returns a started task of type . diff --git a/src/EFCore/Storage/IExecutionStrategyFactory.cs b/src/EFCore/Storage/IExecutionStrategyFactory.cs index f08f5a7d2c8..7e4adc06c7d 100644 --- a/src/EFCore/Storage/IExecutionStrategyFactory.cs +++ b/src/EFCore/Storage/IExecutionStrategyFactory.cs @@ -16,11 +16,19 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public interface IExecutionStrategyFactory { /// /// Creates a new . /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// An instance of . IExecutionStrategy Create(); } diff --git a/src/EFCore/Storage/ITransactionEnlistmentManager.cs b/src/EFCore/Storage/ITransactionEnlistmentManager.cs index b0bd985d151..8ec108269fb 100644 --- a/src/EFCore/Storage/ITransactionEnlistmentManager.cs +++ b/src/EFCore/Storage/ITransactionEnlistmentManager.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface ITransactionEnlistmentManager { /// diff --git a/src/EFCore/Storage/ITypeMappingSource.cs b/src/EFCore/Storage/ITypeMappingSource.cs index 950cd2224c7..87bdfe4320a 100644 --- a/src/EFCore/Storage/ITypeMappingSource.cs +++ b/src/EFCore/Storage/ITypeMappingSource.cs @@ -26,6 +26,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface ITypeMappingSource { /// diff --git a/src/EFCore/Storage/ITypeMappingSourcePlugin.cs b/src/EFCore/Storage/ITypeMappingSourcePlugin.cs index d44f95ae30c..5f451166106 100644 --- a/src/EFCore/Storage/ITypeMappingSourcePlugin.cs +++ b/src/EFCore/Storage/ITypeMappingSourcePlugin.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface ITypeMappingSourcePlugin { /// diff --git a/src/EFCore/Storage/MaterializationContext.cs b/src/EFCore/Storage/MaterializationContext.cs index e4d222c2698..9008f03e50a 100644 --- a/src/EFCore/Storage/MaterializationContext.cs +++ b/src/EFCore/Storage/MaterializationContext.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public readonly struct MaterializationContext { /// diff --git a/src/EFCore/Storage/NonRetryingExecutionStrategy.cs b/src/EFCore/Storage/NonRetryingExecutionStrategy.cs index 559f8b06f88..799aa2ef5f0 100644 --- a/src/EFCore/Storage/NonRetryingExecutionStrategy.cs +++ b/src/EFCore/Storage/NonRetryingExecutionStrategy.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// An implementation of that does no retries. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public sealed class NonRetryingExecutionStrategy : IExecutionStrategy { /// @@ -24,12 +28,20 @@ public NonRetryingExecutionStrategy(ExecutionStrategyDependencies dependencies) /// /// Always returns false, since the does not perform retries. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public bool RetriesOnFailure => false; /// /// Executes the specified operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The state that will be passed to the operation. /// /// A delegate representing an executable operation that returns the result of type . @@ -50,6 +62,10 @@ public TResult Execute( /// /// Executes the specified asynchronous operation and returns the result. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The state that will be passed to the operation. /// /// A function that returns a started task of type . diff --git a/src/EFCore/Storage/RetryLimitExceededException.cs b/src/EFCore/Storage/RetryLimitExceededException.cs index 96bfc4290ff..46122e4cbeb 100644 --- a/src/EFCore/Storage/RetryLimitExceededException.cs +++ b/src/EFCore/Storage/RetryLimitExceededException.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// The exception that is thrown when the action failed more times than the configured limit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// [Serializable] public class RetryLimitExceededException : Exception { diff --git a/src/EFCore/Storage/TypeMappingInfo.cs b/src/EFCore/Storage/TypeMappingInfo.cs index fc09cacea4b..090f61d7e0d 100644 --- a/src/EFCore/Storage/TypeMappingInfo.cs +++ b/src/EFCore/Storage/TypeMappingInfo.cs @@ -13,6 +13,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// Describes metadata needed to decide on a type mapping for a property or type. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public readonly record struct TypeMappingInfo : IEquatable { /// diff --git a/src/EFCore/Storage/TypeMappingSource.cs b/src/EFCore/Storage/TypeMappingSource.cs index d1ac814b231..9d9b5100443 100644 --- a/src/EFCore/Storage/TypeMappingSource.cs +++ b/src/EFCore/Storage/TypeMappingSource.cs @@ -27,6 +27,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class TypeMappingSource : TypeMappingSourceBase { private readonly ConcurrentDictionary<(TypeMappingInfo, Type?, ValueConverter?), CoreTypeMapping?> _explicitMappings = new(); diff --git a/src/EFCore/Storage/TypeMappingSourceBase.cs b/src/EFCore/Storage/TypeMappingSourceBase.cs index 0404074fd2b..f5a6232357c 100644 --- a/src/EFCore/Storage/TypeMappingSourceBase.cs +++ b/src/EFCore/Storage/TypeMappingSourceBase.cs @@ -25,6 +25,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class TypeMappingSourceBase : ITypeMappingSource { /// diff --git a/src/EFCore/Storage/ValueBuffer.cs b/src/EFCore/Storage/ValueBuffer.cs index 4a07c49662c..f7133a1286b 100644 --- a/src/EFCore/Storage/ValueBuffer.cs +++ b/src/EFCore/Storage/ValueBuffer.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public readonly struct ValueBuffer : IEquatable { /// diff --git a/src/EFCore/Storage/ValueConversion/BoolToStringConverter.cs b/src/EFCore/Storage/ValueConversion/BoolToStringConverter.cs index 7411a522a55..2ae9d05824f 100644 --- a/src/EFCore/Storage/ValueConversion/BoolToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/BoolToStringConverter.cs @@ -10,12 +10,18 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts values to and from two string values. /// + /// + /// See EF Core value converters for more information. + /// public class BoolToStringConverter : BoolToTwoValuesConverter { /// /// Creates a new instance of this converter. A case-insensitive first character test is used /// when converting from the store. /// + /// + /// See EF Core value converters for more information. + /// /// The string to use for . /// The string to use for . /// diff --git a/src/EFCore/Storage/ValueConversion/BoolToTwoValuesConverter.cs b/src/EFCore/Storage/ValueConversion/BoolToTwoValuesConverter.cs index 1e716630976..54eae901695 100644 --- a/src/EFCore/Storage/ValueConversion/BoolToTwoValuesConverter.cs +++ b/src/EFCore/Storage/ValueConversion/BoolToTwoValuesConverter.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts values to and from two different values. /// + /// + /// See EF Core value converters for more information. + /// public class BoolToTwoValuesConverter : ValueConverter { /// @@ -20,6 +23,9 @@ public class BoolToTwoValuesConverter : ValueConverter for converting a to zero/one. /// /// + /// + /// See EF Core value converters for more information. + /// /// The value to convert to for . /// The value to convert to for . /// Optional custom translator from store. diff --git a/src/EFCore/Storage/ValueConversion/BoolToZeroOneConverter.cs b/src/EFCore/Storage/ValueConversion/BoolToZeroOneConverter.cs index 811f8a8146f..37b025703f2 100644 --- a/src/EFCore/Storage/ValueConversion/BoolToZeroOneConverter.cs +++ b/src/EFCore/Storage/ValueConversion/BoolToZeroOneConverter.cs @@ -8,11 +8,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts values to and from 0 and 1. /// + /// + /// See EF Core value converters for more information. + /// public class BoolToZeroOneConverter : BoolToTwoValuesConverter { /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// public BoolToZeroOneConverter() : this(null) { @@ -21,6 +27,9 @@ public BoolToZeroOneConverter() /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/BytesToStringConverter.cs b/src/EFCore/Storage/ValueConversion/BytesToStringConverter.cs index 47ca4215d01..df92c2db6df 100644 --- a/src/EFCore/Storage/ValueConversion/BytesToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/BytesToStringConverter.cs @@ -8,11 +8,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts arrays of bytes to and from strings. /// + /// + /// See EF Core value converters for more information. + /// public class BytesToStringConverter : ValueConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public BytesToStringConverter() : this(null) { @@ -21,6 +27,9 @@ public BytesToStringConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/CastingConverter.cs b/src/EFCore/Storage/ValueConversion/CastingConverter.cs index 5c47a126bd0..d6f81b197b1 100644 --- a/src/EFCore/Storage/ValueConversion/CastingConverter.cs +++ b/src/EFCore/Storage/ValueConversion/CastingConverter.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// Converts to and from using simple casts from one type /// to the other. /// + /// + /// See EF Core value converters for more information. + /// public class CastingConverter : ValueConverter { // ReSharper disable once StaticMemberInGenericType @@ -40,6 +43,9 @@ public class CastingConverter : ValueConverter /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public CastingConverter() : this(null) { @@ -48,6 +54,9 @@ public CastingConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public CastingConverter(ConverterMappingHints? mappingHints) : base( Convert(), diff --git a/src/EFCore/Storage/ValueConversion/CharToStringConverter.cs b/src/EFCore/Storage/ValueConversion/CharToStringConverter.cs index 1c68f73695e..7be283b3f04 100644 --- a/src/EFCore/Storage/ValueConversion/CharToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/CharToStringConverter.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts a to and from a single-character . /// + /// + /// See EF Core value converters for more information. + /// public class CharToStringConverter : StringCharConverter { private static readonly ConverterMappingHints _defaultHints = new(size: 1); @@ -15,6 +18,9 @@ public class CharToStringConverter : StringCharConverter /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// public CharToStringConverter() : this(null) { @@ -23,6 +29,9 @@ public CharToStringConverter() /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/ConverterMappingHints.cs b/src/EFCore/Storage/ValueConversion/ConverterMappingHints.cs index b5d2f33befc..4314aa3a066 100644 --- a/src/EFCore/Storage/ValueConversion/ConverterMappingHints.cs +++ b/src/EFCore/Storage/ValueConversion/ConverterMappingHints.cs @@ -10,12 +10,18 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Specifies hints used by the type mapper when mapping using a . /// + /// + /// See EF Core value converters for more information. + /// public class ConverterMappingHints { /// /// Creates a new instance. Any hint contained in the instance /// can be to indicate it has not been specified. /// + /// + /// See EF Core value converters for more information. + /// /// The suggested size of the mapped data type. /// The suggested precision of the mapped data type. /// The suggested scale of the mapped data type. @@ -39,6 +45,9 @@ public ConverterMappingHints( /// Adds hints from the given object to this one. Hints that are already specified are /// not overridden. /// + /// + /// See EF Core value converters for more information. + /// /// The hints to add. /// The combined hints. public virtual ConverterMappingHints With(ConverterMappingHints? hints) diff --git a/src/EFCore/Storage/ValueConversion/DateTimeOffsetToBinaryConverter.cs b/src/EFCore/Storage/ValueConversion/DateTimeOffsetToBinaryConverter.cs index f6885f26b52..1cde7d0fd9d 100644 --- a/src/EFCore/Storage/ValueConversion/DateTimeOffsetToBinaryConverter.cs +++ b/src/EFCore/Storage/ValueConversion/DateTimeOffsetToBinaryConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// Converts to and from binary representation in a long. /// The DateTime is truncated beyond 0.1 millisecond precision. /// + /// + /// See EF Core value converters for more information. + /// public class DateTimeOffsetToBinaryConverter : ValueConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public DateTimeOffsetToBinaryConverter() : this(null) { @@ -22,6 +28,9 @@ public DateTimeOffsetToBinaryConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/DateTimeOffsetToBytesConverter.cs b/src/EFCore/Storage/ValueConversion/DateTimeOffsetToBytesConverter.cs index e2049671db8..58bd2ebe6e7 100644 --- a/src/EFCore/Storage/ValueConversion/DateTimeOffsetToBytesConverter.cs +++ b/src/EFCore/Storage/ValueConversion/DateTimeOffsetToBytesConverter.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts to and from arrays of bytes. /// + /// + /// See EF Core value converters for more information. + /// public class DateTimeOffsetToBytesConverter : ValueConverter { private static readonly ConverterMappingHints _defaultHints = new(size: 12); @@ -18,6 +21,9 @@ public class DateTimeOffsetToBytesConverter : ValueConverter /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public DateTimeOffsetToBytesConverter() : this(null) { @@ -26,6 +32,9 @@ public DateTimeOffsetToBytesConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/DateTimeOffsetToStringConverter.cs b/src/EFCore/Storage/ValueConversion/DateTimeOffsetToStringConverter.cs index c07bdaf0cd3..b7fa07518b8 100644 --- a/src/EFCore/Storage/ValueConversion/DateTimeOffsetToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/DateTimeOffsetToStringConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts to and from strings. /// + /// + /// See EF Core value converters for more information. + /// public class DateTimeOffsetToStringConverter : StringDateTimeOffsetConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public DateTimeOffsetToStringConverter() : this(null) { @@ -22,6 +28,9 @@ public DateTimeOffsetToStringConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/DateTimeToBinaryConverter.cs b/src/EFCore/Storage/ValueConversion/DateTimeToBinaryConverter.cs index 1737bfe4f1e..ec7061f35f5 100644 --- a/src/EFCore/Storage/ValueConversion/DateTimeToBinaryConverter.cs +++ b/src/EFCore/Storage/ValueConversion/DateTimeToBinaryConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// Converts using . This /// will preserve the . /// + /// + /// See EF Core value converters for more information. + /// public class DateTimeToBinaryConverter : ValueConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public DateTimeToBinaryConverter() : this(null) { @@ -22,6 +28,9 @@ public DateTimeToBinaryConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/DateTimeToStringConverter.cs b/src/EFCore/Storage/ValueConversion/DateTimeToStringConverter.cs index d736cd44c77..a4afb731093 100644 --- a/src/EFCore/Storage/ValueConversion/DateTimeToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/DateTimeToStringConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts to and from strings. /// + /// + /// See EF Core value converters for more information. + /// public class DateTimeToStringConverter : StringDateTimeConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public DateTimeToStringConverter() : this(null) { @@ -22,6 +28,9 @@ public DateTimeToStringConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/DateTimeToTicksConverter.cs b/src/EFCore/Storage/ValueConversion/DateTimeToTicksConverter.cs index aaa262149e0..8622a3f6804 100644 --- a/src/EFCore/Storage/ValueConversion/DateTimeToTicksConverter.cs +++ b/src/EFCore/Storage/ValueConversion/DateTimeToTicksConverter.cs @@ -8,11 +8,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts to and . /// + /// + /// See EF Core value converters for more information. + /// public class DateTimeToTicksConverter : ValueConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public DateTimeToTicksConverter() : this(null) { @@ -21,6 +27,9 @@ public DateTimeToTicksConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/EnumToNumberConverter.cs b/src/EFCore/Storage/ValueConversion/EnumToNumberConverter.cs index 9697e97b625..5faa3fc405f 100644 --- a/src/EFCore/Storage/ValueConversion/EnumToNumberConverter.cs +++ b/src/EFCore/Storage/ValueConversion/EnumToNumberConverter.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts enum values to and from their underlying numeric representation. /// + /// + /// See EF Core value converters for more information. + /// public class EnumToNumberConverter : ValueConverter where TEnum : struct where TNumber : struct @@ -31,6 +34,9 @@ public class EnumToNumberConverter : ValueConverter /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// public EnumToNumberConverter() : this(null) { @@ -39,6 +45,9 @@ public EnumToNumberConverter() /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/EnumToStringConverter.cs b/src/EFCore/Storage/ValueConversion/EnumToStringConverter.cs index 25d34fb57e1..782da773a09 100644 --- a/src/EFCore/Storage/ValueConversion/EnumToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/EnumToStringConverter.cs @@ -8,12 +8,18 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts enum values to and from their string representation. /// + /// + /// See EF Core value converters for more information. + /// public class EnumToStringConverter : StringEnumConverter where TEnum : struct { /// /// Creates a new instance of this converter. This converter does not preserve order. /// + /// + /// See EF Core value converters for more information. + /// public EnumToStringConverter() : this(null) { @@ -22,6 +28,9 @@ public EnumToStringConverter() /// /// Creates a new instance of this converter. This converter does not preserve order. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/GuidToBytesConverter.cs b/src/EFCore/Storage/ValueConversion/GuidToBytesConverter.cs index 36497a4c36a..53eb952d0b4 100644 --- a/src/EFCore/Storage/ValueConversion/GuidToBytesConverter.cs +++ b/src/EFCore/Storage/ValueConversion/GuidToBytesConverter.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts a to and from an array of . /// + /// + /// See EF Core value converters for more information. + /// public class GuidToBytesConverter : ValueConverter { private static readonly ConverterMappingHints _defaultHints @@ -24,6 +27,9 @@ private static readonly ConverterMappingHints _defaultHints /// in the standard string representation. /// /// + /// + /// See EF Core value converters for more information. + /// public GuidToBytesConverter() : this(null) { @@ -39,6 +45,9 @@ public GuidToBytesConverter() /// in the standard string representation. /// /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/GuidToStringConverter.cs b/src/EFCore/Storage/ValueConversion/GuidToStringConverter.cs index c059a22df96..e7aa94e556d 100644 --- a/src/EFCore/Storage/ValueConversion/GuidToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/GuidToStringConverter.cs @@ -10,11 +10,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// Converts a to and from a using the /// standard "8-4-4-4-12" format./>. /// + /// + /// See EF Core value converters for more information. + /// public class GuidToStringConverter : StringGuidConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public GuidToStringConverter() : this(null) { @@ -23,6 +29,9 @@ public GuidToStringConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/IPAddressToBytesConverter.cs b/src/EFCore/Storage/ValueConversion/IPAddressToBytesConverter.cs index 478108eba68..338fcd21715 100644 --- a/src/EFCore/Storage/ValueConversion/IPAddressToBytesConverter.cs +++ b/src/EFCore/Storage/ValueConversion/IPAddressToBytesConverter.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts a to and from a . /// + /// + /// See EF Core value converters for more information. + /// public class IPAddressToBytesConverter : ValueConverter { private static readonly ConverterMappingHints _defaultHints = new(size: 16); @@ -15,6 +18,9 @@ public class IPAddressToBytesConverter : ValueConverter /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public IPAddressToBytesConverter() : this(null) { @@ -23,6 +29,9 @@ public IPAddressToBytesConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/IPAddressToStringConverter.cs b/src/EFCore/Storage/ValueConversion/IPAddressToStringConverter.cs index 63edc1fbe8a..b3d38310006 100644 --- a/src/EFCore/Storage/ValueConversion/IPAddressToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/IPAddressToStringConverter.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts a to and from a . /// + /// + /// See EF Core value converters for more information. + /// public class IPAddressToStringConverter : ValueConverter { // IPv4-mapped IPv6 addresses can go up to 45 bytes, e.g. 0000:0000:0000:0000:0000:ffff:192.168.1.1 @@ -26,6 +29,9 @@ public IPAddressToStringConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/IValueConverterSelector.cs b/src/EFCore/Storage/ValueConversion/IValueConverterSelector.cs index b431d689aec..8a277dffae8 100644 --- a/src/EFCore/Storage/ValueConversion/IValueConverterSelector.cs +++ b/src/EFCore/Storage/ValueConversion/IValueConverterSelector.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// This service cannot depend on services registered as . /// /// + /// + /// See EF Core value converters for more information. + /// public interface IValueConverterSelector { /// @@ -26,6 +29,9 @@ public interface IValueConverterSelector /// used to convert the given model type. Converters nearer the front of /// the list should be used in preference to converters nearer the end. /// + /// + /// See EF Core value converters for more information. + /// /// The type for which a converter is needed. /// The store type to target, or null for any. /// The converters available. diff --git a/src/EFCore/Storage/ValueConversion/NumberToBytesConverter.cs b/src/EFCore/Storage/ValueConversion/NumberToBytesConverter.cs index c4908624cf1..cc1186cbe14 100644 --- a/src/EFCore/Storage/ValueConversion/NumberToBytesConverter.cs +++ b/src/EFCore/Storage/ValueConversion/NumberToBytesConverter.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts numeric values to and from arrays of bytes. /// + /// + /// See EF Core value converters for more information. + /// public class NumberToBytesConverter : ValueConverter { // ReSharper disable once StaticMemberInGenericType @@ -26,6 +29,9 @@ public class NumberToBytesConverter : ValueConverter /// and . /// /// + /// + /// See EF Core value converters for more information. + /// public NumberToBytesConverter() : this(null) { @@ -42,6 +48,9 @@ public NumberToBytesConverter() /// and . /// /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/NumberToStringConverter.cs b/src/EFCore/Storage/ValueConversion/NumberToStringConverter.cs index 7a0b72755b2..b4720f695f6 100644 --- a/src/EFCore/Storage/ValueConversion/NumberToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/NumberToStringConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts numeric values to and from their string representation. /// + /// + /// See EF Core value converters for more information. + /// public class NumberToStringConverter : StringNumberConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public NumberToStringConverter() : this(null) { @@ -22,6 +28,9 @@ public NumberToStringConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/PhysicalAddressToBytesConverter.cs b/src/EFCore/Storage/ValueConversion/PhysicalAddressToBytesConverter.cs index f72513872ce..7e6ce3501b2 100644 --- a/src/EFCore/Storage/ValueConversion/PhysicalAddressToBytesConverter.cs +++ b/src/EFCore/Storage/ValueConversion/PhysicalAddressToBytesConverter.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts a to and from a . /// + /// + /// See EF Core value converters for more information. + /// public class PhysicalAddressToBytesConverter : ValueConverter { private static readonly ConverterMappingHints _defaultHints = new(size: 8); @@ -15,6 +18,9 @@ public class PhysicalAddressToBytesConverter : ValueConverter /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public PhysicalAddressToBytesConverter() : this(null) { @@ -23,6 +29,9 @@ public PhysicalAddressToBytesConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/PhysicalAddressToStringConverter.cs b/src/EFCore/Storage/ValueConversion/PhysicalAddressToStringConverter.cs index a5e557e547a..ea9c1fb1b34 100644 --- a/src/EFCore/Storage/ValueConversion/PhysicalAddressToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/PhysicalAddressToStringConverter.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts a to and from a . /// + /// + /// See EF Core value converters for more information. + /// public class PhysicalAddressToStringConverter : ValueConverter { private static readonly ConverterMappingHints _defaultHints = new(size: 20); @@ -17,6 +20,9 @@ public class PhysicalAddressToStringConverter : ValueConverter /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public PhysicalAddressToStringConverter() : this(null) { @@ -25,6 +31,9 @@ public PhysicalAddressToStringConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/StringToBoolConverter.cs b/src/EFCore/Storage/ValueConversion/StringToBoolConverter.cs index 051431d2443..44cdcf1dd86 100644 --- a/src/EFCore/Storage/ValueConversion/StringToBoolConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToBoolConverter.cs @@ -8,11 +8,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts strings to and from values. /// + /// + /// See EF Core value converters for more information. + /// public class StringToBoolConverter : ValueConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public StringToBoolConverter() : this(null) { @@ -21,6 +27,9 @@ public StringToBoolConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/StringToBytesConverter.cs b/src/EFCore/Storage/ValueConversion/StringToBytesConverter.cs index 0ef3b786f28..295f4a2a76b 100644 --- a/src/EFCore/Storage/ValueConversion/StringToBytesConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToBytesConverter.cs @@ -8,11 +8,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts strings to and from arrays of bytes. /// + /// + /// See EF Core value converters for more information. + /// public class StringToBytesConverter : ValueConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// The string encoding to use. /// /// Hints that can be used by the to create data types with appropriate diff --git a/src/EFCore/Storage/ValueConversion/StringToCharConverter.cs b/src/EFCore/Storage/ValueConversion/StringToCharConverter.cs index cc85f6279b9..a28887ba256 100644 --- a/src/EFCore/Storage/ValueConversion/StringToCharConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToCharConverter.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts strings to and from values. /// + /// + /// See EF Core value converters for more information. + /// public class StringToCharConverter : StringCharConverter { private static readonly ConverterMappingHints _defaultHints = new(size: 1); @@ -15,6 +18,9 @@ public class StringToCharConverter : StringCharConverter /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// public StringToCharConverter() : this(null) { @@ -23,6 +29,9 @@ public StringToCharConverter() /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/StringToDateTimeConverter.cs b/src/EFCore/Storage/ValueConversion/StringToDateTimeConverter.cs index 387038cd412..70d847f84ea 100644 --- a/src/EFCore/Storage/ValueConversion/StringToDateTimeConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToDateTimeConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts strings to and from values. /// + /// + /// See EF Core value converters for more information. + /// public class StringToDateTimeConverter : StringDateTimeConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public StringToDateTimeConverter() : this(null) { @@ -22,6 +28,9 @@ public StringToDateTimeConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/StringToDateTimeOffsetConverter.cs b/src/EFCore/Storage/ValueConversion/StringToDateTimeOffsetConverter.cs index 280ac875dfc..831fb86e5a1 100644 --- a/src/EFCore/Storage/ValueConversion/StringToDateTimeOffsetConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToDateTimeOffsetConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts strings to and from values. /// + /// + /// See EF Core value converters for more information. + /// public class StringToDateTimeOffsetConverter : StringDateTimeOffsetConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public StringToDateTimeOffsetConverter() : this(null) { @@ -22,6 +28,9 @@ public StringToDateTimeOffsetConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/StringToEnumConverter.cs b/src/EFCore/Storage/ValueConversion/StringToEnumConverter.cs index 7dcfa44370f..005d4814011 100644 --- a/src/EFCore/Storage/ValueConversion/StringToEnumConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToEnumConverter.cs @@ -8,12 +8,18 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts strings to and from enum values. /// + /// + /// See EF Core value converters for more information. + /// public class StringToEnumConverter : StringEnumConverter where TEnum : struct { /// /// Creates a new instance of this converter. This converter does not preserve order. /// + /// + /// See EF Core value converters for more information. + /// public StringToEnumConverter() : this(null) { @@ -22,6 +28,9 @@ public StringToEnumConverter() /// /// Creates a new instance of this converter. This converter does not preserve order. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/StringToGuidConverter.cs b/src/EFCore/Storage/ValueConversion/StringToGuidConverter.cs index 8fa54cafe64..ba1c9bd0b4c 100644 --- a/src/EFCore/Storage/ValueConversion/StringToGuidConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToGuidConverter.cs @@ -10,11 +10,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// Converts strings to and from a using the /// standard "8-4-4-4-12" format./>. /// + /// + /// See EF Core value converters for more information. + /// public class StringToGuidConverter : StringGuidConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public StringToGuidConverter() : this(null) { @@ -23,6 +29,9 @@ public StringToGuidConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/StringToNumberConverter.cs b/src/EFCore/Storage/ValueConversion/StringToNumberConverter.cs index ee2eb15d98a..571a749b4bd 100644 --- a/src/EFCore/Storage/ValueConversion/StringToNumberConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToNumberConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts strings to and from numeric values. /// + /// + /// See EF Core value converters for more information. + /// public class StringToNumberConverter : StringNumberConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public StringToNumberConverter() : this(null) { @@ -21,6 +27,9 @@ public StringToNumberConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/StringToTimeSpanConverter.cs b/src/EFCore/Storage/ValueConversion/StringToTimeSpanConverter.cs index f6e4cf8b079..84266816022 100644 --- a/src/EFCore/Storage/ValueConversion/StringToTimeSpanConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToTimeSpanConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts strings to and from values. /// + /// + /// See EF Core value converters for more information. + /// public class StringToTimeSpanConverter : StringTimeSpanConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public StringToTimeSpanConverter() : this(null) { @@ -22,6 +28,9 @@ public StringToTimeSpanConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/StringToUriConverter.cs b/src/EFCore/Storage/ValueConversion/StringToUriConverter.cs index b6cfd6a65b0..22978bbaa57 100644 --- a/src/EFCore/Storage/ValueConversion/StringToUriConverter.cs +++ b/src/EFCore/Storage/ValueConversion/StringToUriConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts strings to and from values. /// + /// + /// See EF Core value converters for more information. + /// public class StringToUriConverter : StringUriConverter { /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// public StringToUriConverter() : this(null) { @@ -22,6 +28,9 @@ public StringToUriConverter() /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/TimeSpanToStringConverter.cs b/src/EFCore/Storage/ValueConversion/TimeSpanToStringConverter.cs index 899717ea6be..168d69d3cf5 100644 --- a/src/EFCore/Storage/ValueConversion/TimeSpanToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/TimeSpanToStringConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts to and from strings. /// + /// + /// See EF Core value converters for more information. + /// public class TimeSpanToStringConverter : StringTimeSpanConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public TimeSpanToStringConverter() : this(null) { @@ -22,6 +28,9 @@ public TimeSpanToStringConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/TimeSpanToTicksConverter.cs b/src/EFCore/Storage/ValueConversion/TimeSpanToTicksConverter.cs index a0442e41190..82bea03f410 100644 --- a/src/EFCore/Storage/ValueConversion/TimeSpanToTicksConverter.cs +++ b/src/EFCore/Storage/ValueConversion/TimeSpanToTicksConverter.cs @@ -8,11 +8,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts to and . /// + /// + /// See EF Core value converters for more information. + /// public class TimeSpanToTicksConverter : ValueConverter { /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// public TimeSpanToTicksConverter() : this(null) { @@ -21,6 +27,9 @@ public TimeSpanToTicksConverter() /// /// Creates a new instance of this converter. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/UriToStringConverter.cs b/src/EFCore/Storage/ValueConversion/UriToStringConverter.cs index 6824a0407e1..88fb3550d34 100644 --- a/src/EFCore/Storage/ValueConversion/UriToStringConverter.cs +++ b/src/EFCore/Storage/ValueConversion/UriToStringConverter.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Converts a to and from a . /// + /// + /// See EF Core value converters for more information. + /// public class UriToStringConverter : StringUriConverter { /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// public UriToStringConverter() : this(null) { @@ -22,6 +28,9 @@ public UriToStringConverter() /// /// Creates a new instance of this converter. This converter preserves order. /// + /// + /// See EF Core value converters for more information. + /// /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. diff --git a/src/EFCore/Storage/ValueConversion/ValueConverter.cs b/src/EFCore/Storage/ValueConversion/ValueConverter.cs index d6330b23c3b..bdd11fcc564 100644 --- a/src/EFCore/Storage/ValueConversion/ValueConverter.cs +++ b/src/EFCore/Storage/ValueConversion/ValueConverter.cs @@ -15,11 +15,17 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// Defines conversions from an object of one type in a model to an object of the same or /// different type in the store. /// + /// + /// See EF Core value converters for more information. + /// public abstract class ValueConverter { /// /// Initializes a new instance of the class. /// + /// + /// See EF Core value converters for more information. + /// /// /// The expression to convert objects when writing data to the store, /// exactly as supplied and may not handle @@ -45,6 +51,9 @@ protected ValueConverter( /// /// Initializes a new instance of the class. /// + /// + /// See EF Core value converters for more information. + /// /// /// The expression to convert objects when writing data to the store, /// exactly as supplied and may not handle @@ -82,12 +91,18 @@ protected ValueConverter( /// Gets the function to convert objects when writing data to the store, /// setup to handle nulls, boxing, and non-exact matches of simple types. /// + /// + /// See EF Core value converters for more information. + /// public abstract Func ConvertToProvider { get; } /// /// Gets the function to convert objects when reading data from the store, /// setup to handle nulls, boxing, and non-exact matches of simple types. /// + /// + /// See EF Core value converters for more information. + /// public abstract Func ConvertFromProvider { get; } /// @@ -95,6 +110,9 @@ protected ValueConverter( /// exactly as supplied and may not handle /// nulls, boxing, and non-exact matches of simple types. /// + /// + /// See EF Core value converters for more information. + /// public virtual LambdaExpression ConvertToProviderExpression { get; } /// @@ -102,22 +120,34 @@ protected ValueConverter( /// exactly as supplied and may not handle /// nulls, boxing, and non-exact matches of simple types. /// + /// + /// See EF Core value converters for more information. + /// public virtual LambdaExpression ConvertFromProviderExpression { get; } /// /// The CLR type used in the EF model. /// + /// + /// See EF Core value converters for more information. + /// public abstract Type ModelClrType { get; } /// /// The CLR type used when reading and writing from the store. /// + /// + /// See EF Core value converters for more information. + /// public abstract Type ProviderClrType { get; } /// /// Hints that can be used by the to create data types with appropriate /// facets for the converted data. /// + /// + /// See EF Core value converters for more information. + /// public virtual ConverterMappingHints? MappingHints { get; } /// @@ -130,6 +160,9 @@ protected ValueConverter( /// a primary key) can be used for correlated nullable properties, such as any corresponding foreign key properties. /// /// + /// + /// See EF Core value converters for more information. + /// public virtual bool ConvertsNulls { get; } /// @@ -164,6 +197,9 @@ protected static Type CheckTypeSupported( /// Composes another instance with this one such that /// the result of the first conversion is used as the input to the second conversion. /// + /// + /// See EF Core value converters for more information. + /// /// The second converter. /// The composed converter. public virtual ValueConverter ComposeWith( diff --git a/src/EFCore/Storage/ValueConversion/ValueConverterInfo.cs b/src/EFCore/Storage/ValueConversion/ValueConverterInfo.cs index 54136c83aec..65df6e1de7d 100644 --- a/src/EFCore/Storage/ValueConversion/ValueConverterInfo.cs +++ b/src/EFCore/Storage/ValueConversion/ValueConverterInfo.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// Contains information on an available including a factory to /// create an instance. /// + /// + /// See EF Core value converters for more information. + /// public readonly struct ValueConverterInfo { private readonly Func _factory; @@ -17,6 +20,9 @@ public readonly struct ValueConverterInfo /// /// Creates a new instance. /// + /// + /// See EF Core value converters for more information. + /// /// The CLR type used in the EF model. /// The CLR type used when reading and writing from the database provider. /// A factory to create the converter, if needed. diff --git a/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs b/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs index 327cefec335..1d5f9e4cd06 100644 --- a/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs +++ b/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs @@ -25,6 +25,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// This service cannot depend on services registered as . /// /// + /// + /// See EF Core value converters for more information. + /// public class ValueConverterSelector : IValueConverterSelector { private readonly ConcurrentDictionary<(Type ModelClrType, Type ProviderClrType), ValueConverterInfo> _converters = new(); diff --git a/src/EFCore/Storage/ValueConversion/ValueConverter`.cs b/src/EFCore/Storage/ValueConversion/ValueConverter`.cs index cb0c6186a00..be441214405 100644 --- a/src/EFCore/Storage/ValueConversion/ValueConverter`.cs +++ b/src/EFCore/Storage/ValueConversion/ValueConverter`.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// Defines conversions from an object of one type in a model to an object of the same or /// different type in the store. /// + /// + /// See EF Core value converters for more information. + /// public class ValueConverter : ValueConverter { private Func? _convertToProvider; @@ -19,6 +22,9 @@ public class ValueConverter : ValueConverter /// /// Initializes a new instance of the class. /// + /// + /// See EF Core value converters for more information. + /// /// An expression to convert objects when writing data to the store. /// An expression to convert objects when reading data from the store. /// @@ -36,6 +42,9 @@ public ValueConverter( /// /// Initializes a new instance of the class. /// + /// + /// See EF Core value converters for more information. + /// /// An expression to convert objects when writing data to the store. /// An expression to convert objects when reading data from the store. /// @@ -81,6 +90,9 @@ private static T Sanitize(object value) /// Gets the function to convert objects when writing data to the store, /// setup to handle nulls, boxing, and non-exact matches of simple types. /// + /// + /// See EF Core value converters for more information. + /// public override Func ConvertToProvider => NonCapturingLazyInitializer.EnsureInitialized( ref _convertToProvider, this, static c => SanitizeConverter(c.ConvertToProviderExpression, c.ConvertsNulls)); @@ -89,6 +101,9 @@ private static T Sanitize(object value) /// Gets the function to convert objects when reading data from the store, /// setup to handle nulls, boxing, and non-exact matches of simple types. /// + /// + /// See EF Core value converters for more information. + /// public override Func ConvertFromProvider => NonCapturingLazyInitializer.EnsureInitialized( ref _convertFromProvider, this, static c => SanitizeConverter(c.ConvertFromProviderExpression, c.ConvertsNulls)); @@ -98,6 +113,9 @@ private static T Sanitize(object value) /// exactly as supplied and may not handle /// nulls, boxing, and non-exact matches of simple types. /// + /// + /// See EF Core value converters for more information. + /// public new virtual Expression> ConvertToProviderExpression => (Expression>)base.ConvertToProviderExpression; @@ -106,18 +124,27 @@ private static T Sanitize(object value) /// exactly as supplied and may not handle /// nulls, boxing, and non-exact matches of simple types. /// + /// + /// See EF Core value converters for more information. + /// public new virtual Expression> ConvertFromProviderExpression => (Expression>)base.ConvertFromProviderExpression; /// /// The CLR type used in the EF model. /// + /// + /// See EF Core value converters for more information. + /// public override Type ModelClrType => typeof(TModel); /// /// The CLR type used when reading and writing from the store. /// + /// + /// See EF Core value converters for more information. + /// public override Type ProviderClrType => typeof(TProvider); } diff --git a/src/EFCore/Update/IUpdateAdapter.cs b/src/EFCore/Update/IUpdateAdapter.cs index 453e1f2c0e7..fe9cae6579f 100644 --- a/src/EFCore/Update/IUpdateAdapter.cs +++ b/src/EFCore/Update/IUpdateAdapter.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IUpdateAdapter { /// diff --git a/src/EFCore/Update/IUpdateAdapterFactory.cs b/src/EFCore/Update/IUpdateAdapterFactory.cs index ccedce90cb2..393d77f928b 100644 --- a/src/EFCore/Update/IUpdateAdapterFactory.cs +++ b/src/EFCore/Update/IUpdateAdapterFactory.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IUpdateAdapterFactory { /// diff --git a/src/EFCore/Update/IUpdateEntry.cs b/src/EFCore/Update/IUpdateEntry.cs index 5908299ca10..1637442ab46 100644 --- a/src/EFCore/Update/IUpdateEntry.cs +++ b/src/EFCore/Update/IUpdateEntry.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IUpdateEntry { /// diff --git a/src/EFCore/Update/UpdateEntryExtensions.cs b/src/EFCore/Update/UpdateEntryExtensions.cs index 1ae84b8ec96..52f5701c4f7 100644 --- a/src/EFCore/Update/UpdateEntryExtensions.cs +++ b/src/EFCore/Update/UpdateEntryExtensions.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// /// Extension methods for . /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public static class UpdateEntryExtensions { /// @@ -51,6 +55,9 @@ public static class UpdateEntryExtensions /// It is designed for debugging only and may change arbitrarily between releases. /// /// + /// + /// See EF Core debug views for more information. + /// /// The entry. /// Options for generating the string. /// The number of indent spaces to use before each new line. diff --git a/src/EFCore/ValueGeneration/BinaryValueGenerator.cs b/src/EFCore/ValueGeneration/BinaryValueGenerator.cs index f436ce4bc45..294e3205db1 100644 --- a/src/EFCore/ValueGeneration/BinaryValueGenerator.cs +++ b/src/EFCore/ValueGeneration/BinaryValueGenerator.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// Generates an array bytes from . /// The generated values are non-temporary, meaning they will be saved to the database. /// + /// + /// See EF Core value generation for more information. + /// public class BinaryValueGenerator : ValueGenerator { /// diff --git a/src/EFCore/ValueGeneration/DiscriminatorValueGeneratorFactory.cs b/src/EFCore/ValueGeneration/DiscriminatorValueGeneratorFactory.cs index 27ad2cae737..5a28fe25502 100644 --- a/src/EFCore/ValueGeneration/DiscriminatorValueGeneratorFactory.cs +++ b/src/EFCore/ValueGeneration/DiscriminatorValueGeneratorFactory.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// A factory that creates value generators for the discriminator property that always outputs /// the discriminator value for the given entity type. /// + /// + /// See EF Core value generation for more information. + /// public class DiscriminatorValueGeneratorFactory : ValueGeneratorFactory { /// diff --git a/src/EFCore/ValueGeneration/GuidValueGenerator.cs b/src/EFCore/ValueGeneration/GuidValueGenerator.cs index 3f75971be94..72f34b8d19b 100644 --- a/src/EFCore/ValueGeneration/GuidValueGenerator.cs +++ b/src/EFCore/ValueGeneration/GuidValueGenerator.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// Generates values using . /// The generated values are non-temporary, meaning they will be saved to the database. /// + /// + /// See EF Core value generation for more information. + /// public class GuidValueGenerator : ValueGenerator { /// diff --git a/src/EFCore/ValueGeneration/HiLoValueGenerator.cs b/src/EFCore/ValueGeneration/HiLoValueGenerator.cs index 50dfee136b2..56add2a621e 100644 --- a/src/EFCore/ValueGeneration/HiLoValueGenerator.cs +++ b/src/EFCore/ValueGeneration/HiLoValueGenerator.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// a new low value must be fetched from the database. /// /// + /// + /// See EF Core value generation for more information. + /// /// The type of values that are generated. public abstract class HiLoValueGenerator : ValueGenerator { diff --git a/src/EFCore/ValueGeneration/HiLoValueGeneratorState.cs b/src/EFCore/ValueGeneration/HiLoValueGeneratorState.cs index f1deac49cef..43d3b1afbca 100644 --- a/src/EFCore/ValueGeneration/HiLoValueGeneratorState.cs +++ b/src/EFCore/ValueGeneration/HiLoValueGeneratorState.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// /// The thread safe state used by . /// + /// + /// See EF Core value generation for more information. + /// public class HiLoValueGeneratorState : IDisposable { private readonly SemaphoreSlim _semaphoreSlim = new(1); diff --git a/src/EFCore/ValueGeneration/IValueGeneratorCache.cs b/src/EFCore/ValueGeneration/IValueGeneratorCache.cs index 2df478eccee..424459ed8b7 100644 --- a/src/EFCore/ValueGeneration/IValueGeneratorCache.cs +++ b/src/EFCore/ValueGeneration/IValueGeneratorCache.cs @@ -21,6 +21,10 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IValueGeneratorCache { /// diff --git a/src/EFCore/ValueGeneration/IValueGeneratorSelector.cs b/src/EFCore/ValueGeneration/IValueGeneratorSelector.cs index ae06c1522df..e3f670ee385 100644 --- a/src/EFCore/ValueGeneration/IValueGeneratorSelector.cs +++ b/src/EFCore/ValueGeneration/IValueGeneratorSelector.cs @@ -21,6 +21,10 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IValueGeneratorSelector { /// diff --git a/src/EFCore/ValueGeneration/SequentialGuidValueGenerator.cs b/src/EFCore/ValueGeneration/SequentialGuidValueGenerator.cs index fb0a8d23939..3aa4b47b7f1 100644 --- a/src/EFCore/ValueGeneration/SequentialGuidValueGenerator.cs +++ b/src/EFCore/ValueGeneration/SequentialGuidValueGenerator.cs @@ -22,6 +22,9 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// The generated values are non-temporary, meaning they will be saved to the database. /// /// + /// + /// See EF Core value generation for more information. + /// public class SequentialGuidValueGenerator : ValueGenerator { private long _counter = DateTime.UtcNow.Ticks; diff --git a/src/EFCore/ValueGeneration/StringValueGenerator.cs b/src/EFCore/ValueGeneration/StringValueGenerator.cs index 828e87b222c..c786c64a818 100644 --- a/src/EFCore/ValueGeneration/StringValueGenerator.cs +++ b/src/EFCore/ValueGeneration/StringValueGenerator.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// Generates values using a string representation of . /// The generated values are non-temporary, meaning they will be saved to the database. /// + /// + /// See EF Core value generation for more information. + /// public class StringValueGenerator : ValueGenerator { /// diff --git a/src/EFCore/ValueGeneration/TemporaryGuidValueGenerator.cs b/src/EFCore/ValueGeneration/TemporaryGuidValueGenerator.cs index 8f69098c12a..d4f292cd0d6 100644 --- a/src/EFCore/ValueGeneration/TemporaryGuidValueGenerator.cs +++ b/src/EFCore/ValueGeneration/TemporaryGuidValueGenerator.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// The generated values are temporary, meaning they will be replaced by database /// generated values when the entity is saved. /// + /// + /// See EF Core value generation for more information. + /// public class TemporaryGuidValueGenerator : GuidValueGenerator { /// diff --git a/src/EFCore/ValueGeneration/TemporaryNumberValueGeneratorFactory.cs b/src/EFCore/ValueGeneration/TemporaryNumberValueGeneratorFactory.cs index a3a699fca14..63f74f3fa64 100644 --- a/src/EFCore/ValueGeneration/TemporaryNumberValueGeneratorFactory.cs +++ b/src/EFCore/ValueGeneration/TemporaryNumberValueGeneratorFactory.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// , , /// /// + /// + /// See EF Core value generation for more information. + /// public class TemporaryNumberValueGeneratorFactory : ValueGeneratorFactory { /// diff --git a/src/EFCore/ValueGeneration/ValueGenerator.cs b/src/EFCore/ValueGeneration/ValueGenerator.cs index c42e41c2745..335018f0c53 100644 --- a/src/EFCore/ValueGeneration/ValueGenerator.cs +++ b/src/EFCore/ValueGeneration/ValueGenerator.cs @@ -11,11 +11,17 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// /// Generates values for properties when an entity is added to a context. /// + /// + /// See EF Core value generation for more information. + /// public abstract class ValueGenerator { /// /// Gets a value to be assigned to a property. /// + /// + /// See EF Core value generation for more information. + /// /// The change tracking entry of the entity for which the value is being generated. /// The value to be assigned to a property. public virtual object? Next(EntityEntry entry) @@ -24,6 +30,9 @@ public abstract class ValueGenerator /// /// Template method to be overridden by implementations to perform value generation. /// + /// + /// See EF Core value generation for more information. + /// /// The change tracking entry of the entity for which the value is being generated. /// The generated value. protected abstract object? NextValue(EntityEntry entry); @@ -31,6 +40,9 @@ public abstract class ValueGenerator /// /// Gets a value to be assigned to a property. /// + /// + /// See EF Core value generation for more information. + /// /// The change tracking entry of the entity for which the value is being generated. /// A to observe while waiting for the task to complete. /// The value to be assigned to a property. @@ -43,6 +55,9 @@ public abstract class ValueGenerator /// /// Template method to be overridden by implementations to perform value generation. /// + /// + /// See EF Core value generation for more information. + /// /// The change tracking entry of the entity for which the value is being generated. /// A to observe while waiting for the task to complete. /// The generated value. @@ -65,6 +80,9 @@ public abstract class ValueGenerator /// key which are saved to the database. /// /// + /// + /// See EF Core value generation for more information. + /// public abstract bool GeneratesTemporaryValues { get; } /// @@ -73,6 +91,9 @@ public abstract class ValueGenerator /// previously. For example, discriminator values generated for a TPH hierarchy are stable. Stable values will never /// be marked as unknown. /// + /// + /// See EF Core value generation for more information. + /// public virtual bool GeneratesStableValues => false; } diff --git a/src/EFCore/ValueGeneration/ValueGeneratorCache.cs b/src/EFCore/ValueGeneration/ValueGeneratorCache.cs index c629df6ed0c..5c9dc8c8ede 100644 --- a/src/EFCore/ValueGeneration/ValueGeneratorCache.cs +++ b/src/EFCore/ValueGeneration/ValueGeneratorCache.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ValueGeneratorCache : IValueGeneratorCache { /// diff --git a/src/EFCore/ValueGeneration/ValueGeneratorFactory.cs b/src/EFCore/ValueGeneration/ValueGeneratorFactory.cs index af4c6403d49..c867d471c7c 100644 --- a/src/EFCore/ValueGeneration/ValueGeneratorFactory.cs +++ b/src/EFCore/ValueGeneration/ValueGeneratorFactory.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// /// Base class for factories that create value generators. /// + /// + /// See EF Core value generation for more information. + /// public abstract class ValueGeneratorFactory { /// /// Creates a new value generator. /// + /// + /// See EF Core value generation for more information. + /// /// The property to create the value generator for. /// The newly created value generator. [Obsolete("Use the overload with most parameters")] @@ -23,6 +29,9 @@ public virtual ValueGenerator Create(IProperty property) /// /// Creates a new value generator. /// + /// + /// See EF Core value generation for more information. + /// /// The property to create the value generator for. /// The entity type for which the value generator will be used. /// The newly created value generator. diff --git a/src/EFCore/ValueGeneration/ValueGeneratorSelector.cs b/src/EFCore/ValueGeneration/ValueGeneratorSelector.cs index 37d1426da86..611b7df6e68 100644 --- a/src/EFCore/ValueGeneration/ValueGeneratorSelector.cs +++ b/src/EFCore/ValueGeneration/ValueGeneratorSelector.cs @@ -26,6 +26,10 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ValueGeneratorSelector : IValueGeneratorSelector { /// diff --git a/src/EFCore/ValueGeneration/ValueGenerator`.cs b/src/EFCore/ValueGeneration/ValueGenerator`.cs index 6d517a7b42f..5781fb754b9 100644 --- a/src/EFCore/ValueGeneration/ValueGenerator`.cs +++ b/src/EFCore/ValueGeneration/ValueGenerator`.cs @@ -11,11 +11,17 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// /// Generates values for properties when an entity is added to a context. /// + /// + /// See EF Core value generation for more information. + /// public abstract class ValueGenerator : ValueGenerator { /// /// Template method to be overridden by implementations to perform value generation. /// + /// + /// See EF Core value generation for more information. + /// /// The change tracking entry of the entity for which the value is being generated. /// The generated value. public new abstract TValue Next(EntityEntry entry); @@ -23,6 +29,9 @@ public abstract class ValueGenerator : ValueGenerator /// /// Template method to be overridden by implementations to perform value generation. /// + /// + /// See EF Core value generation for more information. + /// /// The change tracking entry of the entity for which the value is being generated. /// A to observe while waiting for the task to complete. /// The generated value. @@ -35,6 +44,9 @@ public abstract class ValueGenerator : ValueGenerator /// /// Gets a value to be assigned to a property. /// + /// + /// See EF Core value generation for more information. + /// /// The change tracking entry of the entity for which the value is being generated. /// The value to be assigned to a property. protected override object? NextValue(EntityEntry entry) @@ -43,6 +55,9 @@ public abstract class ValueGenerator : ValueGenerator /// /// Gets a value to be assigned to a property. /// + /// + /// See EF Core value generation for more information. + /// /// The change tracking entry of the entity for which the value is being generated. /// A to observe while waiting for the task to complete. /// The value to be assigned to a property. From 50daaa108ef4fd31e40c7bad7f65100be0d6cf7b Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Fri, 10 Sep 2021 06:11:24 +0100 Subject: [PATCH 081/346] Delete optional orphans when foreign key value is set to null (#25957) Fixes #25360 This is a case where an optional relationship is configured with delete orphans behavior. Since the relationship is optional it means that the FK value can be explicitly set to null. (This is not possible for required relationships, which is the usual case for delete orphans.) In this case the navigation fixer was not triggering behavior in the state manager to process deleting orphans. --- .../Internal/InternalEntityEntry.cs | 57 ++++++----- .../Internal/NavigationFixer.cs | 7 ++ .../ChangeTracking/ChangeTrackerTest.cs | 96 +++++++++++++------ 3 files changed, 109 insertions(+), 51 deletions(-) diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index 8b67ffc8015..29896d0e998 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -1257,28 +1257,7 @@ private void SetProperty( { if (value == null) { - if (EntityState != EntityState.Deleted - && EntityState != EntityState.Detached) - { - _stateData.FlagProperty(propertyIndex, PropertyFlag.Null, isFlagged: true); - - if (setModified) - { - SetPropertyModified( - asProperty, changeState: true, isModified: true, - isConceptualNull: true); - } - - if (!isCascadeDelete - && StateManager.DeleteOrphansTiming == CascadeTiming.Immediate) - { - HandleConceptualNulls( - StateManager.SensitiveLoggingEnabled, - force: false, - isCascadeDelete: false); - } - } - + HandleNullForeignKey(asProperty, setModified, isCascadeDelete); writeValue = false; } else @@ -1377,6 +1356,40 @@ private void SetProperty( } } + /// + /// 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 HandleNullForeignKey( + IProperty property, + bool setModified = false, + bool isCascadeDelete = false) + { + if (EntityState != EntityState.Deleted + && EntityState != EntityState.Detached) + { + _stateData.FlagProperty(property.GetIndex(), PropertyFlag.Null, isFlagged: true); + + if (setModified) + { + SetPropertyModified( + property, changeState: true, isModified: true, + isConceptualNull: true); + } + + if (!isCascadeDelete + && StateManager.DeleteOrphansTiming == CascadeTiming.Immediate) + { + HandleConceptualNulls( + StateManager.SensitiveLoggingEnabled, + force: false, + isCascadeDelete: false); + } + } + } + private static Func ValuesEqualFunc(IProperty property) { var comparer = property.GetValueComparer(); diff --git a/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs b/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs index e2ea9c3f678..0efa9a2f671 100644 --- a/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs +++ b/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs @@ -495,6 +495,13 @@ var targetDependentEntry } } + if (newValue == null + && (foreignKey.DeleteBehavior == DeleteBehavior.Cascade + || foreignKey.DeleteBehavior == DeleteBehavior.ClientCascade)) + { + entry.HandleNullForeignKey(property); + } + stateManager.UpdateDependentMap(entry, foreignKey); } diff --git a/test/EFCore.Tests/ChangeTracking/ChangeTrackerTest.cs b/test/EFCore.Tests/ChangeTracking/ChangeTrackerTest.cs index 6542f9e97ef..0d4b7b87658 100644 --- a/test/EFCore.Tests/ChangeTracking/ChangeTrackerTest.cs +++ b/test/EFCore.Tests/ChangeTracking/ChangeTrackerTest.cs @@ -1923,15 +1923,34 @@ public void Dependent_FKs_are_not_nulled_when_principal_is_detached(bool delayCa } } - [ConditionalTheory] // Issue #16546 - [InlineData(false)] - [InlineData(true)] - public void Optional_relationship_with_cascade_still_cascades(bool delayCascade) + [ConditionalTheory] // Issues #16546 #25360 + [InlineData(false, false, false, true, false)] + [InlineData(true, false, false, true, false)] + [InlineData(false, true, false, true, false)] + [InlineData(true, true, false, true, false)] + [InlineData(false, false, true, true, false)] + [InlineData(true, false, true, true, false)] + [InlineData(false, true, false, false, true)] + [InlineData(true, true, false, false, true)] + [InlineData(false, false, true, false, true)] + [InlineData(true, false, true, false, true)] + [InlineData(false, true, false, true, true)] + [InlineData(true, true, false, true, true)] + [InlineData(false, false, true, true, true)] + [InlineData(true, false, true, true, true)] + public void Optional_relationship_with_cascade_still_cascades( + bool delayCascade, + bool setProperty, + bool setCurrentValue, + bool useForeignKey, + bool useNavigation) { Kontainer detachedContainer; - var databaseName = "K" + delayCascade; - using (var context = new KontainerContext(databaseName)) + using (var context = new KontainerContext()) { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + context.Add( new Kontainer { @@ -1949,51 +1968,77 @@ public void Optional_relationship_with_cascade_still_cascades(bool delayCascade) .Single(); } - using (var context = new KontainerContext(databaseName)) + using (var context = new KontainerContext()) { var attachedContainer = context.Set() .Include(container => container.Rooms) .ThenInclude(room => room.Troduct) .Single(); + var attachedRoom = attachedContainer.Rooms.Single(); + var attachedTroduct = attachedRoom.Troduct; + Assert.Equal(3, context.ChangeTracker.Entries().Count()); Assert.Equal(EntityState.Unchanged, context.Entry(attachedContainer).State); - Assert.Equal(EntityState.Unchanged, context.Entry(attachedContainer.Rooms.Single()).State); - Assert.Equal(EntityState.Unchanged, context.Entry(attachedContainer.Rooms.Single().Troduct).State); - - var detachedRoom = detachedContainer.Rooms.Single(); - detachedRoom.Troduct = null; - detachedRoom.TroductId = null; - - var attachedRoom = attachedContainer.Rooms.Single(); + Assert.Equal(EntityState.Unchanged, context.Entry(attachedRoom).State); + Assert.Equal(EntityState.Unchanged, context.Entry(attachedTroduct).State); if (delayCascade) { context.ChangeTracker.DeleteOrphansTiming = CascadeTiming.OnSaveChanges; } - context.Entry(attachedRoom).CurrentValues.SetValues(detachedRoom); + if (setProperty) + { + if (useForeignKey) + { + attachedRoom.TroductId = null; + } + + if (useNavigation) + { + attachedRoom.Troduct = null; + } + } + else if (setCurrentValue) + { + if (useForeignKey) + { + context.Entry(attachedRoom).Property(e => e.TroductId).CurrentValue = null; + } + + if (useNavigation) + { + context.Entry(attachedRoom).Reference(e => e.Troduct).CurrentValue = null; + } + } + else + { + var detachedRoom = detachedContainer.Rooms.Single(); + detachedRoom.TroductId = null; + context.Entry(attachedRoom).CurrentValues.SetValues(detachedRoom); + } Assert.Equal(3, context.ChangeTracker.Entries().Count()); Assert.Equal(EntityState.Unchanged, context.Entry(attachedContainer).State); - Assert.Equal(EntityState.Unchanged, context.Entry(attachedContainer.Rooms.Single().Troduct).State); + Assert.Equal(EntityState.Unchanged, context.Entry(attachedTroduct).State); if (delayCascade) { - Assert.Equal(EntityState.Modified, context.Entry(attachedContainer.Rooms.Single()).State); + Assert.Equal(EntityState.Modified, context.Entry(attachedRoom).State); } else { // Deleted because FK with cascade has been set to null - Assert.Equal(EntityState.Deleted, context.Entry(attachedContainer.Rooms.Single()).State); + Assert.Equal(EntityState.Deleted, context.Entry(attachedRoom).State); } context.ChangeTracker.CascadeChanges(); Assert.Equal(3, context.ChangeTracker.Entries().Count()); Assert.Equal(EntityState.Unchanged, context.Entry(attachedContainer).State); - Assert.Equal(EntityState.Unchanged, context.Entry(attachedContainer.Rooms.Single().Troduct).State); - Assert.Equal(EntityState.Deleted, context.Entry(attachedContainer.Rooms.Single()).State); + Assert.Equal(EntityState.Unchanged, context.Entry(attachedTroduct).State); + Assert.Equal(EntityState.Deleted, context.Entry(attachedRoom).State); context.SaveChanges(); } @@ -2025,13 +2070,6 @@ private class Troduct private class KontainerContext : DbContext { - private readonly string _databaseName; - - public KontainerContext(string databaseName) - { - _databaseName = databaseName; - } - protected internal override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() @@ -2045,7 +2083,7 @@ protected internal override void OnModelCreating(ModelBuilder modelBuilder) protected internal override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder .UseInternalServiceProvider(InMemoryFixture.DefaultServiceProvider) - .UseInMemoryDatabase(_databaseName); + .UseInMemoryDatabase(nameof(KontainerContext)); } [ConditionalTheory] From b5602c665740e46ab69b534a087d03c61fc5768a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:02:16 +0000 Subject: [PATCH 082/346] Update dependencies from https://github.com/dotnet/runtime build 20210910.8 (#25965) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1d49d55450a..ac629340199 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee - + https://github.com/dotnet/runtime - 614c782790eceb2f4247e6e380db548a58b55a69 + 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee diff --git a/eng/Versions.props b/eng/Versions.props index 8255e9ce8bd..dbf3792ea86 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 - 6.0.0-rc.2.21459.18 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.8 3.7.0 From 647a6e1fa22022ccdd7b9d1740dd3999be6ee104 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Fri, 10 Sep 2021 23:06:17 +0200 Subject: [PATCH 083/346] Fix indentation when scaffolding with no namespace (#25964) Fixes #25403 --- .../Internal/CSharpDbContextGenerator.cs | 12 +--- .../Infrastructure/IndentedStringBuilder.cs | 23 +++++++ .../Internal/CSharpDbContextGeneratorTest.cs | 69 +++++++++++++------ 3 files changed, 75 insertions(+), 29 deletions(-) diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs index a651ba5fa0b..c0aacc2a032 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs @@ -261,15 +261,9 @@ protected virtual void GenerateOnConfiguring( { if (!suppressConnectionStringWarning) { - _builder.DecrementIndent() - .DecrementIndent() - .DecrementIndent() - .DecrementIndent() - .AppendLine("#warning " + DesignStrings.SensitiveInformationWarning) - .IncrementIndent() - .IncrementIndent() - .IncrementIndent() - .IncrementIndent(); + using var _ = _builder.SuspendIndent(); + + _builder.AppendLine("#warning " + DesignStrings.SensitiveInformationWarning); } var useProviderCall = _providerConfigurationCodeGenerator.GenerateUseProvider( diff --git a/src/EFCore/Infrastructure/IndentedStringBuilder.cs b/src/EFCore/Infrastructure/IndentedStringBuilder.cs index 24f26da35c8..6852e89ba5d 100644 --- a/src/EFCore/Infrastructure/IndentedStringBuilder.cs +++ b/src/EFCore/Infrastructure/IndentedStringBuilder.cs @@ -215,6 +215,13 @@ public virtual IndentedStringBuilder DecrementIndent() public virtual IDisposable Indent() => new Indenter(this); + /// + /// Temporarily disables all indentation. Restores the original indentation when the returned object is disposed. + /// + /// An object that restores the original indentation when disposed. + public virtual IDisposable SuspendIndent() + => new IndentSuspender(this); + /// /// Returns the built string. /// @@ -246,5 +253,21 @@ public Indenter(IndentedStringBuilder stringBuilder) public void Dispose() => _stringBuilder.DecrementIndent(); } + + private sealed class IndentSuspender : IDisposable + { + private readonly IndentedStringBuilder _stringBuilder; + private readonly byte _indent; + + public IndentSuspender(IndentedStringBuilder stringBuilder) + { + _stringBuilder = stringBuilder; + _indent = _stringBuilder._indent; + _stringBuilder._indent = 0; + } + + public void Dispose() + => _stringBuilder._indent = _indent; + } } } diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs index f5b92abf2b6..78780767d07 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs @@ -56,9 +56,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { -#warning " - + DesignStrings.SensitiveInformationWarning - + @" +#warning " + DesignStrings.SensitiveInformationWarning + @" optionsBuilder.UseSqlServer(""Initial Catalog=TestDatabase""); } } @@ -639,9 +637,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { -#warning " - + DesignStrings.SensitiveInformationWarning - + @" +#warning " + DesignStrings.SensitiveInformationWarning + @" optionsBuilder.UseSqlServer(""Initial Catalog=TestDatabase""); } } @@ -721,9 +717,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { -#warning " - + DesignStrings.SensitiveInformationWarning - + @" +#warning " + DesignStrings.SensitiveInformationWarning + @" optionsBuilder.UseSqlServer(""Initial Catalog=TestDatabase""); } } @@ -806,9 +800,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { -#warning " - + DesignStrings.SensitiveInformationWarning - + @" +#warning " + DesignStrings.SensitiveInformationWarning + @" optionsBuilder.UseSqlServer(""Initial Catalog=TestDatabase""); } } @@ -887,9 +879,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { -#warning " - + DesignStrings.SensitiveInformationWarning - + @" +#warning " + DesignStrings.SensitiveInformationWarning + @" optionsBuilder.UseSqlServer(""Initial Catalog=TestDatabase""); } } @@ -941,13 +931,52 @@ public void Global_namespace_works() { Test( modelBuilder => modelBuilder.Entity("MyEntity"), - new ModelCodeGenerationOptions - { - ModelNamespace = string.Empty - }, + new ModelCodeGenerationOptions { ModelNamespace = string.Empty }, code => { - Assert.DoesNotContain("namespace ", code.ContextFile.Code); + AssertFileContents( + @"using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; + +public partial class TestDbContext : DbContext +{ + public TestDbContext() + { + } + + public TestDbContext(DbContextOptions options) + : base(options) + { + } + + public virtual DbSet MyEntity { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { +#warning " + DesignStrings.SensitiveInformationWarning + @" + optionsBuilder.UseSqlServer(""Initial Catalog=TestDatabase""); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.HasNoKey(); + }); + + OnModelCreatingPartial(modelBuilder); + } + + partial void OnModelCreatingPartial(ModelBuilder modelBuilder); +} +", + code.ContextFile); + Assert.DoesNotContain("namespace ", Assert.Single(code.AdditionalFiles).Code); }, model => From 9f863be44153f39f8b32960caa6e5772e863fad3 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Fri, 10 Sep 2021 14:40:03 -0700 Subject: [PATCH 084/346] Make compiled model classes public and supporting classes internal Part of #25812 --- .../CSharpRuntimeModelCodeGenerator.cs | 6 +- .../CSharpRuntimeModelCodeGeneratorTest.cs | 94 +++++++++---------- 2 files changed, 47 insertions(+), 53 deletions(-) diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs index 62655ae9871..667564d3f5e 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs @@ -160,7 +160,7 @@ private string CreateModel( var className = _code.Identifier(contextType.ShortDisplayName()) + ModelSuffix; mainBuilder .Append("[DbContext(typeof(").Append(_code.Reference(contextType)).AppendLine("))]") - .Append("partial class ").Append(className).AppendLine(" : " + nameof(RuntimeModel)) + .Append("public partial class ").Append(className).AppendLine(" : " + nameof(RuntimeModel)) .AppendLine("{"); using (mainBuilder.Indent()) @@ -219,7 +219,7 @@ private string CreateModelBuilder( var className = _code.Identifier(contextType.ShortDisplayName()) + ModelSuffix; mainBuilder - .Append("partial class ").AppendLine(className) + .Append("public partial class ").AppendLine(className) .AppendLine("{"); using (mainBuilder.Indent()) @@ -474,7 +474,7 @@ private string GenerateEntityType(IEntityType entityType, string @namespace, str } mainBuilder - .Append("partial class ").AppendLine(className) + .Append("internal partial class ").AppendLine(className) .AppendLine("{"); using (mainBuilder.Indent()) { diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs index 04f8cb6d0fa..2cc88a9c5ef 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs @@ -35,6 +35,7 @@ using NetTopologySuite.Geometries; using Newtonsoft.Json.Linq; using Xunit; +using static Microsoft.EntityFrameworkCore.Migrations.Design.CSharpMigrationsGeneratorTest; using static Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGeneratorTest; public class GlobalNamespaceContext : Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGeneratorTest.ContextBase @@ -76,7 +77,7 @@ public void Empty_model() namespace TestNamespace { [DbContext(typeof(CSharpRuntimeModelCodeGeneratorTest.EmptyContext))] - partial class EmptyContextModel : RuntimeModel + public partial class EmptyContextModel : RuntimeModel { static EmptyContextModel() { @@ -107,7 +108,7 @@ static EmptyContextModel() namespace TestNamespace { - partial class EmptyContextModel + public partial class EmptyContextModel { partial void Initialize() { @@ -482,7 +483,7 @@ public void Fully_qualified_model() namespace Internal { [DbContext(typeof(DbContext))] - partial class DbContextModel : RuntimeModel + public partial class DbContextModel : RuntimeModel { static DbContextModel() { @@ -513,7 +514,7 @@ static DbContextModel() namespace Internal { - partial class DbContextModel + public partial class DbContextModel { partial void Initialize() { @@ -545,7 +546,7 @@ partial void Initialize() namespace Internal { - partial class IndexEntityType + internal partial class IndexEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { @@ -594,7 +595,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace Internal { - partial class InternalEntityType + internal partial class InternalEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { @@ -643,7 +644,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace Internal { - partial class IdentityUserEntityType + internal partial class IdentityUserEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { @@ -792,7 +793,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace Internal { - partial class IdentityUser0EntityType + internal partial class IdentityUser0EntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { @@ -867,7 +868,7 @@ public void BigModel() namespace TestNamespace { [DbContext(typeof(CSharpRuntimeModelCodeGeneratorTest.BigContext))] - partial class BigContextModel : RuntimeModel + public partial class BigContextModel : RuntimeModel { static BigContextModel() { @@ -897,7 +898,7 @@ static BigContextModel() namespace TestNamespace { - partial class BigContextModel + public partial class BigContextModel { partial void Initialize() { @@ -939,6 +940,7 @@ partial void Initialize() using System.Reflection; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations.Design; using Microsoft.EntityFrameworkCore.Scaffolding.Internal; using Microsoft.EntityFrameworkCore.ValueGeneration; using NetTopologySuite.Geometries; @@ -948,7 +950,7 @@ partial void Initialize() namespace TestNamespace { - partial class DependentBasebyteEntityType + internal partial class DependentBasebyteEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? baseEntityType = null) { @@ -973,7 +975,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? ba var enumDiscriminator = runtimeEntityType.AddProperty( ""EnumDiscriminator"", - typeof(CSharpRuntimeModelCodeGeneratorTest.Discriminator), + typeof(CSharpMigrationsGeneratorTest.Enum1), afterSaveBehavior: PropertySaveBehavior.Throw, valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); enumDiscriminator.AddAnnotation(""SqlServer:ValueGenerationStrategy"", SqlServerValueGenerationStrategy.None); @@ -1038,7 +1040,7 @@ public static RuntimeForeignKey CreateForeignKey2(RuntimeEntityType declaringEnt public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { - runtimeEntityType.AddAnnotation(""DiscriminatorValue"", CSharpRuntimeModelCodeGeneratorTest.Discriminator.Base); + runtimeEntityType.AddAnnotation(""DiscriminatorValue"", CSharpMigrationsGeneratorTest.Enum1.One); runtimeEntityType.AddAnnotation(""Relational:FunctionName"", null); runtimeEntityType.AddAnnotation(""Relational:Schema"", null); runtimeEntityType.AddAnnotation(""Relational:SqlQuery"", null); @@ -1068,7 +1070,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace TestNamespace { - partial class PrincipalBaseEntityType + internal partial class PrincipalBaseEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? baseEntityType = null) { @@ -1180,7 +1182,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace TestNamespace { - partial class OwnedTypeEntityType + internal partial class OwnedTypeEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? baseEntityType = null) { @@ -1270,7 +1272,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace TestNamespace { - partial class OwnedType0EntityType + internal partial class OwnedType0EntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? baseEntityType = null) { @@ -1359,7 +1361,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace TestNamespace { - partial class PrincipalBasePrincipalDerivedDependentBasebyteEntityType + internal partial class PrincipalBasePrincipalDerivedDependentBasebyteEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? baseEntityType = null) { @@ -1462,6 +1464,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) using System; using System.Reflection; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations.Design; using Microsoft.EntityFrameworkCore.Scaffolding.Internal; #pragma warning disable 219, 612, 618 @@ -1469,7 +1472,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace TestNamespace { - partial class DependentDerivedbyteEntityType + internal partial class DependentDerivedbyteEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? baseEntityType = null) { @@ -1502,7 +1505,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? ba public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { - runtimeEntityType.AddAnnotation(""DiscriminatorValue"", CSharpRuntimeModelCodeGeneratorTest.Discriminator.Derived); + runtimeEntityType.AddAnnotation(""DiscriminatorValue"", CSharpMigrationsGeneratorTest.Enum1.Two); runtimeEntityType.AddAnnotation(""Relational:FunctionName"", null); runtimeEntityType.AddAnnotation(""Relational:Schema"", null); runtimeEntityType.AddAnnotation(""Relational:SqlQuery"", null); @@ -1530,7 +1533,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace TestNamespace { - partial class PrincipalDerivedDependentBasebyteEntityType + internal partial class PrincipalDerivedDependentBasebyteEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? baseEntityType = null) { @@ -1948,7 +1951,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var principalDiscriminator = dependentBase.FindDiscriminatorProperty(); Assert.IsType( principalDiscriminator.GetValueGeneratorFactory()(principalDiscriminator, dependentBase)); - Assert.Equal(Discriminator.Base, dependentBase.GetDiscriminatorValue()); + Assert.Equal(Enum1.One, dependentBase.GetDiscriminatorValue()); var dependentBaseForeignKey = dependentBase.GetForeignKeys().Single(fk => fk != dependentForeignKey); var dependentForeignKeyProperty = dependentBaseForeignKey.Properties.Single(); @@ -1956,7 +1959,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) Assert.Equal(new[] { dependentBaseForeignKey, dependentForeignKey }, dependentForeignKeyProperty.GetContainingForeignKeys()); var dependentDerived = dependentBase.GetDerivedTypes().Single(); - Assert.Equal(Discriminator.Derived, dependentDerived.GetDiscriminatorValue()); + Assert.Equal(Enum1.Two, dependentDerived.GetDiscriminatorValue()); Assert.Equal(2, dependentDerived.GetDeclaredProperties().Count()); @@ -2132,9 +2135,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) eb.ToTable("PrincipalDerived"); - eb.HasDiscriminator("EnumDiscriminator") - .HasValue(Discriminator.Base) - .HasValue>(Discriminator.Derived); + eb.HasDiscriminator("EnumDiscriminator") + .HasValue(Enum1.One) + .HasValue>(Enum1.Two); }); modelBuilder.Entity>(eb => @@ -2191,15 +2194,6 @@ public class DependentDerived : DependentBase private string Data { get; set; } } - public enum Discriminator - { - /// - Base, - - /// - Derived - } - public class OwnedType : INotifyPropertyChanged, INotifyPropertyChanging { private EntityFrameworkCore.DbContext _context; @@ -2242,7 +2236,7 @@ public void DbFunctions() namespace TestNamespace { [DbContext(typeof(CSharpRuntimeModelCodeGeneratorTest.DbFunctionContext))] - partial class DbFunctionContextModel : RuntimeModel + public partial class DbFunctionContextModel : RuntimeModel { static DbFunctionContextModel() { @@ -2277,7 +2271,7 @@ static DbFunctionContextModel() namespace TestNamespace { - partial class DbFunctionContextModel + public partial class DbFunctionContextModel { partial void Initialize() { @@ -2413,7 +2407,7 @@ partial void Initialize() namespace TestNamespace { - partial class DataEntityType + internal partial class DataEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { @@ -2461,7 +2455,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) namespace TestNamespace { - partial class ObjectEntityType + internal partial class ObjectEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { @@ -2727,7 +2721,7 @@ public void Sequences() namespace TestNamespace { [DbContext(typeof(CSharpRuntimeModelCodeGeneratorTest.SequencesContext))] - partial class SequencesContextModel : RuntimeModel + public partial class SequencesContextModel : RuntimeModel { static SequencesContextModel() { @@ -2759,7 +2753,7 @@ static SequencesContextModel() namespace TestNamespace { - partial class SequencesContextModel + public partial class SequencesContextModel { partial void Initialize() { @@ -2809,7 +2803,7 @@ partial void Initialize() namespace TestNamespace { - partial class DataEntityType + internal partial class DataEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { @@ -2930,7 +2924,7 @@ public void CheckConstraints() namespace TestNamespace { [DbContext(typeof(CSharpRuntimeModelCodeGeneratorTest.ConstraintsContext))] - partial class ConstraintsContextModel : RuntimeModel + public partial class ConstraintsContextModel : RuntimeModel { static ConstraintsContextModel() { @@ -2961,7 +2955,7 @@ static ConstraintsContextModel() namespace TestNamespace { - partial class ConstraintsContextModel + public partial class ConstraintsContextModel { partial void Initialize() { @@ -2988,7 +2982,7 @@ partial void Initialize() namespace TestNamespace { - partial class DataEntityType + internal partial class DataEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { @@ -3081,7 +3075,7 @@ public void Sqlite() namespace Microsoft.EntityFrameworkCore.Metadata { [DbContext(typeof(CSharpRuntimeModelCodeGeneratorTest.SqliteContext))] - partial class SqliteContextModel : RuntimeModel + public partial class SqliteContextModel : RuntimeModel { static SqliteContextModel() { @@ -3110,7 +3104,7 @@ static SqliteContextModel() namespace Microsoft.EntityFrameworkCore.Metadata { - partial class SqliteContextModel + public partial class SqliteContextModel { partial void Initialize() { @@ -3135,7 +3129,7 @@ partial void Initialize() namespace Microsoft.EntityFrameworkCore.Metadata { - partial class DataEntityType + internal partial class DataEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { @@ -3256,7 +3250,7 @@ public void Cosmos() namespace TestNamespace { [DbContext(typeof(CSharpRuntimeModelCodeGeneratorTest.CosmosContext))] - partial class CosmosContextModel : RuntimeModel + public partial class CosmosContextModel : RuntimeModel { static CosmosContextModel() { @@ -3287,7 +3281,7 @@ static CosmosContextModel() namespace TestNamespace { - partial class CosmosContextModel + public partial class CosmosContextModel { partial void Initialize() { @@ -3315,7 +3309,7 @@ partial void Initialize() namespace TestNamespace { - partial class DataEntityType + internal partial class DataEntityType { public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null) { From 243bce0bc6f60beba4cf8fff110d135d3e086e51 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Fri, 10 Sep 2021 14:40:29 -0700 Subject: [PATCH 085/346] Apply pre-convention value converters on nullable types Fixes #25896 --- .../Internal/PropertyConfiguration.cs | 4 ++-- .../ModelBuilding/NonRelationshipTestBase.cs | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/EFCore/Metadata/Internal/PropertyConfiguration.cs b/src/EFCore/Metadata/Internal/PropertyConfiguration.cs index 959eb5cbee0..4005ce3478d 100644 --- a/src/EFCore/Metadata/Internal/PropertyConfiguration.cs +++ b/src/EFCore/Metadata/Internal/PropertyConfiguration.cs @@ -74,14 +74,14 @@ public virtual void Apply(IMutableProperty property) break; case CoreAnnotationNames.ValueConverterType: - if (ClrType == property.ClrType) + if (ClrType.UnwrapNullableType() == property.ClrType.UnwrapNullableType()) { property.SetValueConverter((Type?)annotation.Value); } break; case CoreAnnotationNames.ValueComparerType: - if (ClrType == property.ClrType) + if (ClrType.UnwrapNullableType() == property.ClrType.UnwrapNullableType()) { property.SetValueComparer((Type?)annotation.Value); } diff --git a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs index 748007356b8..dc4a56c94d6 100644 --- a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs @@ -979,6 +979,27 @@ public virtual void Properties_can_have_value_converter_configured_by_type() Assert.IsType>(wrappedProperty.GetValueComparer()); } + [ConditionalFact] + public virtual void Value_converter_configured_on_non_nullable_type_is_applied() + { + var modelBuilder = CreateModelBuilder(c => + { + c.Properties().HaveConversion>(); + }); + + modelBuilder.Entity( + b => + { + b.Property("Wierd"); + }); + + var model = modelBuilder.FinalizeModel(); + var entityType = model.FindEntityType(typeof(Quarks)); + + Assert.IsType>(entityType.FindProperty("Id").GetValueConverter()); + Assert.IsType>(entityType.FindProperty("Wierd").GetValueConverter()); + } + [ConditionalFact] public virtual void Value_converter_configured_on_base_type_is_not_applied() { From f67dd1005191d4ed5ab7485a7996958a1975fe39 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 11 Sep 2021 00:28:53 +0000 Subject: [PATCH 086/346] Update dependencies from https://github.com/dotnet/runtime build 20210910.14 (#25975) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ac629340199..1370c9c1e9b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa - + https://github.com/dotnet/runtime - 8bfc0302a28bd94fe5078d9ea489b6a8bc8978ee + 46c7023a3de4d6df7f9b001ce46f22f482168dfa diff --git a/eng/Versions.props b/eng/Versions.props index dbf3792ea86..fe505c17c06 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 - 6.0.0-rc.2.21460.8 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21460.14 3.7.0 From 8de029694c5452f7064b18a83435078455006d38 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Sat, 11 Sep 2021 09:15:33 +0100 Subject: [PATCH 087/346] Generate multiple query tags without newlines between them (#25963) Fixes #25414 --- .../Query/QuerySqlGenerator.cs | 5 +- ...yableMethodNormalizingExpressionVisitor.cs | 2 +- .../Query/FromSqlSprocQueryTestBase.cs | 51 ++++++++++++++++++- .../Query/FromSqlSprocQuerySqlServerTest.cs | 26 +++++++++- ...NorthwindQueryTaggingQuerySqlServerTest.cs | 7 +-- 5 files changed, 80 insertions(+), 11 deletions(-) diff --git a/src/EFCore.Relational/Query/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs index dbbf169fe3a..804e975f594 100644 --- a/src/EFCore.Relational/Query/QuerySqlGenerator.cs +++ b/src/EFCore.Relational/Query/QuerySqlGenerator.cs @@ -115,10 +115,9 @@ protected virtual void GenerateTagsHeaderComment(SelectExpression selectExpressi { foreach (var tag in selectExpression.Tags) { - _relationalCommandBuilder - .AppendLines(_sqlGenerationHelper.GenerateComment(tag)) - .AppendLine(); + _relationalCommandBuilder.AppendLines(_sqlGenerationHelper.GenerateComment(tag)); } + _relationalCommandBuilder.AppendLine(); } } diff --git a/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs b/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs index 173b4e5692c..00f5e2d5467 100644 --- a/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/QueryableMethodNormalizingExpressionVisitor.cs @@ -217,7 +217,7 @@ private void VerifyReturnType(Expression expression, ParameterExpression lambdaP var filePath = methodCallExpression.Arguments[1].GetConstantValue(); var lineNumber = methodCallExpression.Arguments[2].GetConstantValue(); - _queryCompilationContext.AddTag($"file: {filePath}:{lineNumber}"); + _queryCompilationContext.AddTag($"File: {filePath}:{lineNumber}"); return visitedExpression; } diff --git a/test/EFCore.Relational.Specification.Tests/Query/FromSqlSprocQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/FromSqlSprocQueryTestBase.cs index 1a686996d60..fd9362c05f5 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/FromSqlSprocQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/FromSqlSprocQueryTestBase.cs @@ -66,6 +66,31 @@ public virtual async Task From_sql_queryable_stored_procedure_with_tag(bool asyn && mep.UnitPrice == 263.50m); } + [ConditionalTheory] + [InlineData(false)] + [InlineData(true)] + public virtual async Task From_sql_queryable_stored_procedure_with_tags(bool async) + { + using var context = CreateContext(); + var query = context + .Set() + .FromSqlRaw(TenMostExpensiveProductsSproc, GetTenMostExpensiveProductsParameters()) + .TagWith("One") + .TagWith("Two") + .TagWith("Three"); + + var actual = async + ? await query.ToArrayAsync() + : query.ToArray(); + + Assert.Equal(10, actual.Length); + + Assert.Contains( + actual, mep => + mep.TenMostExpensiveProducts == "Côte de Blaye" + && mep.UnitPrice == 263.50m); + } + [ConditionalTheory] [InlineData(false)] [InlineData(true)] @@ -83,7 +108,31 @@ public virtual async Task From_sql_queryable_stored_procedure_with_caller_info_t var actual = query.ToQueryString().Split(Environment.NewLine).First(); - Assert.Equal("-- file: SampleFileName:13", actual); + Assert.Equal("-- File: SampleFileName:13", actual); + } + + [ConditionalTheory] + [InlineData(false)] + [InlineData(true)] + public virtual async Task From_sql_queryable_stored_procedure_with_caller_info_tag_and_other_tags(bool async) + { + using var context = CreateContext(); + var query = context + .Set() + .FromSqlRaw(TenMostExpensiveProductsSproc, GetTenMostExpensiveProductsParameters()) + .TagWith("Before") + .TagWithCallSite("SampleFileName", 13) + .TagWith("After"); + + var queryResult = async + ? await query.ToArrayAsync() + : query.ToArray(); + + var tags = query.ToQueryString().Split(Environment.NewLine).ToList(); + + Assert.Equal("-- Before", tags[0]); + Assert.Equal("-- File: SampleFileName:13", tags[1]); + Assert.Equal("-- After", tags[2]); } [ConditionalTheory] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/FromSqlSprocQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/FromSqlSprocQuerySqlServerTest.cs index de124ebd6d7..fa7e932df3e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/FromSqlSprocQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/FromSqlSprocQuerySqlServerTest.cs @@ -28,6 +28,18 @@ public override async Task From_sql_queryable_stored_procedure_with_tag(bool asy AssertSql( @"-- Stored Procedure +[dbo].[Ten Most Expensive Products]"); + } + + public override async Task From_sql_queryable_stored_procedure_with_tags(bool async) + { + await base.From_sql_queryable_stored_procedure_with_tags(async); + + AssertSql( + @"-- One +-- Two +-- Three + [dbo].[Ten Most Expensive Products]"); } @@ -36,7 +48,19 @@ public override async Task From_sql_queryable_stored_procedure_with_caller_info_ await base.From_sql_queryable_stored_procedure_with_caller_info_tag(async); AssertSql( - @"-- file: SampleFileName:13 + @"-- File: SampleFileName:13 + +[dbo].[Ten Most Expensive Products]"); + } + + public override async Task From_sql_queryable_stored_procedure_with_caller_info_tag_and_other_tags(bool async) + { + await base.From_sql_queryable_stored_procedure_with_caller_info_tag_and_other_tags(async); + + AssertSql( + @"-- Before +-- File: SampleFileName:13 +-- After [dbo].[Ten Most Expensive Products]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindQueryTaggingQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindQueryTaggingQuerySqlServerTest.cs index 61dd3f293c0..c3bbc9e1dad 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindQueryTaggingQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindQueryTaggingQuerySqlServerTest.cs @@ -39,7 +39,6 @@ public override void Single_query_multiple_tags() AssertSql( @"-- Yanni - -- Enya SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] @@ -53,7 +52,6 @@ public override void Tags_on_subquery() AssertSql( @"-- Yanni - -- Laurel SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] @@ -162,7 +160,6 @@ public override void Single_query_multiple_multiline_tag() @"-- Yanni -- AND -- Laurel - -- Yet -- Another -- Multiline @@ -179,9 +176,9 @@ public override void Single_query_multiline_tag_with_empty_lines() AssertSql( @"-- Yanni --- +-- " + @" -- AND --- +-- " + @" -- Laurel SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] From 64ab71278ac8b0ea9ecda34a65c351e52178a8ba Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Sat, 11 Sep 2021 10:03:04 +0100 Subject: [PATCH 088/346] Handle nulls passed to typed equality method expression (#25966) * Handle nulls passed to typed equality method expression Fixes #25492 * Re-enabled #25615 --- src/EFCore/ChangeTracking/ValueComparer`.cs | 21 ++++++- .../Query/GearsOfWarQueryInMemoryTest.cs | 4 -- .../EFCore.Tests/Storage/ValueComparerTest.cs | 55 ++++++++++++++----- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/src/EFCore/ChangeTracking/ValueComparer`.cs b/src/EFCore/ChangeTracking/ValueComparer`.cs index 75b6d76e94c..422d00a7bc0 100644 --- a/src/EFCore/ChangeTracking/ValueComparer`.cs +++ b/src/EFCore/ChangeTracking/ValueComparer`.cs @@ -130,6 +130,23 @@ public ValueComparer( && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(T)); + if (typedEquals != null) + { + return Expression.Lambda>( + type.IsClass + ? Expression.OrElse( + Expression.AndAlso( + Expression.Equal(param1, Expression.Constant(null, type)), + Expression.Equal(param2, Expression.Constant(null, type))), + Expression.AndAlso( + Expression.AndAlso( + Expression.NotEqual(param1, Expression.Constant(null, type)), + Expression.NotEqual(param2, Expression.Constant(null, type))), + Expression.Call(param1, typedEquals, param2))) + : Expression.Call(param1, typedEquals, param2), + param1, param2); + } + while (typedEquals == null && type != null) { @@ -151,9 +168,7 @@ public ValueComparer( ObjectEqualsMethod, Expression.Convert(param1, typeof(object)), Expression.Convert(param2, typeof(object))) - : typedEquals.IsStatic - ? Expression.Call(typedEquals, param1, param2) - : Expression.Call(param1, typedEquals, param2), + : Expression.Call(typedEquals, param1, param2), param1, param2); } diff --git a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs index 23eaace61a2..19ce4f49885 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs @@ -51,10 +51,6 @@ public override Task Projecting_entity_as_well_as_correlated_collection_of_scala public override Task Correlated_collection_with_distinct_3_levels(bool async) => base.Correlated_collection_with_distinct_3_levels(async); - [ConditionalTheory(Skip = "Issue #25615")] - public override Task Comparison_with_value_converted_subclass(bool async) - => base.Comparison_with_value_converted_subclass(async); - public override async Task Projecting_correlated_collection_followed_by_Distinct(bool async) { var message = (await Assert.ThrowsAsync( diff --git a/test/EFCore.Tests/Storage/ValueComparerTest.cs b/test/EFCore.Tests/Storage/ValueComparerTest.cs index fb3b6c27311..8aa0f077d13 100644 --- a/test/EFCore.Tests/Storage/ValueComparerTest.cs +++ b/test/EFCore.Tests/Storage/ValueComparerTest.cs @@ -285,7 +285,37 @@ private void GenericCompareTest(T value1, T value2, int? hashCode = null) Assert.False(keyEquals(value2, value1)); Assert.Equal(hashCode ?? value1.GetHashCode(), getHashCode(value1)); + Assert.Equal(hashCode ?? value1.GetHashCode(), getKeyHashCode(value1)); + } + + private void GenericCompareTestWithNulls(T value1, T value2, int? hashCode = null) + where T : class + { + var comparer = new ValueComparer(false); + var equals = comparer.EqualsExpression.Compile(); + var getHashCode = comparer.HashCodeExpression.Compile(); + + Assert.True(equals(value1, value1)); + Assert.True(equals(value2, value2)); + Assert.False(equals(value1, value2)); + Assert.False(equals(value2, value1)); + Assert.False(equals(value1, null)); + Assert.False(equals(null, value2)); + Assert.True(equals(null, null)); + + var keyComparer = new ValueComparer(true); + var keyEquals = keyComparer.EqualsExpression.Compile(); + var getKeyHashCode = keyComparer.HashCodeExpression.Compile(); + Assert.True(keyEquals(value1, value1)); + Assert.True(keyEquals(value2, value2)); + Assert.False(keyEquals(value1, value2)); + Assert.False(keyEquals(value2, value1)); + Assert.False(keyEquals(value1, null)); + Assert.False(keyEquals(null, value2)); + Assert.True(keyEquals(null, null)); + + Assert.Equal(hashCode ?? value1.GetHashCode(), getHashCode(value1)); Assert.Equal(hashCode ?? value1.GetHashCode(), getKeyHashCode(value1)); } @@ -305,20 +335,19 @@ public void Default_raw_comparer_works_for_non_null_normal_types() GenericCompareTest(1, 2); GenericCompareTest('A', 'B', 'A'); GenericCompareTest("A", "B"); - GenericCompareTest(1, "A"); GenericCompareTest(JustAnEnum.A, JustAnEnum.B); - GenericCompareTest( - new JustAClass { A = 1 }, new JustAClass { A = 2 }); - GenericCompareTest( - new JustAClassWithEquality { A = 1 }, new JustAClassWithEquality { A = 2 }); - GenericCompareTest( - new JustAClassWithEqualityOperators { A = 1 }, new JustAClassWithEqualityOperators { A = 2 }); - GenericCompareTest( - new JustAStruct { A = 1 }, new JustAStruct { A = 2 }); - GenericCompareTest( - new JustAStructWithEquality { A = 1 }, new JustAStructWithEquality { A = 2 }); - GenericCompareTest( - new JustAStructWithEqualityOperators { A = 1 }, new JustAStructWithEqualityOperators { A = 2 }); + GenericCompareTest(new JustAStruct { A = 1 }, new JustAStruct { A = 2 }); + GenericCompareTest(new JustAStructWithEquality { A = 1 }, new JustAStructWithEquality { A = 2 }); + GenericCompareTest(new JustAStructWithEqualityOperators { A = 1 }, new JustAStructWithEqualityOperators { A = 2 }); + } + + [ConditionalFact] + public void Default_raw_comparer_works_for_reference_types() + { + GenericCompareTestWithNulls(1, "A"); + GenericCompareTestWithNulls(new JustAClass { A = 1 }, new JustAClass { A = 2 }); + GenericCompareTestWithNulls(new JustAClassWithEquality { A = 1 }, new JustAClassWithEquality { A = 2 }); + GenericCompareTestWithNulls(new JustAClassWithEqualityOperators { A = 1 }, new JustAClassWithEqualityOperators { A = 2 }); } [ConditionalFact] From f01b70def5f65ddc96cbe46e3e5809cbc914d500 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Sat, 11 Sep 2021 10:03:43 +0100 Subject: [PATCH 089/346] More links to conceptual docs (#25962) * More links to conceptual docs Part of #17508 * Remove hyphens from lazy-loading. --- .../BackingFieldAttribute.cs | 3 + .../ObservableCollectionListSource.cs | 3 + src/EFCore.Abstractions/CommentAttribute.cs | 3 + .../DbFunctionAttribute.cs | 3 + .../EntityTypeConfigurationAttribute.cs | 3 + src/EFCore.Abstractions/IndexAttribute.cs | 3 + .../Infrastructure/ILazyLoader.cs | 3 + .../Infrastructure/LazyLoaderExtensions.cs | 6 + src/EFCore.Abstractions/KeylessAttribute.cs | 3 + .../ObservableCollectionExtensions.cs | 3 + src/EFCore.Abstractions/OwnedAttribute.cs | 3 + src/EFCore.Abstractions/PrecisionAttribute.cs | 3 + .../Query/NotParameterizedAttribute.cs | 3 + src/EFCore.Abstractions/UnicodeAttribute.cs | 3 + .../Diagnostics/CosmosEventId.cs | 4 + .../CosmosItemCommandExecutedEventData.cs | 3 + .../Diagnostics/CosmosQueryEventData.cs | 3 + .../CosmosQueryExecutedEventData.cs | 3 + .../Diagnostics/CosmosReadItemEventData.cs | 3 + .../CosmosDatabaseFacadeExtensions.cs | 6 + .../CosmosDbContextOptionsExtensions.cs | 20 + .../CosmosEntityTypeBuilderExtensions.cs | 120 ++++++ .../Extensions/CosmosEntityTypeExtensions.cs | 4 + .../CosmosModelBuilderExtensions.cs | 32 ++ .../Extensions/CosmosModelExtensions.cs | 4 + .../CosmosPropertyBuilderExtensions.cs | 28 ++ .../Extensions/CosmosPropertyExtensions.cs | 4 + .../Extensions/CosmosQueryableExtensions.cs | 12 + .../CosmosServiceCollectionExtensions.cs | 8 + .../CosmosDbContextOptionsBuilder.cs | 66 +++- .../Conventions/ContextContainerConvention.cs | 4 + .../CosmosDiscriminatorConvention.cs | 4 + ...osmosInversePropertyAttributeConvention.cs | 4 + .../CosmosKeyDiscoveryConvention.cs | 4 + ...osmosManyToManyJoinEntityTypeConvention.cs | 4 + .../CosmosRelationshipDiscoveryConvention.cs | 4 + .../CosmosRuntimeModelConvention.cs | 4 + .../Conventions/ETagPropertyConvention.cs | 4 + .../Conventions/StoreKeyConvention.cs | 4 + .../IdValueGeneratorFactory.cs | 4 + .../Diagnostics/InMemoryEventId.cs | 4 + .../InMemoryDatabaseFacadeExtensions.cs | 3 + .../InMemoryDbContextOptionsExtensions.cs | 16 + .../InMemoryEntityTypeBuilderExtensions.cs | 20 + .../InMemoryEntityTypeExtensions.cs | 4 + .../InMemoryDbContextOptionsBuilder.cs | 8 + .../DefiningQueryRewritingConvention.cs | 4 + .../InMemoryConventionSetBuilder.cs | 4 + .../Storage/InMemoryDatabaseRoot.cs | 3 + src/EFCore.Proxies/EFCore.Proxies.csproj | 4 +- .../Internal/ProxiesOptionsExtension.cs | 4 +- src/EFCore.Proxies/ProxiesExtensions.cs | 8 +- ...ySuiteDbContextOptionsBuilderExtensions.cs | 5 + ...opologySuiteServiceCollectionExtensions.cs | 5 + ...ctingValueGenerationStrategiesEventData.cs | 5 + .../Diagnostics/SqlServerEventId.cs | 5 + .../SqlServerDatabaseFacadeExtensions.cs | 4 + ...ServerDbContextOptionsBuilderExtensions.cs | 35 ++ .../SqlServerDbFunctionsExtensions.cs | 370 +++++++++++++++++- .../Extensions/SqlServerDbSetExtensions.cs | 66 +++- .../SqlServerEntityTypeBuilderExtensions.cs | 69 ++++ .../SqlServerEntityTypeExtensions.cs | 5 + .../SqlServerIndexBuilderExtensions.cs | 90 +++++ .../Extensions/SqlServerIndexExtensions.cs | 5 + .../SqlServerKeyBuilderExtensions.cs | 25 ++ .../Extensions/SqlServerKeyExtensions.cs | 5 + .../SqlServerMigrationBuilderExtensions.cs | 4 + .../SqlServerModelBuilderExtensions.cs | 115 ++++++ .../Extensions/SqlServerModelExtensions.cs | 5 + .../SqlServerPropertyBuilderExtensions.cs | 95 +++++ .../Extensions/SqlServerPropertyExtensions.cs | 5 + .../SqlServerServiceCollectionExtensions.cs | 5 + .../SqlServerTableBuilderExtensions.cs | 16 + .../SqlServerDbContextOptionsBuilder.cs | 12 + .../Builders/TemporalPeriodPropertyBuilder.cs | 4 + .../Metadata/Builders/TemporalTableBuilder.cs | 16 + .../Builders/TemporalTableBuilder`.cs | 4 + .../SqlServerConventionSetBuilder.cs | 5 + .../SqlServerDbFunctionConvention.cs | 5 + .../Conventions/SqlServerIndexConvention.cs | 5 + ...qlServerMemoryOptimizedTablesConvention.cs | 5 + .../SqlServerOnDeleteConvention.cs | 5 + .../SqlServerRuntimeModelConvention.cs | 5 + .../SqlServerSharedTableConvention.cs | 5 + .../SqlServerStoreGenerationConvention.cs | 5 + .../SqlServerTemporalConvention.cs | 5 + .../SqlServerValueGenerationConvention.cs | 5 + ...ServerValueGenerationStrategyConvention.cs | 5 + .../SqlServerValueGenerationStrategy.cs | 5 + .../SqlServerCreateDatabaseOperation.cs | 5 + .../SqlServerDropDatabaseOperation.cs | 5 + .../SqlServerMigrationsSqlGenerator.cs | 5 + .../Diagnostics/SqliteEventId.cs | 4 + .../SqliteDatabaseFacadeExtensions.cs | 3 + ...SqliteDbContextOptionsBuilderExtensions.cs | 29 +- .../Extensions/SqliteDbFunctionsExtensions.cs | 20 + .../SqliteMigrationBuilderExtensions.cs | 6 + .../SqlitePropertyBuilderExtensions.cs | 20 + .../Extensions/SqlitePropertyExtensions.cs | 4 + .../SqliteServiceCollectionExtensions.cs | 4 + .../Infrastructure/SpatialiteLoader.cs | 4 + .../SqliteDbContextOptionsBuilder.cs | 4 + .../Conventions/SqliteConventionSetBuilder.cs | 4 + .../SqliteRuntimeModelConvention.cs | 4 + .../SqliteSharedTableConvention.cs | 4 + .../SqliteMigrationsSqlGenerator.cs | 4 + ...ySuiteDbContextOptionsBuilderExtensions.cs | 8 + ...opologySuiteServiceCollectionExtensions.cs | 4 + .../Diagnostics/LazyLoadingEventData.cs | 4 +- src/EFCore/Properties/CoreStrings.Designer.cs | 2 +- src/EFCore/Properties/CoreStrings.resx | 2 +- .../ProxyGraphUpdatesSqlServerTest.cs | 2 +- .../ProxyGraphUpdatesSqliteTest.cs | 2 +- 113 files changed, 1633 insertions(+), 42 deletions(-) diff --git a/src/EFCore.Abstractions/BackingFieldAttribute.cs b/src/EFCore.Abstractions/BackingFieldAttribute.cs index cd77a54312d..bbb37b81a2f 100644 --- a/src/EFCore.Abstractions/BackingFieldAttribute.cs +++ b/src/EFCore.Abstractions/BackingFieldAttribute.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Names the backing field associated with this property or navigation property. /// + /// + /// See Modeling entity types and relationships for more information. + /// [AttributeUsage(AttributeTargets.Property)] public sealed class BackingFieldAttribute : Attribute { diff --git a/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs b/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs index 8ae0af8e3c8..aa8e99d4dfa 100644 --- a/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs +++ b/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking /// For WPF data binding use an ObservableCollection rather than an instance of this class. /// /// + /// + /// See Local views of tracked entities in EF Core for more information. + /// /// The type of elements in the collection. public class ObservableCollectionListSource : ObservableCollection, IListSource where T : class diff --git a/src/EFCore.Abstractions/CommentAttribute.cs b/src/EFCore.Abstractions/CommentAttribute.cs index 6e82f97bb00..81c7869dc30 100644 --- a/src/EFCore.Abstractions/CommentAttribute.cs +++ b/src/EFCore.Abstractions/CommentAttribute.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Marks a class, property or field with a comment to be set on the corresponding database table or column. /// + /// + /// See Modeling entity types and relationships for more information. + /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field)] public sealed class CommentAttribute : Attribute { diff --git a/src/EFCore.Abstractions/DbFunctionAttribute.cs b/src/EFCore.Abstractions/DbFunctionAttribute.cs index 56c127de13b..3c2e3ba55fd 100644 --- a/src/EFCore.Abstractions/DbFunctionAttribute.cs +++ b/src/EFCore.Abstractions/DbFunctionAttribute.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore /// Maps a static CLR method to a database function so that the CLR method may be used in LINQ queries. /// By convention uses the .NET method name as name of the database function and the default schema. /// + /// + /// See Database functions for more information. + /// [AttributeUsage(AttributeTargets.Method)] #pragma warning disable CA1813 // Avoid unsealed attributes // Already shipped unsealed diff --git a/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs b/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs index be21a27f2f8..287c08cf744 100644 --- a/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs +++ b/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Specifies the configuration type for the entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// [AttributeUsage(AttributeTargets.Class)] public sealed class EntityTypeConfigurationAttribute : Attribute { diff --git a/src/EFCore.Abstractions/IndexAttribute.cs b/src/EFCore.Abstractions/IndexAttribute.cs index ff179e9f644..319ecf4cfd7 100644 --- a/src/EFCore.Abstractions/IndexAttribute.cs +++ b/src/EFCore.Abstractions/IndexAttribute.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Specifies an index to be generated in the database. /// + /// + /// See Modeling entity types and relationships for more information. + /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public sealed class IndexAttribute : Attribute { diff --git a/src/EFCore.Abstractions/Infrastructure/ILazyLoader.cs b/src/EFCore.Abstractions/Infrastructure/ILazyLoader.cs index 02dd365c098..0ff192e6c07 100644 --- a/src/EFCore.Abstractions/Infrastructure/ILazyLoader.cs +++ b/src/EFCore.Abstractions/Infrastructure/ILazyLoader.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// The implementation does not need to be thread-safe. /// /// + /// + /// See Lazy loading for more information. + /// public interface ILazyLoader : IDisposable { /// diff --git a/src/EFCore.Abstractions/Infrastructure/LazyLoaderExtensions.cs b/src/EFCore.Abstractions/Infrastructure/LazyLoaderExtensions.cs index 042e64060fe..e97bb85f2a0 100644 --- a/src/EFCore.Abstractions/Infrastructure/LazyLoaderExtensions.cs +++ b/src/EFCore.Abstractions/Infrastructure/LazyLoaderExtensions.cs @@ -9,11 +9,17 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// Extension methods for the service that make it more /// convenient to use from entity classes. /// + /// + /// See Lazy loading for more information. + /// public static class LazyLoaderExtensions { /// /// Loads a navigation property if it has not already been loaded. /// + /// + /// See Lazy loading for more information. + /// /// The type of the navigation property. /// The loader instance, which may be . /// The entity on which the navigation property is located. diff --git a/src/EFCore.Abstractions/KeylessAttribute.cs b/src/EFCore.Abstractions/KeylessAttribute.cs index ef41eaf4ff2..6d93617d343 100644 --- a/src/EFCore.Abstractions/KeylessAttribute.cs +++ b/src/EFCore.Abstractions/KeylessAttribute.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Marks a type as keyless entity. /// + /// + /// See Modeling entity types and relationships for more information. + /// [AttributeUsage(AttributeTargets.Class)] public sealed class KeylessAttribute : Attribute { diff --git a/src/EFCore.Abstractions/ObservableCollectionExtensions.cs b/src/EFCore.Abstractions/ObservableCollectionExtensions.cs index b5f643ce219..c90d1406d3f 100644 --- a/src/EFCore.Abstractions/ObservableCollectionExtensions.cs +++ b/src/EFCore.Abstractions/ObservableCollectionExtensions.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Extension methods for . /// + /// + /// See Local views of tracked entities in EF Core for more information. + /// public static class ObservableCollectionExtensions { /// diff --git a/src/EFCore.Abstractions/OwnedAttribute.cs b/src/EFCore.Abstractions/OwnedAttribute.cs index 82542c46f9a..969e55172d2 100644 --- a/src/EFCore.Abstractions/OwnedAttribute.cs +++ b/src/EFCore.Abstractions/OwnedAttribute.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Marks a type as owned. All references to this type will be configured as owned entity types. /// + /// + /// See Modeling entity types and relationships for more information. + /// [AttributeUsage(AttributeTargets.Class)] public sealed class OwnedAttribute : Attribute { diff --git a/src/EFCore.Abstractions/PrecisionAttribute.cs b/src/EFCore.Abstractions/PrecisionAttribute.cs index becc604c353..2fdd3a9c60f 100644 --- a/src/EFCore.Abstractions/PrecisionAttribute.cs +++ b/src/EFCore.Abstractions/PrecisionAttribute.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore /// For example, if the property is a /// then this is the maximum number of digits. /// + /// + /// See Modeling entity types and relationships for more information. + /// [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class PrecisionAttribute : Attribute { diff --git a/src/EFCore.Abstractions/Query/NotParameterizedAttribute.cs b/src/EFCore.Abstractions/Query/NotParameterizedAttribute.cs index 90d7cecb28e..3509744f261 100644 --- a/src/EFCore.Abstractions/Query/NotParameterizedAttribute.cs +++ b/src/EFCore.Abstractions/Query/NotParameterizedAttribute.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Query /// /// Signals that custom LINQ operator parameter should not be parameterized during query compilation. /// + /// + /// See Querying data with EF Core for more information. + /// [AttributeUsage(AttributeTargets.Parameter)] public sealed class NotParameterizedAttribute : Attribute { diff --git a/src/EFCore.Abstractions/UnicodeAttribute.cs b/src/EFCore.Abstractions/UnicodeAttribute.cs index a58622c7fea..536d372638f 100644 --- a/src/EFCore.Abstractions/UnicodeAttribute.cs +++ b/src/EFCore.Abstractions/UnicodeAttribute.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Configures the property as capable of persisting unicode characters. /// + /// + /// See Modeling entity types and relationships for more information. + /// [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class UnicodeAttribute : Attribute { diff --git a/src/EFCore.Cosmos/Diagnostics/CosmosEventId.cs b/src/EFCore.Cosmos/Diagnostics/CosmosEventId.cs index 96eab5d1bbb..c78935beb21 100644 --- a/src/EFCore.Cosmos/Diagnostics/CosmosEventId.cs +++ b/src/EFCore.Cosmos/Diagnostics/CosmosEventId.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// behavior of warnings. /// /// + /// + /// See Logging, events, and diagnostics, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosEventId { // Warning: These values must not change between releases. diff --git a/src/EFCore.Cosmos/Diagnostics/CosmosItemCommandExecutedEventData.cs b/src/EFCore.Cosmos/Diagnostics/CosmosItemCommandExecutedEventData.cs index 49b4a7a45c1..420dcf16769 100644 --- a/src/EFCore.Cosmos/Diagnostics/CosmosItemCommandExecutedEventData.cs +++ b/src/EFCore.Cosmos/Diagnostics/CosmosItemCommandExecutedEventData.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// A event payload class for Cosmos item command executed events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class CosmosItemCommandExecutedEventData : EventData { /// diff --git a/src/EFCore.Cosmos/Diagnostics/CosmosQueryEventData.cs b/src/EFCore.Cosmos/Diagnostics/CosmosQueryEventData.cs index 27c2d6c3677..8d91f950a69 100644 --- a/src/EFCore.Cosmos/Diagnostics/CosmosQueryEventData.cs +++ b/src/EFCore.Cosmos/Diagnostics/CosmosQueryEventData.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// A event payload class for Cosmos query events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class CosmosQueryEventData : EventData { /// diff --git a/src/EFCore.Cosmos/Diagnostics/CosmosQueryExecutedEventData.cs b/src/EFCore.Cosmos/Diagnostics/CosmosQueryExecutedEventData.cs index 08708bfc854..d406b6597a6 100644 --- a/src/EFCore.Cosmos/Diagnostics/CosmosQueryExecutedEventData.cs +++ b/src/EFCore.Cosmos/Diagnostics/CosmosQueryExecutedEventData.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// A event payload class for Cosmos query events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class CosmosQueryExecutedEventData : EventData { /// diff --git a/src/EFCore.Cosmos/Diagnostics/CosmosReadItemEventData.cs b/src/EFCore.Cosmos/Diagnostics/CosmosReadItemEventData.cs index c814d208813..4d064f29bed 100644 --- a/src/EFCore.Cosmos/Diagnostics/CosmosReadItemEventData.cs +++ b/src/EFCore.Cosmos/Diagnostics/CosmosReadItemEventData.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// A event payload class for Cosmos read-item events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class CosmosReadItemEventData : EventData { /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosDatabaseFacadeExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosDatabaseFacadeExtensions.cs index b84e790a7fb..bc9c3dd03b0 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosDatabaseFacadeExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosDatabaseFacadeExtensions.cs @@ -22,6 +22,9 @@ public static class CosmosDatabaseFacadeExtensions /// /// Gets the underlying for this . /// + /// + /// See Accessing Azure Cosmos DB with EF Core for more information. + /// /// The for the context. /// The public static CosmosClient GetCosmosClient(this DatabaseFacade databaseFacade) @@ -51,6 +54,9 @@ private static TService GetService(IInfrastructure d /// provider to use as part of configuring the context. /// /// + /// + /// See Accessing Azure Cosmos DB with EF Core for more information. + /// /// The facade from . /// if the Cosmos provider is being used. public static bool IsCosmos(this DatabaseFacade database) diff --git a/src/EFCore.Cosmos/Extensions/CosmosDbContextOptionsExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosDbContextOptionsExtensions.cs index b3667d0fe77..183920c2d8b 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosDbContextOptionsExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosDbContextOptionsExtensions.cs @@ -12,11 +12,19 @@ namespace Microsoft.EntityFrameworkCore /// /// Cosmos-specific extension methods for . /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosDbContextOptionsExtensions { /// /// Configures the context to connect to an Azure Cosmos database. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The type of context to be configured. /// The builder being used to configure the context. /// The account end-point to connect to. @@ -41,6 +49,10 @@ public static DbContextOptionsBuilder UseCosmos( /// /// Configures the context to connect to an Azure Cosmos database. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder being used to configure the context. /// The account end-point to connect to. /// The account key. @@ -77,6 +89,10 @@ public static DbContextOptionsBuilder UseCosmos( /// /// Configures the context to connect to an Azure Cosmos database. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The type of context to be configured. /// The builder being used to configure the context. /// The connection string of the database to connect to. @@ -98,6 +114,10 @@ public static DbContextOptionsBuilder UseCosmos( /// /// Configures the context to connect to an Azure Cosmos database. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder being used to configure the context. /// The connection string of the database to connect to. /// The database name. diff --git a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs index 1c2efc35780..57a5ec7114c 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs @@ -17,11 +17,19 @@ namespace Microsoft.EntityFrameworkCore /// /// Cosmos-specific extension methods for . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosEntityTypeBuilderExtensions { /// /// Configures the container that the entity type maps to when targeting Azure Cosmos. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the container. /// The same builder instance so that multiple calls can be chained. @@ -40,6 +48,10 @@ public static EntityTypeBuilder ToContainer( /// /// Configures the container that the entity type maps to when targeting Azure Cosmos. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The name of the container. @@ -53,6 +65,10 @@ public static EntityTypeBuilder ToContainer( /// /// Configures the container that the entity type maps to when targeting Azure Cosmos. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the container. /// Indicates whether the configuration was specified using a data annotation. @@ -79,6 +95,10 @@ public static EntityTypeBuilder ToContainer( /// Returns a value indicating whether the container that the entity type maps to can be set /// from the current configuration source /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the container. /// Indicates whether the configuration was specified using a data annotation. @@ -97,6 +117,10 @@ public static bool CanSetContainer( /// /// Configures the property name that the entity is mapped to when stored as an embedded document. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the parent property. /// The same builder instance so that multiple calls can be chained. @@ -112,6 +136,10 @@ public static OwnedNavigationBuilder ToJsonProperty( /// /// Configures the property name that the entity is mapped to when stored as an embedded document. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the parent property. /// The same builder instance so that multiple calls can be chained. @@ -129,6 +157,10 @@ public static OwnedNavigationBuilder ToJsonPrope /// /// Configures the property name that the entity is mapped to when stored as an embedded document. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the parent property. /// Indicates whether the configuration was specified using a data annotation. @@ -155,6 +187,10 @@ public static OwnedNavigationBuilder ToJsonPrope /// Returns a value indicating whether the parent property name to which the entity type is mapped to can be set /// from the current configuration source /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the parent property. /// Indicates whether the configuration was specified using a data annotation. @@ -173,6 +209,10 @@ public static bool CanSetJsonProperty( /// /// Configures the property that is used to store the partition key. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the partition key property. /// The same builder instance so that multiple calls can be chained. @@ -188,6 +228,10 @@ public static EntityTypeBuilder HasPartitionKey( /// /// Configures the property that is used to store the partition key. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the partition key property. /// The same builder instance so that multiple calls can be chained. @@ -204,6 +248,10 @@ public static EntityTypeBuilder HasPartitionKey( /// /// Configures the property that is used to store the partition key. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The partition key property. /// The same builder instance so that multiple calls can be chained. @@ -222,6 +270,10 @@ public static EntityTypeBuilder HasPartitionKey( /// /// Configures the property that is used to store the partition key. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the partition key property. /// Indicates whether the configuration was specified using a data annotation. @@ -248,6 +300,10 @@ public static EntityTypeBuilder HasPartitionKey( /// Returns a value indicating whether the property that is used to store the partition key can be set /// from the current configuration source /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The name of the partition key property. /// Indicates whether the configuration was specified using a data annotation. @@ -266,6 +322,10 @@ public static bool CanSetPartitionKey( /// /// Configures this entity to use CosmosDb etag concurrency checks. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The same builder instance so that multiple calls can be chained. public static EntityTypeBuilder UseETagConcurrency(this EntityTypeBuilder entityTypeBuilder) @@ -281,6 +341,10 @@ public static EntityTypeBuilder UseETagConcurrency(this EntityTypeBuilder entity /// /// Configures this entity to use CosmosDb etag concurrency checks. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The same builder instance so that multiple calls can be chained. public static EntityTypeBuilder UseETagConcurrency(this EntityTypeBuilder entityTypeBuilder) @@ -294,6 +358,10 @@ public static EntityTypeBuilder UseETagConcurrency(this Entity /// /// Configures the time to live for analytical store in seconds at container scope. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The time to live. /// The same builder instance so that multiple calls can be chained. @@ -309,6 +377,10 @@ public static EntityTypeBuilder HasAnalyticalStoreTimeToLive( /// /// Configures the time to live for analytical store in seconds at container scope. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The time to live. /// The same builder instance so that multiple calls can be chained. @@ -325,6 +397,10 @@ public static EntityTypeBuilder HasAnalyticalStoreTimeToLive( /// /// Configures the time to live for analytical store in seconds at container scope. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The time to live. /// Indicates whether the configuration was specified using a data annotation. @@ -351,6 +427,10 @@ public static EntityTypeBuilder HasAnalyticalStoreTimeToLive( /// Returns a value indicating whether the time to live for analytical store can be set /// from the current configuration source /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The time to live. /// Indicates whether the configuration was specified using a data annotation. @@ -368,6 +448,10 @@ public static bool CanSetAnalyticalStoreTimeToLive( /// /// Configures the default time to live in seconds at container scope. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The time to live. /// The same builder instance so that multiple calls can be chained. @@ -383,6 +467,10 @@ public static EntityTypeBuilder HasDefaultTimeToLive( /// /// Configures the default time to live in seconds at container scope. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The time to live. /// The same builder instance so that multiple calls can be chained. @@ -399,6 +487,10 @@ public static EntityTypeBuilder HasDefaultTimeToLive( /// /// Configures the default time to live in seconds at container scope. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The time to live. /// Indicates whether the configuration was specified using a data annotation. @@ -425,6 +517,10 @@ public static EntityTypeBuilder HasDefaultTimeToLive( /// Returns a value indicating whether the default time to live can be set /// from the current configuration source /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The time to live. /// Indicates whether the configuration was specified using a data annotation. @@ -442,6 +538,10 @@ public static bool CanSetDefaultTimeToLive( /// /// Configures the manual provisioned throughput offering. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The throughput to set. public static EntityTypeBuilder HasManualThroughput(this EntityTypeBuilder entityTypeBuilder, int? throughput) @@ -454,6 +554,10 @@ public static EntityTypeBuilder HasManualThroughput(this EntityTypeBuilder entit /// /// Configures the manual provisioned throughput offering. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The throughput to set. public static EntityTypeBuilder HasManualThroughput(this EntityTypeBuilder entityTypeBuilder, int? throughput) @@ -467,6 +571,10 @@ public static EntityTypeBuilder HasManualThroughput(this Entit /// /// Configures the autoscale provisioned throughput offering. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The throughput to set. public static EntityTypeBuilder HasAutoscaleThroughput(this EntityTypeBuilder entityTypeBuilder, int? throughput) @@ -479,6 +587,10 @@ public static EntityTypeBuilder HasAutoscaleThroughput(this EntityTypeBuilder en /// /// Configures the autoscale provisioned throughput offering. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The throughput to set. public static EntityTypeBuilder HasAutoscaleThroughput(this EntityTypeBuilder entityTypeBuilder, int? throughput) @@ -492,6 +604,10 @@ public static EntityTypeBuilder HasAutoscaleThroughput(this En /// /// Configures the provisioned throughput. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The throughput to set. /// Whether autoscale is enabled. @@ -515,6 +631,10 @@ public static EntityTypeBuilder HasAutoscaleThroughput(this En /// /// Returns a value indicating whether the given throughput can be set. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the entity type being configured. /// The throughput to set. /// Whether autoscale is enabled. diff --git a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs index f207cbed36d..f944a77fdf5 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore /// /// Entity type extension methods for Cosmos metadata. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosEntityTypeExtensions { /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs index 029958b5015..fbc549e88a1 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs @@ -14,12 +14,20 @@ namespace Microsoft.EntityFrameworkCore /// /// Cosmos-specific extension methods for . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosModelBuilderExtensions { /// /// Configures the default container name that will be used if no name /// is explicitly configured for an entity type. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The model builder. /// The default container name. /// The same builder instance so that multiple calls can be chained. @@ -39,6 +47,10 @@ public static ModelBuilder HasDefaultContainer( /// Configures the default container name that will be used if no name /// is explicitly configured for an entity type. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The model builder. /// The default container name. /// Indicates whether the configuration was specified using a data annotation. @@ -64,6 +76,10 @@ public static ModelBuilder HasDefaultContainer( /// /// Returns a value indicating whether the given container name can be set as default. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The model builder. /// The default container name. /// Indicates whether the configuration was specified using a data annotation. @@ -81,6 +97,10 @@ public static bool CanSetDefaultContainer( /// /// Configures the manual provisioned throughput offering. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The model builder. /// The throughput to set. public static ModelBuilder HasManualThroughput(this ModelBuilder modelBuilder, int? throughput) @@ -93,6 +113,10 @@ public static ModelBuilder HasManualThroughput(this ModelBuilder modelBuilder, i /// /// Configures the autoscale provisioned throughput offering. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The model builder. /// The throughput to set. public static ModelBuilder HasAutoscaleThroughput(this ModelBuilder modelBuilder, int? throughput) @@ -105,6 +129,10 @@ public static ModelBuilder HasAutoscaleThroughput(this ModelBuilder modelBuilder /// /// Configures the provisioned throughput. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The model builder. /// The throughput to set. /// Whether autoscale is enabled. @@ -128,6 +156,10 @@ public static ModelBuilder HasAutoscaleThroughput(this ModelBuilder modelBuilder /// /// Returns a value indicating whether the given throughput can be set. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The model builder. /// The throughput to set. /// Whether autoscale is enabled. diff --git a/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs index a5bdb09902b..4081fc8723f 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore /// /// Model extension methods for Cosmos metadata. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosModelExtensions { /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs index d1b1271c23c..9b6bbf1accf 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs @@ -11,11 +11,19 @@ namespace Microsoft.EntityFrameworkCore /// /// Cosmos-specific extension methods for . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosPropertyBuilderExtensions { /// /// Configures the property name that the property is mapped to when targeting Azure Cosmos. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// If an empty string is supplied then the property will not be persisted. /// The builder for the property being configured. /// The name of the property. @@ -35,6 +43,10 @@ public static PropertyBuilder ToJsonProperty( /// /// Configures the property name that the property is mapped to when targeting Azure Cosmos. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The name of the property. @@ -52,6 +64,10 @@ public static PropertyBuilder ToJsonProperty( /// If an empty string is supplied then the property will not be persisted. /// /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the property being configured. /// The name of the property. /// Indicates whether the configuration was specified using a data annotation. @@ -77,6 +93,10 @@ public static PropertyBuilder ToJsonProperty( /// /// Returns a value indicating whether the given property name can be set. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the property being configured. /// The name of the property. /// Indicates whether the configuration was specified using a data annotation. @@ -90,6 +110,10 @@ public static bool CanSetJsonProperty( /// /// Configures this property to be the etag concurrency token. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The builder for the property being configured. /// The same builder instance so that multiple calls can be chained. public static PropertyBuilder IsETagConcurrency(this PropertyBuilder propertyBuilder) @@ -105,6 +129,10 @@ public static PropertyBuilder IsETagConcurrency(this PropertyBuilder propertyBui /// /// Configures this property to be the etag concurrency token. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The same builder instance so that multiple calls can be chained. diff --git a/src/EFCore.Cosmos/Extensions/CosmosPropertyExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosPropertyExtensions.cs index 86345bec3b9..1c82bf13c0f 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosPropertyExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosPropertyExtensions.cs @@ -11,6 +11,10 @@ namespace Microsoft.EntityFrameworkCore /// /// Property extension methods for Cosmos metadata. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosPropertyExtensions { /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosQueryableExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosQueryableExtensions.cs index 8c70d528e86..5c6d5235c16 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosQueryableExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosQueryableExtensions.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore /// /// Cosmos-specific extension methods for LINQ queries. /// + /// + /// See Querying data with EF Core, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosQueryableExtensions { internal static readonly MethodInfo WithPartitionKeyMethodInfo @@ -26,6 +30,10 @@ internal static readonly MethodInfo WithPartitionKeyMethodInfo /// Specify the partition key for partition used for the query. Required when using /// a resource token that provides permission based on a partition key for authentication, /// + /// + /// See Querying data with EF Core, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The type of entity being queried. /// The source query. /// The partition key. @@ -64,6 +72,10 @@ source.Provider is EntityQueryProvider /// /// context.Blogs.FromSqlRaw(""SELECT * FROM root c WHERE c["Name"] = {0})", userSuppliedSearchTerm) /// + /// + /// See Querying data with EF Core, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The type of the elements of . /// /// An to use as the base of the raw SQL query (typically a ). diff --git a/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs index 66be77af4d4..f0131be09c4 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs @@ -24,6 +24,10 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Cosmos-specific extension methods for . /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public static class CosmosServiceCollectionExtensions { /// @@ -51,6 +55,10 @@ public static class CosmosServiceCollectionExtensions /// See Using DbContext with dependency injection for more information. /// /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The type of context to be registered. /// The to add services to. /// The connection string of the database to connect to. diff --git a/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs b/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs index 11941d2e291..75219f66a70 100644 --- a/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs +++ b/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class CosmosDbContextOptionsBuilder : ICosmosDbContextOptionsBuilderInfrastructure { private readonly DbContextOptionsBuilder _optionsBuilder; @@ -29,6 +33,10 @@ public class CosmosDbContextOptionsBuilder : ICosmosDbContextOptionsBuilderInfra /// /// Initializes a new instance of the class. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The options builder. public CosmosDbContextOptionsBuilder(DbContextOptionsBuilder optionsBuilder) { @@ -44,6 +52,10 @@ DbContextOptionsBuilder ICosmosDbContextOptionsBuilderInfrastructure.OptionsBuil /// /// Configures the context to use the provided . /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// A function that returns a new instance of an execution strategy. public virtual CosmosDbContextOptionsBuilder ExecutionStrategy( Func getExecutionStrategy) @@ -52,6 +64,10 @@ public virtual CosmosDbContextOptionsBuilder ExecutionStrategy( /// /// Configures the context to use the provided geo-replicated region. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// Azure Cosmos DB region name. public virtual CosmosDbContextOptionsBuilder Region(string region) => WithOption(e => e.WithRegion(Check.NotNull(region, nameof(region)))); @@ -59,6 +75,10 @@ public virtual CosmosDbContextOptionsBuilder Region(string region) /// /// Limits the operations to the provided endpoint. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// to limit the operations to the provided endpoint. public virtual CosmosDbContextOptionsBuilder LimitToEndpoint(bool enable = true) => WithOption(e => e.WithLimitToEndpoint(Check.NotNull(enable, nameof(enable)))); @@ -72,6 +92,10 @@ public virtual CosmosDbContextOptionsBuilder LimitToEndpoint(bool enable = true) /// /// .HttpClientFactory(static () => new HttpClient()) /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// A function that returns an . public virtual CosmosDbContextOptionsBuilder HttpClientFactory(Func? httpClientFactory) => WithOption(e => e.WithHttpClientFactory(Check.NotNull(httpClientFactory, nameof(httpClientFactory)))); @@ -79,6 +103,10 @@ public virtual CosmosDbContextOptionsBuilder HttpClientFactory(Func? /// /// Configures the context to use the provided connection mode. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// Azure Cosmos DB connection mode. public virtual CosmosDbContextOptionsBuilder ConnectionMode(ConnectionMode connectionMode) => WithOption(e => e.WithConnectionMode(Check.NotNull(connectionMode, nameof(connectionMode)))); @@ -86,6 +114,10 @@ public virtual CosmosDbContextOptionsBuilder ConnectionMode(ConnectionMode conne /// /// Configures the proxy information used for web requests. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The proxy information used for web requests. public virtual CosmosDbContextOptionsBuilder WebProxy(IWebProxy proxy) => WithOption(e => e.WithWebProxy(Check.NotNull(proxy, nameof(proxy)))); @@ -94,6 +126,10 @@ public virtual CosmosDbContextOptionsBuilder WebProxy(IWebProxy proxy) /// Configures the timeout when connecting to the Azure Cosmos DB service. /// The number specifies the time to wait for response to come back from network peer. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// Request timeout. public virtual CosmosDbContextOptionsBuilder RequestTimeout(TimeSpan timeout) => WithOption(e => e.WithRequestTimeout(Check.NotNull(timeout, nameof(timeout)))); @@ -101,6 +137,10 @@ public virtual CosmosDbContextOptionsBuilder RequestTimeout(TimeSpan timeout) /// /// Configures the amount of time allowed for trying to establish a connection. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// Open TCP connection timeout. public virtual CosmosDbContextOptionsBuilder OpenTcpConnectionTimeout(TimeSpan timeout) => WithOption(e => e.WithOpenTcpConnectionTimeout(Check.NotNull(timeout, nameof(timeout)))); @@ -108,6 +148,10 @@ public virtual CosmosDbContextOptionsBuilder OpenTcpConnectionTimeout(TimeSpan t /// /// Configures the amount of idle time after which unused connections are closed. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// Idle connection timeout. public virtual CosmosDbContextOptionsBuilder IdleTcpConnectionTimeout(TimeSpan timeout) => WithOption(e => e.WithIdleTcpConnectionTimeout(Check.NotNull(timeout, nameof(timeout)))); @@ -116,6 +160,10 @@ public virtual CosmosDbContextOptionsBuilder IdleTcpConnectionTimeout(TimeSpan t /// Configures the maximum number of concurrent connections allowed for the target service endpoint /// in the Azure Cosmos DB service. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The maximum number of concurrent connections allowed. public virtual CosmosDbContextOptionsBuilder GatewayModeMaxConnectionLimit(int connectionLimit) => WithOption(e => e.WithGatewayModeMaxConnectionLimit(Check.NotNull(connectionLimit, nameof(connectionLimit)))); @@ -125,6 +173,10 @@ public virtual CosmosDbContextOptionsBuilder GatewayModeMaxConnectionLimit(int c /// Together with MaxRequestsPerTcpConnection, this setting limits the number of requests that are /// simultaneously sent to a single Cosmos DB back-end (MaxRequestsPerTcpConnection x MaxTcpConnectionPerEndpoint). /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The maximum number of TCP connections that may be opened to each Cosmos DB back-end. public virtual CosmosDbContextOptionsBuilder MaxTcpConnectionsPerEndpoint(int connectionLimit) => WithOption(e => e.WithMaxTcpConnectionsPerEndpoint(Check.NotNull(connectionLimit, nameof(connectionLimit)))); @@ -133,15 +185,23 @@ public virtual CosmosDbContextOptionsBuilder MaxTcpConnectionsPerEndpoint(int co /// Configures the number of requests allowed simultaneously over a single TCP connection. /// When more requests are in flight simultaneously, the direct/TCP client will open additional connections. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// The number of requests allowed simultaneously over a single TCP connection. public virtual CosmosDbContextOptionsBuilder MaxRequestsPerTcpConnection(int requestLimit) => WithOption(e => e.WithMaxRequestsPerTcpConnection(Check.NotNull(requestLimit, nameof(requestLimit)))); /// - /// Sets the boolean to only return the headers and status code in the Cosmos DB response for write item operation - /// like Create, Upsert, Patch and Replace. Setting the option to false will cause the response to have a null resource. - /// This reduces networking and CPU load by not sending the resource back over the network and serializing it on the client. + /// Sets the boolean to only return the headers and status code in the Cosmos DB response for write item operation + /// like Create, Upsert, Patch and Replace. Setting the option to false will cause the response to have a null resource. + /// This reduces networking and CPU load by not sending the resource back over the network and serializing it on the client. /// + /// + /// See Using DbContextOptions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// /// to have null resource public virtual CosmosDbContextOptionsBuilder ContentResponseOnWriteEnabled(bool enabled = true) => WithOption(e => e.ContentResponseOnWriteEnabled(Check.NotNull(enabled, nameof(enabled)))); diff --git a/src/EFCore.Cosmos/Metadata/Conventions/ContextContainerConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/ContextContainerConvention.cs index 64a01588809..9fa183b0f7e 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/ContextContainerConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/ContextContainerConvention.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the default container name as the context type name. /// + /// + /// See Model building conventions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class ContextContainerConvention : IModelInitializedConvention { /// diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs index 623a51283c6..8ecce2c4d49 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs @@ -11,6 +11,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the discriminator value for entity types as the entity type name. /// + /// + /// See Model building conventions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class CosmosDiscriminatorConvention : DiscriminatorConvention, IForeignKeyOwnershipChangedConvention, diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosInversePropertyAttributeConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosInversePropertyAttributeConvention.cs index ac5f1f8bc4b..e6378a45ca5 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosInversePropertyAttributeConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosInversePropertyAttributeConvention.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// specified on the other navigation property. /// All navigations are assumed to be targeting owned entity types for Cosmos. /// + /// + /// See Model building conventions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class CosmosInversePropertyAttributeConvention : InversePropertyAttributeConvention { /// diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosKeyDiscoveryConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosKeyDiscoveryConvention.cs index c59ba70bf5f..a3291a67d77 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosKeyDiscoveryConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosKeyDiscoveryConvention.cs @@ -13,6 +13,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that finds primary key property for the entity type based on the names /// and adds the partition key to it if present. /// + /// + /// See Model building conventions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class CosmosKeyDiscoveryConvention : KeyDiscoveryConvention, IEntityTypeAnnotationChangedConvention diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosManyToManyJoinEntityTypeConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosManyToManyJoinEntityTypeConvention.cs index 0947faabcff..282addc0850 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosManyToManyJoinEntityTypeConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosManyToManyJoinEntityTypeConvention.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that creates a join entity type for a many-to-many relationship /// and adds a partition key to it if the related types share one. /// + /// + /// See Model building conventions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class CosmosManyToManyJoinEntityTypeConvention : ManyToManyJoinEntityTypeConvention, IEntityTypeAnnotationChangedConvention diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosRelationshipDiscoveryConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosRelationshipDiscoveryConvention.cs index 5997d87deb0..10e5a27839b 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosRelationshipDiscoveryConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosRelationshipDiscoveryConvention.cs @@ -13,6 +13,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// as long as there is no ambiguity as to which is the corresponding inverse navigation. /// All navigations are assumed to be targeting owned entity types for Cosmos. /// + /// + /// See Model building conventions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class CosmosRelationshipDiscoveryConvention : RelationshipDiscoveryConvention { /// diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosRuntimeModelConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosRuntimeModelConvention.cs index 641e3e7dbcb..734f83b8cfb 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosRuntimeModelConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosRuntimeModelConvention.cs @@ -13,6 +13,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that creates an optimized copy of the mutable model. This convention is typically /// implemented by database providers to update provider annotations when creating a read-only model. /// + /// + /// See Model building conventions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class CosmosRuntimeModelConvention : RuntimeModelConvention { /// diff --git a/src/EFCore.Cosmos/Metadata/Conventions/ETagPropertyConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/ETagPropertyConvention.cs index fb955092bde..a0db9c7dc08 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/ETagPropertyConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/ETagPropertyConvention.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Conventions /// /// A convention that adds etag metadata on the concurrency token, if present. /// + /// + /// See Model building conventions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class ETagPropertyConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs index 97a8d3a305e..1d733dccadb 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs @@ -21,6 +21,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// This convention also adds the '__jObject' containing the JSON object returned by the store. /// /// + /// + /// See Model building conventions, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class StoreKeyConvention : IEntityTypeAddedConvention, IPropertyAnnotationChangedConvention, diff --git a/src/EFCore.Cosmos/ValueGeneration/IdValueGeneratorFactory.cs b/src/EFCore.Cosmos/ValueGeneration/IdValueGeneratorFactory.cs index 588b15f44a4..5b2f4307a30 100644 --- a/src/EFCore.Cosmos/ValueGeneration/IdValueGeneratorFactory.cs +++ b/src/EFCore.Cosmos/ValueGeneration/IdValueGeneratorFactory.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.ValueGeneration /// /// A factory that creates value generators for the 'id' property that combines the primary key values. /// + /// + /// See EF Core value generation, and + /// Accessing Azure Cosmos DB with EF Core for more information. + /// public class IdValueGeneratorFactory : ValueGeneratorFactory { /// diff --git a/src/EFCore.InMemory/Diagnostics/InMemoryEventId.cs b/src/EFCore.InMemory/Diagnostics/InMemoryEventId.cs index 7d72b8b5508..69ab58f665d 100644 --- a/src/EFCore.InMemory/Diagnostics/InMemoryEventId.cs +++ b/src/EFCore.InMemory/Diagnostics/InMemoryEventId.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// behavior of warnings. /// /// + /// + /// See Logging, events, and diagnostics, and + /// The EF Core in-memory database provider for more information. + /// public static class InMemoryEventId { // Warning: These values must not change between releases. diff --git a/src/EFCore.InMemory/Extensions/InMemoryDatabaseFacadeExtensions.cs b/src/EFCore.InMemory/Extensions/InMemoryDatabaseFacadeExtensions.cs index 775e2bb278a..8ed648126af 100644 --- a/src/EFCore.InMemory/Extensions/InMemoryDatabaseFacadeExtensions.cs +++ b/src/EFCore.InMemory/Extensions/InMemoryDatabaseFacadeExtensions.cs @@ -23,6 +23,9 @@ public static class InMemoryDatabaseFacadeExtensions /// provider to use as part of configuring the context. /// /// + /// + /// See The EF Core in-memory database provider for more information. + /// /// The facade from . /// if the in-memory database is being used. public static bool IsInMemory(this DatabaseFacade database) diff --git a/src/EFCore.InMemory/Extensions/InMemoryDbContextOptionsExtensions.cs b/src/EFCore.InMemory/Extensions/InMemoryDbContextOptionsExtensions.cs index d2f3ce411a0..cec2ba03d14 100644 --- a/src/EFCore.InMemory/Extensions/InMemoryDbContextOptionsExtensions.cs +++ b/src/EFCore.InMemory/Extensions/InMemoryDbContextOptionsExtensions.cs @@ -24,6 +24,10 @@ public static class InMemoryDbContextOptionsExtensions /// cref="UseInMemoryDatabase{TContext}(DbContextOptionsBuilder{TContext},string,InMemoryDatabaseRoot,Action{InMemoryDbContextOptionsBuilder})" /> /// passing a shared on which to root the database. /// + /// + /// See Using DbContextOptions, and + /// The EF Core in-memory database provider for more information. + /// /// The type of context being configured. /// The builder being used to configure the context. /// @@ -47,6 +51,10 @@ public static DbContextOptionsBuilder UseInMemoryDatabase( /// /// passing a shared on which to root the database. /// + /// + /// See Using DbContextOptions, and + /// The EF Core in-memory database provider for more information. + /// /// The builder being used to configure the context. /// /// The name of the in-memory database. This allows the scope of the in-memory database to be controlled @@ -65,6 +73,10 @@ public static DbContextOptionsBuilder UseInMemoryDatabase( /// The in-memory database is shared anywhere the same name is used, but only for a given /// service provider. /// + /// + /// See Using DbContextOptions, and + /// The EF Core in-memory database provider for more information. + /// /// The type of context being configured. /// The builder being used to configure the context. /// @@ -92,6 +104,10 @@ public static DbContextOptionsBuilder UseInMemoryDatabase( /// The in-memory database is shared anywhere the same name is used, but only for a given /// service provider. /// + /// + /// See Using DbContextOptions, and + /// The EF Core in-memory database provider for more information. + /// /// The builder being used to configure the context. /// /// The name of the in-memory database. This allows the scope of the in-memory database to be controlled diff --git a/src/EFCore.InMemory/Extensions/InMemoryEntityTypeBuilderExtensions.cs b/src/EFCore.InMemory/Extensions/InMemoryEntityTypeBuilderExtensions.cs index be1dca32548..430684cea76 100644 --- a/src/EFCore.InMemory/Extensions/InMemoryEntityTypeBuilderExtensions.cs +++ b/src/EFCore.InMemory/Extensions/InMemoryEntityTypeBuilderExtensions.cs @@ -14,11 +14,19 @@ namespace Microsoft.EntityFrameworkCore /// /// Extension methods for for the in-memory provider. /// + /// + /// See Modeling entity types and relationships, and + /// The EF Core in-memory database provider for more information. + /// public static class InMemoryEntityTypeBuilderExtensions { /// /// Configures a query used to provide data for an entity type. /// + /// + /// See Modeling entity types and relationships, and + /// The EF Core in-memory database provider for more information. + /// /// The builder for the entity type being configured. /// The query that will provide the underlying data for the entity type. /// The same builder instance so that multiple calls can be chained. @@ -36,6 +44,10 @@ public static EntityTypeBuilder ToInMemoryQuery( /// /// Configures a query used to provide data for an entity type. /// + /// + /// See Modeling entity types and relationships, and + /// The EF Core in-memory database provider for more information. + /// /// The builder for the entity type being configured. /// The query that will provide the underlying data for the entity type. /// The same builder instance so that multiple calls can be chained. @@ -54,6 +66,10 @@ public static EntityTypeBuilder ToInMemoryQuery( /// /// Configures a query used to provide data for an entity type. /// + /// + /// See Modeling entity types and relationships, and + /// The EF Core in-memory database provider for more information. + /// /// The builder for the entity type being configured. /// The query that will provide the underlying data for the entity type. /// Indicates whether the configuration was specified using a data annotation. @@ -78,6 +94,10 @@ public static EntityTypeBuilder ToInMemoryQuery( /// /// Returns a value indicating whether the given in-memory query can be set from the current configuration source. /// + /// + /// See Modeling entity types and relationships, and + /// The EF Core in-memory database provider for more information. + /// /// The builder for the entity type being configured. /// The query that will provide the underlying data for the keyless entity type. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.InMemory/Extensions/InMemoryEntityTypeExtensions.cs b/src/EFCore.InMemory/Extensions/InMemoryEntityTypeExtensions.cs index 13a78413c43..a569ff8e8dd 100644 --- a/src/EFCore.InMemory/Extensions/InMemoryEntityTypeExtensions.cs +++ b/src/EFCore.InMemory/Extensions/InMemoryEntityTypeExtensions.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore /// /// Extension methods for for the in-memory provider. /// + /// + /// See Modeling entity types and relationships, and + /// The EF Core in-memory database provider for more information. + /// public static class InMemoryEntityTypeExtensions { /// diff --git a/src/EFCore.InMemory/Infrastructure/InMemoryDbContextOptionsBuilder.cs b/src/EFCore.InMemory/Infrastructure/InMemoryDbContextOptionsBuilder.cs index 36f7d0aa4e5..9d086688444 100644 --- a/src/EFCore.InMemory/Infrastructure/InMemoryDbContextOptionsBuilder.cs +++ b/src/EFCore.InMemory/Infrastructure/InMemoryDbContextOptionsBuilder.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Using DbContextOptions, and + /// The EF Core in-memory database provider for more information. + /// public class InMemoryDbContextOptionsBuilder : IInMemoryDbContextOptionsBuilderInfrastructure { /// @@ -46,6 +50,10 @@ DbContextOptionsBuilder IInMemoryDbContextOptionsBuilderInfrastructure.OptionsBu /// Enables nullability check for all properties across all entities within the in-memory database. /// /// + /// + /// See Using DbContextOptions, and + /// The EF Core in-memory database provider for more information. + /// /// If , then nullability check is enforced. /// The same builder instance so that multiple calls can be chained. public virtual InMemoryDbContextOptionsBuilder EnableNullChecks(bool nullChecksEnabled = true) diff --git a/src/EFCore.InMemory/Metadata/Conventions/DefiningQueryRewritingConvention.cs b/src/EFCore.InMemory/Metadata/Conventions/DefiningQueryRewritingConvention.cs index d5339856a11..3282467b5ab 100644 --- a/src/EFCore.InMemory/Metadata/Conventions/DefiningQueryRewritingConvention.cs +++ b/src/EFCore.InMemory/Metadata/Conventions/DefiningQueryRewritingConvention.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// This makes them consistent with how DbSet accesses in the actual queries are represented, which allows for easier processing in the /// query pipeline. /// + /// + /// See Model building conventions, and + /// The EF Core in-memory database provider for more information. + /// public class DefiningQueryRewritingConvention : QueryFilterRewritingConvention { /// diff --git a/src/EFCore.InMemory/Metadata/Conventions/InMemoryConventionSetBuilder.cs b/src/EFCore.InMemory/Metadata/Conventions/InMemoryConventionSetBuilder.cs index 21ca3ce56f3..fca62502306 100644 --- a/src/EFCore.InMemory/Metadata/Conventions/InMemoryConventionSetBuilder.cs +++ b/src/EFCore.InMemory/Metadata/Conventions/InMemoryConventionSetBuilder.cs @@ -21,6 +21,10 @@ namespace Microsoft.EntityFrameworkCore.InMemory.Metadata.Conventions /// The implementations do not need to be thread-safe. /// /// + /// + /// See Model building conventions, and + /// The EF Core in-memory database provider for more information. + /// public class InMemoryConventionSetBuilder : ProviderConventionSetBuilder { /// diff --git a/src/EFCore.InMemory/Storage/InMemoryDatabaseRoot.cs b/src/EFCore.InMemory/Storage/InMemoryDatabaseRoot.cs index 78126d3f8c8..dd3bdcd86e5 100644 --- a/src/EFCore.InMemory/Storage/InMemoryDatabaseRoot.cs +++ b/src/EFCore.InMemory/Storage/InMemoryDatabaseRoot.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// + /// + /// See The EF Core in-memory database provider for more information. + /// public sealed class InMemoryDatabaseRoot { /// diff --git a/src/EFCore.Proxies/EFCore.Proxies.csproj b/src/EFCore.Proxies/EFCore.Proxies.csproj index 66464791283..2bae9a4cc08 100644 --- a/src/EFCore.Proxies/EFCore.Proxies.csproj +++ b/src/EFCore.Proxies/EFCore.Proxies.csproj @@ -1,13 +1,13 @@  - Lazy-loading proxies for Entity Framework Core. + Lazy loading proxies for Entity Framework Core. net6.0 3.6 Microsoft.EntityFrameworkCore.Proxies Microsoft.EntityFrameworkCore true - $(PackageTags);Lazy-loading + $(PackageTags);Lazy loading diff --git a/src/EFCore.Proxies/Proxies/Internal/ProxiesOptionsExtension.cs b/src/EFCore.Proxies/Proxies/Internal/ProxiesOptionsExtension.cs index e42f0ad5185..b0117ac07fe 100644 --- a/src/EFCore.Proxies/Proxies/Internal/ProxiesOptionsExtension.cs +++ b/src/EFCore.Proxies/Proxies/Internal/ProxiesOptionsExtension.cs @@ -182,9 +182,9 @@ public override bool IsDatabaseProvider public override string LogFragment => _logFragment ??= Extension.UseLazyLoadingProxies && Extension.UseChangeTrackingProxies - ? "using lazy-loading and change tracking proxies " + ? "using lazy loading and change tracking proxies " : Extension.UseLazyLoadingProxies - ? "using lazy-loading proxies " + ? "using lazy loading proxies " : Extension.UseChangeTrackingProxies ? "using change tracking proxies " : ""; diff --git a/src/EFCore.Proxies/ProxiesExtensions.cs b/src/EFCore.Proxies/ProxiesExtensions.cs index 3413d47a90c..4b9d6f4be54 100644 --- a/src/EFCore.Proxies/ProxiesExtensions.cs +++ b/src/EFCore.Proxies/ProxiesExtensions.cs @@ -90,7 +90,7 @@ public static DbContextOptionsBuilder UseChangeTrackingProxies /// - /// Turns on the creation of lazy-loading proxies. + /// Turns on the creation of lazy loading proxies. /// /// /// Note that this requires appropriate services to be available in the EF internal service provider. Normally this @@ -102,7 +102,7 @@ public static DbContextOptionsBuilder UseChangeTrackingProxies /// or exposed AddDbContext. /// - /// to use lazy-loading proxies; to prevent their use. + /// to use lazy loading proxies; to prevent their use. /// The same builder to allow method calls to be chained. public static DbContextOptionsBuilder UseLazyLoadingProxies( this DbContextOptionsBuilder optionsBuilder, @@ -122,7 +122,7 @@ public static DbContextOptionsBuilder UseLazyLoadingProxies( /// /// - /// Turns on the creation of lazy-loading proxies. + /// Turns on the creation of lazy loading proxies. /// /// /// Note that this requires appropriate services to be available in the EF internal service provider. Normally this @@ -135,7 +135,7 @@ public static DbContextOptionsBuilder UseLazyLoadingProxies( /// The options builder, as passed to /// or exposed AddDbContext. /// - /// to use lazy-loading proxies; to prevent their use. + /// to use lazy loading proxies; to prevent their use. /// The same builder to allow method calls to be chained. public static DbContextOptionsBuilder UseLazyLoadingProxies( this DbContextOptionsBuilder optionsBuilder, diff --git a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions.cs b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions.cs index d709ca34762..b0c89c67715 100644 --- a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions.cs +++ b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions.cs @@ -10,6 +10,11 @@ namespace Microsoft.EntityFrameworkCore /// /// NetTopologySuite specific extension methods for . /// + /// + /// See Spatial data, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerNetTopologySuiteDbContextOptionsBuilderExtensions { /// diff --git a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs index 620c2c195d9..636e5d83a88 100644 --- a/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs +++ b/src/EFCore.SqlServer.NTS/Extensions/SqlServerNetTopologySuiteServiceCollectionExtensions.cs @@ -15,6 +15,11 @@ namespace Microsoft.Extensions.DependencyInjection /// /// EntityFrameworkCore.SqlServer.NetTopologySuite extension methods for . /// + /// + /// See Spatial data, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerNetTopologySuiteServiceCollectionExtensions { /// diff --git a/src/EFCore.SqlServer/Diagnostics/ConflictingValueGenerationStrategiesEventData.cs b/src/EFCore.SqlServer/Diagnostics/ConflictingValueGenerationStrategiesEventData.cs index fbaf4110786..57e176c4c17 100644 --- a/src/EFCore.SqlServer/Diagnostics/ConflictingValueGenerationStrategiesEventData.cs +++ b/src/EFCore.SqlServer/Diagnostics/ConflictingValueGenerationStrategiesEventData.cs @@ -11,6 +11,11 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// A event payload class for events that have /// a property. /// + /// + /// See Logging, events, and diagnostics, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class ConflictingValueGenerationStrategiesEventData : EventData { /// diff --git a/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs b/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs index 82f65737858..52bae2587dd 100644 --- a/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs +++ b/src/EFCore.SqlServer/Diagnostics/SqlServerEventId.cs @@ -16,6 +16,11 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// behavior of warnings. /// /// + /// + /// See Logging, events, and diagnostics, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerEventId { // Warning: These values must not change between releases. diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDatabaseFacadeExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDatabaseFacadeExtensions.cs index 211a7d073d7..30a728866bb 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDatabaseFacadeExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDatabaseFacadeExtensions.cs @@ -24,6 +24,10 @@ public static class SqlServerDatabaseFacadeExtensions /// provider to use as part of configuring the context. /// /// + /// + /// See Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The facade from . /// if SQL Server is being used; otherwise. public static bool IsSqlServer(this DatabaseFacade database) diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbContextOptionsBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbContextOptionsBuilderExtensions.cs index c12cef6bd29..4fda9b5dfd0 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbContextOptionsBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbContextOptionsBuilderExtensions.cs @@ -14,6 +14,11 @@ namespace Microsoft.EntityFrameworkCore /// /// SQL Server specific extension methods for . /// + /// + /// See Using DbContextOptions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerDbContextOptionsExtensions { /// @@ -27,6 +32,11 @@ public static class SqlServerDbContextOptionsExtensions /// Set a connection string using . /// /// + /// + /// See Using DbContextOptions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder being used to configure the context. /// An optional action to allow additional SQL Server specific configuration. /// The options builder so that further configuration can be chained. @@ -48,6 +58,11 @@ public static DbContextOptionsBuilder UseSqlServer( /// /// Configures the context to connect to a Microsoft SQL Server database. /// + /// + /// See Using DbContextOptions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder being used to configure the context. /// The connection string of the database to connect to. /// An optional action to allow additional SQL Server specific configuration. @@ -74,6 +89,11 @@ public static DbContextOptionsBuilder UseSqlServer( /// /// Configures the context to connect to a Microsoft SQL Server database. /// + /// + /// See Using DbContextOptions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder being used to configure the context. /// /// An existing to be used to connect to the database. If the connection is @@ -111,6 +131,11 @@ public static DbContextOptionsBuilder UseSqlServer( /// Set a connection string using . /// /// + /// + /// See Using DbContextOptions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder being used to configure the context. /// An optional action to allow additional SQL Server specific configuration. /// The options builder so that further configuration can be chained. @@ -124,6 +149,11 @@ public static DbContextOptionsBuilder UseSqlServer( /// /// Configures the context to connect to a Microsoft SQL Server database. /// + /// + /// See Using DbContextOptions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The type of context to be configured. /// The builder being used to configure the context. /// The connection string of the database to connect to. @@ -141,6 +171,11 @@ public static DbContextOptionsBuilder UseSqlServer( /// /// Configures the context to connect to a Microsoft SQL Server database. /// + /// + /// See Using DbContextOptions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The type of context to be configured. /// The builder being used to configure the context. /// diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs index a9a0cfd4e60..07d0daabadb 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs @@ -12,6 +12,11 @@ namespace Microsoft.EntityFrameworkCore /// Provides CLR methods that get translated to database functions when used in LINQ to Entities queries. /// The methods on this class are accessed via . /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerDbFunctionsExtensions { /// @@ -20,8 +25,9 @@ public static class SqlServerDbFunctionsExtensions /// /// /// - /// This DbFunction method has no in-memory implementation and will throw if the query switches to client-evaluation. - /// This can happen if the query contains one or more expressions that could not be translated to the store. + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. /// /// The instance. /// The property on which the search will be performed. @@ -40,8 +46,9 @@ public static bool FreeText( /// /// /// - /// This DbFunction method has no in-memory implementation and will throw if the query switches to client-evaluation. - /// This can happen if the query contains one or more expressions that could not be translated to the store. + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. /// /// The instance. /// The property on which the search will be performed. @@ -58,8 +65,9 @@ public static bool FreeText( /// /// /// - /// This DbFunction method has no in-memory implementation and will throw if the query switches to client-evaluation. - /// This can happen if the query contains one or more expressions that could not be translated to the store. + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. /// /// The instance. /// The property on which the search will be performed. @@ -78,8 +86,9 @@ public static bool Contains( /// /// /// - /// This DbFunction method has no in-memory implementation and will throw if the query switches to client-evaluation. - /// This can happen if the query contains one or more expressions that could not be translated to the store. + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. /// /// The instance. /// The property on which the search will be performed. @@ -94,6 +103,11 @@ public static bool Contains( /// Counts the number of year boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(year, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -108,6 +122,11 @@ public static int DateDiffYear( /// Counts the number of year boundaries crossed between and . /// Corresponds to SQL Server's DATEDIFF(year, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -122,6 +141,11 @@ public static int DateDiffYear( /// Counts the number of year boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(year, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -136,6 +160,11 @@ public static int DateDiffYear( /// Counts the number of year boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(year, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -150,6 +179,11 @@ public static int DateDiffYear( /// Counts the number of month boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(month, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -164,6 +198,11 @@ public static int DateDiffMonth( /// Counts the number of month boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(month, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -178,6 +217,11 @@ public static int DateDiffMonth( /// Counts the number of month boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(month, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -192,6 +236,11 @@ public static int DateDiffMonth( /// Counts the number of month boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(month, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -206,6 +255,11 @@ public static int DateDiffMonth( /// Counts the number of day boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(day, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -220,6 +274,11 @@ public static int DateDiffDay( /// Counts the number of day boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(day, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -234,6 +293,11 @@ public static int DateDiffDay( /// Counts the number of day boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(day, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -248,6 +312,11 @@ public static int DateDiffDay( /// Counts the number of day boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(day, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -262,6 +331,11 @@ public static int DateDiffDay( /// Counts the number of hour boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(hour, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -276,6 +350,11 @@ public static int DateDiffHour( /// Counts the number of hour boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(hour, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -290,6 +369,11 @@ public static int DateDiffHour( /// Counts the number of hour boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(hour, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -304,6 +388,11 @@ public static int DateDiffHour( /// Counts the number of hour boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(hour, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -318,6 +407,11 @@ public static int DateDiffHour( /// Counts the number of hour boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(hour, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -332,6 +426,11 @@ public static int DateDiffHour( /// Counts the number of hour boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(hour, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -346,6 +445,11 @@ public static int DateDiffHour( /// Counts the number of minute boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(minute, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -360,6 +464,11 @@ public static int DateDiffMinute( /// Counts the number of minute boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(minute, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -374,6 +483,11 @@ public static int DateDiffMinute( /// Counts the number of minute boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(minute, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -388,6 +502,11 @@ public static int DateDiffMinute( /// Counts the number of minute boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(minute, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -402,6 +521,11 @@ public static int DateDiffMinute( /// Counts the number of minute boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(minute, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -416,6 +540,11 @@ public static int DateDiffMinute( /// Counts the number of minute boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(minute, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -430,6 +559,11 @@ public static int DateDiffMinute( /// Counts the number of second boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(second, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -444,6 +578,11 @@ public static int DateDiffSecond( /// Counts the number of second boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(second, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -458,6 +597,11 @@ public static int DateDiffSecond( /// Counts the number of second boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(second, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -472,6 +616,11 @@ public static int DateDiffSecond( /// Counts the number of second boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(second, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -486,6 +635,11 @@ public static int DateDiffSecond( /// Counts the number of second boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(second, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -500,6 +654,11 @@ public static int DateDiffSecond( /// Counts the number of second boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(second, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -514,6 +673,11 @@ public static int DateDiffSecond( /// Counts the number of millisecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(millisecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -528,6 +692,11 @@ public static int DateDiffMillisecond( /// Counts the number of millisecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(millisecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -542,6 +711,11 @@ public static int DateDiffMillisecond( /// Counts the number of millisecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(millisecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -556,6 +730,11 @@ public static int DateDiffMillisecond( /// Counts the number of millisecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(millisecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -570,6 +749,11 @@ public static int DateDiffMillisecond( /// Counts the number of millisecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(millisecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -584,6 +768,11 @@ public static int DateDiffMillisecond( /// Counts the number of millisecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(millisecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -598,6 +787,11 @@ public static int DateDiffMillisecond( /// Counts the number of microsecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(microsecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -612,6 +806,11 @@ public static int DateDiffMicrosecond( /// Counts the number of microsecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(microsecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -626,6 +825,11 @@ public static int DateDiffMicrosecond( /// Counts the number of microsecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(microsecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -640,6 +844,11 @@ public static int DateDiffMicrosecond( /// Counts the number of microsecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(microsecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -654,6 +863,11 @@ public static int DateDiffMicrosecond( /// Counts the number of microsecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(microsecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -668,6 +882,11 @@ public static int DateDiffMicrosecond( /// Counts the number of microsecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(microsecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -682,6 +901,11 @@ public static int DateDiffMicrosecond( /// Counts the number of nanosecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(nanosecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -696,6 +920,11 @@ public static int DateDiffNanosecond( /// Counts the number of nanosecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(nanosecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -710,6 +939,11 @@ public static int DateDiffNanosecond( /// Counts the number of nanosecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(nanosecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -724,6 +958,11 @@ public static int DateDiffNanosecond( /// Counts the number of nanosecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(nanosecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -738,6 +977,11 @@ public static int DateDiffNanosecond( /// Counts the number of nanosecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(nanosecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -752,6 +996,11 @@ public static int DateDiffNanosecond( /// Counts the number of nanosecond boundaries crossed between the and /// . Corresponds to SQL Server's DATEDIFF(nanosecond, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting timespan for the calculation. /// Ending timespan for the calculation. @@ -766,6 +1015,11 @@ public static int DateDiffNanosecond( /// Counts the number of week boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(week, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -780,6 +1034,11 @@ public static int DateDiffWeek( /// Counts the number of week boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(week, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -794,6 +1053,11 @@ public static int DateDiffWeek( /// Counts the number of week boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(week, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -808,6 +1072,11 @@ public static int DateDiffWeek( /// Counts the number of week boundaries crossed between the and . /// Corresponds to SQL Server's DATEDIFF(week, @startDate, @endDate). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Starting date for the calculation. /// Ending date for the calculation. @@ -822,6 +1091,11 @@ public static int DateDiffWeek( /// Validate if the given string is a valid date. /// Corresponds to the SQL Server's ISDATE('date'). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Expression to validate /// true for valid date and false otherwise. @@ -835,6 +1109,11 @@ public static bool IsDate( /// and millisecond. /// Corresponds to the SQL Server's DATETIMEFROMPARTS(year, month, day, hour, minute, second, millisecond). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The year (1753 through 9999). /// The month (1 through 12). @@ -862,6 +1141,11 @@ public static DateTime DateTimeFromParts( /// Initializes a new instance of the structure to the specified year, month, day. /// Corresponds to the SQL Server's DATEFROMPARTS(year, month, day). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The year (1753 through 9999). /// The month (1 through 12). @@ -879,6 +1163,11 @@ public static DateTime DateFromParts( /// fractions, and precision. /// Corresponds to the SQL Server's DATETIME2FROMPARTS(year, month, day, hour, minute, seconds, fractions, precision). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The year (1753 through 9999). /// The month (1 through 12). @@ -910,6 +1199,11 @@ public static DateTime DateTime2FromParts( /// Corresponds to the SQL Server's DATETIMEOFFSETFROMPARTS(year, month, day, hour, minute, seconds, fractions, hour_offset, /// minute_offset, precision). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The year (1753 through 9999). /// The month (1 through 12). @@ -943,6 +1237,11 @@ public static DateTimeOffset DateTimeOffsetFromParts( /// Initializes a new instance of the structure to the specified year, month, day, hour and minute. /// Corresponds to the SQL Server's SMALLDATETIMEFROMPARTS(year, month, day, hour, minute). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The year (1753 through 9999). /// The month (1 through 12). @@ -963,6 +1262,11 @@ public static DateTime SmallDateTimeFromParts( /// Initializes a new instance of the structure to the specified hour, minute, second, fractions, and /// precision. Corresponds to the SQL Server's TIMEFROMPARTS(hour, minute, seconds, fractions, precision). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The hours (0 through 23). /// The minutes (0 through 59). @@ -984,6 +1288,11 @@ public static TimeSpan TimeFromParts( /// /// Returns the number of bytes used to represent any expression. /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The value to be examined for data length. /// The number of bytes in the input value. @@ -995,6 +1304,11 @@ public static TimeSpan TimeFromParts( /// /// Returns the number of bytes used to represent any expression. /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The value to be examined for data length. /// The number of bytes in the input value. @@ -1006,6 +1320,11 @@ public static TimeSpan TimeFromParts( /// /// Returns the number of bytes used to represent any expression. /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The value to be examined for data length. /// The number of bytes in the input value. @@ -1017,6 +1336,11 @@ public static TimeSpan TimeFromParts( /// /// Returns the number of bytes used to represent any expression. /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The value to be examined for data length. /// The number of bytes in the input value. @@ -1028,6 +1352,11 @@ public static TimeSpan TimeFromParts( /// /// Returns the number of bytes used to represent any expression. /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The value to be examined for data length. /// The number of bytes in the input value. @@ -1039,6 +1368,11 @@ public static TimeSpan TimeFromParts( /// /// Returns the number of bytes used to represent any expression. /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The value to be examined for data length. /// The number of bytes in the input value. @@ -1050,6 +1384,11 @@ public static TimeSpan TimeFromParts( /// /// Returns the number of bytes used to represent any expression. /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The value to be examined for data length. /// The number of bytes in the input value. @@ -1061,6 +1400,11 @@ public static TimeSpan TimeFromParts( /// /// Returns the number of bytes used to represent any expression. /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The value to be examined for data length. /// The number of bytes in the input value. @@ -1072,6 +1416,11 @@ public static TimeSpan TimeFromParts( /// /// Returns the number of bytes used to represent any expression. /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// The value to be examined for data length. /// The number of bytes in the input value. @@ -1084,6 +1433,11 @@ public static TimeSpan TimeFromParts( /// Validate if the given string is a valid numeric. /// Corresponds to the SQL Server's ISNUMERIC(expression). /// + /// + /// See Database functions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The instance. /// Expression to validate /// for a valid numeric, otherwise . diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbSetExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbSetExtensions.cs index 1169078cff0..5aa5a947d33 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbSetExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbSetExtensions.cs @@ -3,7 +3,6 @@ using System; using System.Linq; -using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; using Microsoft.EntityFrameworkCore.Utilities; @@ -18,15 +17,21 @@ public static class SqlServerDbSetExtensions { /// /// - /// Applies temporal 'AsOf' operation on the given DbSet, which only returns elements that were present in the database at a given point in time. + /// Applies temporal 'AsOf' operation on the given DbSet, which only returns elements that were present in the database at a given + /// point in time. /// /// - /// Temporal information is stored in UTC format on the database, so any arguments in local time may lead to unexpected results. + /// Temporal information is stored in UTC format on the database, so any arguments in local time may lead to + /// unexpected results. /// /// /// Temporal queries are always set as 'NoTracking'. /// /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// Source DbSet on which the temporal operation is applied. /// representing a point in time for which the results should be returned. /// An representing the entities at a given point in time. @@ -50,21 +55,29 @@ public static IQueryable TemporalAsOf( /// /// - /// Applies temporal 'FromTo' operation on the given DbSet, which only returns elements that were present in the database between two points in time. + /// Applies temporal 'FromTo' operation on the given DbSet, which only returns elements that were present in the database between two + /// points in time. /// /// - /// Elements that were created at the starting point as well as elements that were removed at the end point are not included in the results. + /// Elements that were created at the starting point as well as elements that were removed at the end point are not included in the + /// results. /// /// - /// All versions of entities in that were present within the time range are returned, so it is possible to return multiple entities with the same key. + /// All versions of entities in that were present within the time range are returned, so it is possible to return multiple entities + /// with the same key. /// /// - /// Temporal information is stored in UTC format on the database, so any arguments in local time may lead to unexpected results. + /// Temporal information is stored in UTC format on the database, so any arguments in local time may lead to + /// unexpected results. /// /// /// Temporal queries are always set as 'NoTracking'. /// /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// Source DbSet on which the temporal operation is applied. /// Point in time representing the start of the period for which results should be returned. /// Point in time representing the end of the period for which results should be returned. @@ -91,21 +104,29 @@ public static IQueryable TemporalFromTo( /// /// - /// Applies temporal 'Between' operation on the given DbSet, which only returns elements that were present in the database between two points in time. + /// Applies temporal 'Between' operation on the given DbSet, which only returns elements that were present in the database between two + /// points in time. /// /// - /// Elements that were created at the starting point are not included in the results, however elements that were removed at the end point are included in the results. + /// Elements that were created at the starting point are not included in the results, however elements that were removed at the end + /// point are included in the results. /// /// - /// All versions of entities in that were present within the time range are returned, so it is possible to return multiple entities with the same key. + /// All versions of entities in that were present within the time range are returned, so it is possible to return multiple entities + /// with the same key. /// /// - /// Temporal information is stored in UTC format on the database, so any arguments in local time may lead to unexpected results. + /// Temporal information is stored in UTC format on the database, so any arguments in local time may lead to + /// unexpected results. /// /// /// Temporal queries are always set as 'NoTracking'. /// /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// Source DbSet on which the temporal operation is applied. /// Point in time representing the start of the period for which results should be returned. /// Point in time representing the end of the period for which results should be returned. @@ -132,21 +153,29 @@ public static IQueryable TemporalBetween( /// /// - /// Applies temporal 'ContainedIn' operation on the given DbSet, which only returns elements that were present in the database between two points in time. + /// Applies temporal 'ContainedIn' operation on the given DbSet, which only returns elements that were present in the database between + /// two points in time. /// /// - /// Elements that were created at the starting point as well as elements that were removed at the end point are included in the results. + /// Elements that were created at the starting point as well as elements that were removed at the end point are included in the + /// results. /// /// - /// All versions of entities in that were present within the time range are returned, so it is possible to return multiple entities with the same key. + /// All versions of entities in that were present within the time range are returned, so it is possible to return multiple entities + /// with the same key. /// /// - /// Temporal information is stored in UTC format on the database, so any arguments in local time may lead to unexpected results. + /// Temporal information is stored in UTC format on the database, so any arguments in local time may lead to + /// unexpected results. /// /// /// Temporal queries are always set as 'NoTracking'. /// /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// Source DbSet on which the temporal operation is applied. /// Point in time representing the start of the period for which results should be returned. /// Point in time representing the end of the period for which results should be returned. @@ -173,12 +202,17 @@ public static IQueryable TemporalContainedIn( /// /// - /// Applies temporal 'All' operation on the given DbSet, which returns all historical versions of the entities as well as their current state. + /// Applies temporal 'All' operation on the given DbSet, which returns all historical versions of the entities as well as their current + /// state. /// /// /// Temporal queries are always set as 'NoTracking'. /// /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// Source DbSet on which the temporal operation is applied. /// An representing the entities and their historical versions. public static IQueryable TemporalAll( diff --git a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeBuilderExtensions.cs index 49835d990fc..5b3659496a5 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeBuilderExtensions.cs @@ -11,11 +11,20 @@ namespace Microsoft.EntityFrameworkCore /// /// SQL Server specific extension methods for . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerEntityTypeBuilderExtensions { /// /// Configures the table that the entity maps to when targeting SQL Server as memory-optimized. /// + /// + /// See Using SQL Server memory-optimized tables with EF Core + /// for more information. + /// /// The builder for the entity type being configured. /// A value indicating whether the table is memory-optimized. /// The same builder instance so that multiple calls can be chained. @@ -33,6 +42,10 @@ public static EntityTypeBuilder IsMemoryOptimized( /// /// Configures the table that the entity maps to when targeting SQL Server as memory-optimized. /// + /// + /// See Using SQL Server memory-optimized tables with EF Core + /// for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// A value indicating whether the table is memory-optimized. @@ -46,6 +59,10 @@ public static EntityTypeBuilder IsMemoryOptimized( /// /// Configures the table that the entity maps to when targeting SQL Server as memory-optimized. /// + /// + /// See Using SQL Server memory-optimized tables with EF Core + /// for more information. + /// /// The builder for the entity type being configured. /// A value indicating whether the table is memory-optimized. /// The same builder instance so that multiple calls can be chained. @@ -63,6 +80,10 @@ public static OwnedNavigationBuilder IsMemoryOptimized( /// /// Configures the table that the entity maps to when targeting SQL Server as memory-optimized. /// + /// + /// See Using SQL Server memory-optimized tables with EF Core + /// for more information. + /// /// The entity type being configured. /// The entity type that this relationship targets. /// The builder for the entity type being configured. @@ -79,6 +100,10 @@ public static OwnedNavigationBuilder IsMemoryOptimized< /// /// Configures the table that the entity maps to when targeting SQL Server as memory-optimized. /// + /// + /// See Using SQL Server memory-optimized tables with EF Core + /// for more information. + /// /// The builder for the entity type being configured. /// A value indicating whether the table is memory-optimized. /// Indicates whether the configuration was specified using a data annotation. @@ -103,6 +128,10 @@ public static OwnedNavigationBuilder IsMemoryOptimized< /// /// Returns a value indicating whether the mapped table can be configured as memory-optimized. /// + /// + /// See Using SQL Server memory-optimized tables with EF Core + /// for more information. + /// /// The builder for the entity type being configured. /// A value indicating whether the table is memory-optimized. /// Indicates whether the configuration was specified using a data annotation. @@ -120,6 +149,10 @@ public static bool CanSetIsMemoryOptimized( /// /// Configures the table as temporal. /// + /// + /// See Using SQL Server memory-optimized tables with EF Core + /// for more information. + /// /// The builder for the entity being configured. /// A value indicating whether the table is temporal. /// Indicates whether the configuration was specified using a data annotation. @@ -145,6 +178,10 @@ public static bool CanSetIsMemoryOptimized( /// /// Returns a value indicating whether the mapped table can be configured as temporal. /// + /// + /// See Using SQL Server memory-optimized tables with EF Core + /// for more information. + /// /// The builder for the entity type being configured. /// A value indicating whether the table is temporal. /// Indicates whether the configuration was specified using a data annotation. @@ -162,6 +199,10 @@ public static bool CanSetIsTemporal( /// /// Configures a history table name for the entity mapped to a temporal table. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the entity being configured. /// The name of the history table. /// Indicates whether the configuration was specified using a data annotation. @@ -187,6 +228,10 @@ public static bool CanSetIsTemporal( /// /// Returns a value indicating whether the given history table name can be set for the entity. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the entity type being configured. /// The name of the history table. /// Indicates whether the configuration was specified using a data annotation. @@ -205,6 +250,10 @@ public static bool CanSetHistoryTableName( /// /// Configures a history table schema for the entity mapped to a temporal table. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the entity being configured. /// The schema of the history table. /// Indicates whether the configuration was specified using a data annotation. @@ -230,6 +279,10 @@ public static bool CanSetHistoryTableName( /// /// Returns a value indicating whether the mapped table can have history table schema. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the entity type being configured. /// The schema of the history table. /// Indicates whether the configuration was specified using a data annotation. @@ -247,6 +300,10 @@ public static bool CanSetHistoryTableSchema( /// /// Configures a period start property for the entity mapped to a temporal table. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the entity being configured. /// The name of the period start property. /// Indicates whether the configuration was specified using a data annotation. @@ -272,6 +329,10 @@ public static bool CanSetHistoryTableSchema( /// /// Returns a value indicating whether the mapped table can have period start property. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the entity type being configured. /// The name of the period start property. /// Indicates whether the configuration was specified using a data annotation. @@ -289,6 +350,10 @@ public static bool CanSetPeriodStart( /// /// Configures a period end property for the entity mapped to a temporal table. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the entity being configured. /// The name of the period end property. /// Indicates whether the configuration was specified using a data annotation. @@ -314,6 +379,10 @@ public static bool CanSetPeriodStart( /// /// Returns a value indicating whether the mapped table can have period end property. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the entity type being configured. /// The name of the period end property. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs index 60deb668e82..0b7cadc06d0 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs @@ -12,6 +12,11 @@ namespace Microsoft.EntityFrameworkCore /// /// Entity type extension methods for SQL Server-specific metadata. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerEntityTypeExtensions { private const string DefaultHistoryTableNameSuffix = "History"; diff --git a/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs index 72149c39d5c..ed340337d68 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerIndexBuilderExtensions.cs @@ -18,11 +18,21 @@ namespace Microsoft.EntityFrameworkCore /// /// SQL Server specific extension methods for . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerIndexBuilderExtensions { /// /// Configures whether the index is clustered when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the index being configured. /// A value indicating whether the index is clustered. /// A builder to further configure the index. @@ -38,6 +48,11 @@ public static IndexBuilder IsClustered(this IndexBuilder indexBuilder, bool clus /// /// Configures whether the index is clustered when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the index being configured. /// A value indicating whether the index is clustered. /// A builder to further configure the index. @@ -49,6 +64,11 @@ public static IndexBuilder IsClustered( /// /// Configures whether the index is clustered when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the index being configured. /// A value indicating whether the index is clustered. /// Indicates whether the configuration was specified using a data annotation. @@ -73,6 +93,11 @@ public static IndexBuilder IsClustered( /// /// Returns a value indicating whether the index can be configured as clustered. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the index being configured. /// A value indicating whether the index is clustered. /// Indicates whether the configuration was specified using a data annotation. @@ -90,6 +115,11 @@ public static bool CanSetIsClustered( /// /// Configures index include properties when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the index being configured. /// An array of property names to be used in 'include' clause. /// A builder to further configure the index. @@ -106,6 +136,11 @@ public static IndexBuilder IncludeProperties(this IndexBuilder indexBuilder, par /// /// Configures index include properties when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the index being configured. /// An array of property names to be used in 'include' clause. /// A builder to further configure the index. @@ -124,6 +159,11 @@ public static IndexBuilder IncludeProperties( /// /// Configures index include properties when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the index being configured. /// /// @@ -153,6 +193,11 @@ public static IndexBuilder IncludeProperties( /// /// Configures index include properties when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the index being configured. /// An array of property names to be used in 'include' clause. /// Indicates whether the configuration was specified using a data annotation. @@ -178,6 +223,11 @@ public static IndexBuilder IncludeProperties( /// /// Returns a value indicating whether the given include properties can be set. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the index being configured. /// An array of property names to be used in 'include' clause. /// Indicates whether the configuration was specified using a data annotation. @@ -199,6 +249,11 @@ public static bool CanSetIncludeProperties( /// /// Configures whether the index is created with online 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. + /// /// The builder for the index being configured. /// A value indicating whether the index is created with online option. /// A builder to further configure the index. @@ -214,6 +269,11 @@ public static IndexBuilder IsCreatedOnline(this IndexBuilder indexBuilder, bool /// /// Configures whether the index is created with online 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. + /// /// The builder for the index being configured. /// A value indicating whether the index is created with online option. /// A builder to further configure the index. @@ -225,6 +285,11 @@ public static IndexBuilder IsCreatedOnline( /// /// Configures whether the index is created with online 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. + /// /// The builder for the index being configured. /// A value indicating whether the index is created with online option. /// Indicates whether the configuration was specified using a data annotation. @@ -250,6 +315,11 @@ public static IndexBuilder IsCreatedOnline( /// /// Returns a value indicating whether the index can be configured with online 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. + /// /// The builder for the index being configured. /// A value indicating whether the index is created with online option. /// Indicates whether the configuration was specified using a data annotation. @@ -271,6 +341,11 @@ public static bool CanSetIsCreatedOnline( /// /// Configures whether the index is created with fill factor 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. + /// /// The builder for the index being configured. /// A value indicating whether the index is created with fill factor option. /// A builder to further configure the index. @@ -286,6 +361,11 @@ public static IndexBuilder HasFillFactor(this IndexBuilder indexBuilder, int fil /// /// Configures whether the index is created with fill factor 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. + /// /// The builder for the index being configured. /// A value indicating whether the index is created with fill factor option. /// A builder to further configure the index. @@ -297,6 +377,11 @@ public static IndexBuilder HasFillFactor( /// /// Configures whether the index is created with fill factor 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. + /// /// The builder for the index being configured. /// A value indicating whether the index is created with fill factor option. /// Indicates whether the configuration was specified using a data annotation. @@ -322,6 +407,11 @@ public static IndexBuilder HasFillFactor( /// /// Returns a value indicating whether the index can be configured with fill factor 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. + /// /// The builder for the index being configured. /// A value indicating whether the index is created with fill factor option. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.SqlServer/Extensions/SqlServerIndexExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerIndexExtensions.cs index 596d24da974..0b0f629853d 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerIndexExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerIndexExtensions.cs @@ -13,6 +13,11 @@ namespace Microsoft.EntityFrameworkCore /// /// Index extension methods for SQL Server-specific metadata. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerIndexExtensions { /// diff --git a/src/EFCore.SqlServer/Extensions/SqlServerKeyBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerKeyBuilderExtensions.cs index 93a9a9c802d..35e65b72a68 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerKeyBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerKeyBuilderExtensions.cs @@ -11,11 +11,21 @@ namespace Microsoft.EntityFrameworkCore /// /// SQL Server specific extension methods for . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerKeyBuilderExtensions { /// /// Configures whether the key is clustered when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the key being configured. /// A value indicating whether the key is clustered. /// The same builder instance so that multiple calls can be chained. @@ -31,6 +41,11 @@ public static KeyBuilder IsClustered(this KeyBuilder keyBuilder, bool clustered /// /// Configures whether the key is clustered when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the key being configured. /// A value indicating whether the key is clustered. /// The same builder instance so that multiple calls can be chained. @@ -42,6 +57,11 @@ public static KeyBuilder IsClustered( /// /// Configures whether the key is clustered when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the key being configured. /// A value indicating whether the key is clustered. /// Indicates whether the configuration was specified using a data annotation. @@ -66,6 +86,11 @@ public static KeyBuilder IsClustered( /// /// Returns a value indicating whether the key can be configured as clustered. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the key being configured. /// A value indicating whether the key is clustered. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.SqlServer/Extensions/SqlServerKeyExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerKeyExtensions.cs index 6a1f4cfed3f..5695f289d06 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerKeyExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerKeyExtensions.cs @@ -12,6 +12,11 @@ namespace Microsoft.EntityFrameworkCore /// /// Key extension methods for SQL Server-specific metadata. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerKeyExtensions { /// diff --git a/src/EFCore.SqlServer/Extensions/SqlServerMigrationBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerMigrationBuilderExtensions.cs index 65cc5add527..20e72414997 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerMigrationBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerMigrationBuilderExtensions.cs @@ -17,6 +17,10 @@ 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 + /// for more information. + /// /// /// The migrationBuilder from the parameters on or /// . diff --git a/src/EFCore.SqlServer/Extensions/SqlServerModelBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerModelBuilderExtensions.cs index 634d5d8557e..722610a99cc 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerModelBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerModelBuilderExtensions.cs @@ -12,12 +12,22 @@ namespace Microsoft.EntityFrameworkCore /// /// SQL Server specific extension methods for . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerModelBuilderExtensions { /// /// Configures the model to use a sequence-based hi-lo pattern to generate values for key properties /// marked as , when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The name of the sequence. /// The schema of the sequence. @@ -53,6 +63,11 @@ public static ModelBuilder UseHiLo( /// Configures the database sequence used for the hi-lo pattern to generate values for key properties /// marked as , when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The name of the sequence. /// The schema of the sequence. @@ -78,6 +93,11 @@ public static ModelBuilder UseHiLo( /// /// Returns a value indicating whether the given name and schema can be set for the hi-lo sequence. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The name of the sequence. /// The schema of the sequence. @@ -102,6 +122,11 @@ public static bool CanSetHiLoSequence( /// marked as , when targeting SQL Server. This is the default /// behavior when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The value that is used for the very first row loaded into the table. /// The incremental value that is added to the identity value of the previous row that was loaded. @@ -129,6 +154,11 @@ public static ModelBuilder UseIdentityColumns( /// marked as , when targeting SQL Server. This is the default /// behavior when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The value that is used for the very first row loaded into the table. /// The incremental value that is added to the identity value of the previous row that was loaded. @@ -142,6 +172,11 @@ public static ModelBuilder UseIdentityColumns( /// /// Configures the default seed for SQL Server IDENTITY. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The value that is used for the very first row loaded into the table. /// Indicates whether the configuration was specified using a data annotation. @@ -166,6 +201,11 @@ public static ModelBuilder UseIdentityColumns( /// /// Returns a value indicating whether the given value can be set as the default seed for SQL Server IDENTITY. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The value that is used for the very first row loaded into the table. /// Indicates whether the configuration was specified using a data annotation. @@ -183,6 +223,11 @@ public static bool CanSetIdentityColumnSeed( /// /// Configures the default increment for SQL Server IDENTITY. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The incremental value that is added to the identity value of the previous row that was loaded. /// Indicates whether the configuration was specified using a data annotation. @@ -207,6 +252,11 @@ public static bool CanSetIdentityColumnSeed( /// /// Returns a value indicating whether the given value can be set as the default increment for SQL Server IDENTITY. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The incremental value that is added to the identity value of the previous row that was loaded. /// Indicates whether the configuration was specified using a data annotation. @@ -225,6 +275,11 @@ public static bool CanSetIdentityColumnIncrement( /// Configures the default value generation strategy for key properties marked as , /// when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The value generation strategy. /// Indicates whether the configuration was specified using a data annotation. @@ -260,6 +315,11 @@ public static bool CanSetIdentityColumnIncrement( /// /// Returns a value indicating whether the given value can be set as the default value generation strategy. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The value generation strategy. /// Indicates whether the configuration was specified using a data annotation. @@ -283,6 +343,11 @@ public static bool CanSetValueGenerationStrategy( /// Units must be included, e.g. "100 MB". See Azure SQL Database documentation for all supported values. /// /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The maximum size of the database. /// The same builder instance so that multiple calls can be chained. @@ -304,6 +369,11 @@ public static ModelBuilder HasDatabaseMaxSize(this ModelBuilder modelBuilder, st /// Units must be included, e.g. "100 MB". See Azure SQL Database documentation for all supported values. /// /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The maximum size of the database. /// Indicates whether the configuration was specified using a data annotation. @@ -328,6 +398,11 @@ public static ModelBuilder HasDatabaseMaxSize(this ModelBuilder modelBuilder, st /// /// Returns a value indicating whether the given value can be set as the maximum size of the database. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The maximum size of the database. /// Indicates whether the configuration was specified using a data annotation. @@ -350,6 +425,11 @@ public static bool CanSetDatabaseMaxSize( /// See Azure SQL Database documentation for supported values. /// /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The service tier of the database as a string literal. /// The same builder instance so that multiple calls can be chained. @@ -371,6 +451,11 @@ public static ModelBuilder HasServiceTier(this ModelBuilder modelBuilder, string /// See Azure SQL Database documentation for supported values. /// /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The expression for the service tier of the database. /// The same builder instance so that multiple calls can be chained. @@ -392,6 +477,11 @@ public static ModelBuilder HasServiceTierSql(this ModelBuilder modelBuilder, str /// See Azure SQL Database documentation for supported values. /// /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The expression for the service tier of the database. /// Indicates whether the configuration was specified using a data annotation. @@ -416,6 +506,11 @@ public static ModelBuilder HasServiceTierSql(this ModelBuilder modelBuilder, str /// /// Returns a value indicating whether the given value can be set as the service tier of the database. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The expression for the service tier of the database. /// Indicates whether the configuration was specified using a data annotation. @@ -438,6 +533,11 @@ public static bool CanSetServiceTierSql( /// See Azure SQL Database documentation for supported values. /// /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The performance level of the database as a string literal. /// The same builder instance so that multiple calls can be chained. @@ -459,6 +559,11 @@ public static ModelBuilder HasPerformanceLevel(this ModelBuilder modelBuilder, s /// See Azure SQL Database documentation for supported values. /// /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The expression for the performance level of the database. /// The same builder instance so that multiple calls can be chained. @@ -480,6 +585,11 @@ public static ModelBuilder HasPerformanceLevelSql(this ModelBuilder modelBuilder /// See Azure SQL Database documentation for supported values. /// /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The expression for the performance level of the database. /// Indicates whether the configuration was specified using a data annotation. @@ -504,6 +614,11 @@ public static ModelBuilder HasPerformanceLevelSql(this ModelBuilder modelBuilder /// /// Returns a value indicating whether the given value can be set as the performance level of the database. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The model builder. /// The performance level of the database expression. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.SqlServer/Extensions/SqlServerModelExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerModelExtensions.cs index 77e4700845f..7d3d8d164af 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerModelExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerModelExtensions.cs @@ -13,6 +13,11 @@ namespace Microsoft.EntityFrameworkCore /// /// Model extension methods for SQL Server-specific metadata. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerModelExtensions { /// diff --git a/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs index 6ed2f999ec2..a1b9d055d44 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs @@ -12,12 +12,22 @@ namespace Microsoft.EntityFrameworkCore /// /// SQL Server specific extension methods for . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerPropertyBuilderExtensions { /// /// Configures the key property to use a sequence-based hi-lo pattern to generate values for new entities, /// when targeting SQL Server. This method sets the property to be . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The name of the sequence. /// The schema of the sequence. @@ -55,6 +65,11 @@ public static PropertyBuilder UseHiLo( /// Configures the key property to use a sequence-based hi-lo pattern to generate values for new entities, /// when targeting SQL Server. This method sets the property to be . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The name of the sequence. @@ -70,6 +85,11 @@ public static PropertyBuilder UseHiLo( /// Configures the database sequence used for the hi-lo pattern to generate values for the key property, /// when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The name of the sequence. /// The schema of the sequence. @@ -97,6 +117,11 @@ public static PropertyBuilder UseHiLo( /// /// Returns a value indicating whether the given name and schema can be set for the hi-lo sequence. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The name of the sequence. /// The schema of the sequence. @@ -120,6 +145,11 @@ public static bool CanSetHiLoSequence( /// Configures the key property to use the SQL Server IDENTITY feature to generate values for new entities, /// when targeting SQL Server. This method sets the property to be . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The value that is used for the very first row loaded into the table. /// The incremental value that is added to the identity value of the previous row that was loaded. @@ -145,6 +175,11 @@ public static PropertyBuilder UseIdentityColumn( /// Configures the key property to use the SQL Server IDENTITY feature to generate values for new entities, /// when targeting SQL Server. This method sets the property to be . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The value that is used for the very first row loaded into the table. /// The incremental value that is added to the identity value of the previous row that was loaded. @@ -159,6 +194,11 @@ public static PropertyBuilder UseIdentityColumn( /// Configures the key property to use the SQL Server IDENTITY feature to generate values for new entities, /// when targeting SQL Server. This method sets the property to be . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The value that is used for the very first row loaded into the table. @@ -174,6 +214,11 @@ public static PropertyBuilder UseIdentityColumn( /// Configures the key property to use the SQL Server IDENTITY feature to generate values for new entities, /// when targeting SQL Server. This method sets the property to be . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The value that is used for the very first row loaded into the table. @@ -188,6 +233,11 @@ public static PropertyBuilder UseIdentityColumn( /// /// Configures the seed for SQL Server IDENTITY. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The value that is used for the very first row loaded into the table. /// Indicates whether the configuration was specified using a data annotation. @@ -212,6 +262,11 @@ public static PropertyBuilder UseIdentityColumn( /// /// Returns a value indicating whether the given value can be set as the seed for SQL Server IDENTITY. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The value that is used for the very first row loaded into the table. /// Indicates whether the configuration was specified using a data annotation. @@ -229,6 +284,11 @@ public static bool CanSetIdentityColumnSeed( /// /// Configures the increment for SQL Server IDENTITY. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The incremental value that is added to the identity value of the previous row that was loaded. /// Indicates whether the configuration was specified using a data annotation. @@ -253,6 +313,11 @@ public static bool CanSetIdentityColumnSeed( /// /// Returns a value indicating whether the given value can be set as the increment for SQL Server IDENTITY. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The incremental value that is added to the identity value of the previous row that was loaded. /// Indicates whether the configuration was specified using a data annotation. @@ -270,6 +335,11 @@ public static bool CanSetIdentityColumnIncrement( /// /// Configures the value generation strategy for the key property, when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The value generation strategy. /// Indicates whether the configuration was specified using a data annotation. @@ -306,6 +376,11 @@ public static bool CanSetIdentityColumnIncrement( /// /// Returns a value indicating whether the given value can be set as the value generation strategy. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// The value generation strategy. /// Indicates whether the configuration was specified using a data annotation. @@ -326,6 +401,11 @@ public static bool CanSetValueGenerationStrategy( /// /// Configures whether the property's column is created as sparse when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// + /// for more information. /// The builder for the property being configured. /// A value indicating whether the property's column is created as sparse. /// A builder to further configure the property. @@ -342,6 +422,11 @@ public static PropertyBuilder IsSparse(this PropertyBuilder propertyBuilder, boo /// /// Configures whether the property's column is created as sparse when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// A value indicating whether the property's column is created as sparse. /// A builder to further configure the property. @@ -354,6 +439,11 @@ public static PropertyBuilder IsSparse( /// /// Configures whether the property's column is created as sparse when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// A value indicating whether the property's column is created as sparse. /// Indicates whether the configuration was specified using a data annotation. @@ -377,6 +467,11 @@ public static PropertyBuilder IsSparse( /// /// Returns a value indicating whether the property's column can be configured as sparse when targeting SQL Server. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The builder for the property being configured. /// A value indicating whether the property's column is created as sparse. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs index f7acc82ffee..cfa28416842 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs @@ -17,6 +17,11 @@ namespace Microsoft.EntityFrameworkCore /// /// Property extension methods for SQL Server-specific metadata. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public static class SqlServerPropertyExtensions { /// diff --git a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs index d55f9ab69c8..7a6240342e1 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs @@ -57,6 +57,11 @@ public static class SqlServerServiceCollectionExtensions /// See Using DbContext with dependency injection for more information. /// /// + /// + /// See Using DbContextOptions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// /// The type of context to be registered. /// The to add services to. /// The connection string of the database to connect to. diff --git a/src/EFCore.SqlServer/Extensions/SqlServerTableBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerTableBuilderExtensions.cs index fdc4fc95795..44cab755d58 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerTableBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerTableBuilderExtensions.cs @@ -15,6 +15,10 @@ public static class SqlServerTableBuilderExtensions /// /// Configures the table as temporal. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the table being configured. /// A value indicating whether the table is temporal. /// An object that can be used to configure the temporal table. @@ -30,6 +34,10 @@ public static TemporalTableBuilder IsTemporal( /// /// Configures the table as temporal. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The builder for the table being configured. /// An action that performs configuration of the temporal table. /// The same builder instance so that multiple calls can be chained. @@ -47,6 +55,10 @@ public static TableBuilder IsTemporal( /// /// Configures the table as temporal. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The entity type being configured. /// The builder for the table being configured. /// A value indicating whether the table is temporal. @@ -64,6 +76,10 @@ public static TemporalTableBuilder IsTemporal( /// /// Configures the table as temporal. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The entity type being configured. /// The builder for the table being configured. /// An action that performs configuration of the temporal table. diff --git a/src/EFCore.SqlServer/Infrastructure/SqlServerDbContextOptionsBuilder.cs b/src/EFCore.SqlServer/Infrastructure/SqlServerDbContextOptionsBuilder.cs index 7c96c80ce95..1c1feb47c9b 100644 --- a/src/EFCore.SqlServer/Infrastructure/SqlServerDbContextOptionsBuilder.cs +++ b/src/EFCore.SqlServer/Infrastructure/SqlServerDbContextOptionsBuilder.cs @@ -41,6 +41,10 @@ public SqlServerDbContextOptionsBuilder(DbContextOptionsBuilder optionsBuilder) /// Default values of 6 for the maximum retry count and 30 seconds for the maximum default delay are used. /// /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public virtual SqlServerDbContextOptionsBuilder EnableRetryOnFailure() => ExecutionStrategy(c => new SqlServerRetryingExecutionStrategy(c)); @@ -56,6 +60,10 @@ public virtual SqlServerDbContextOptionsBuilder EnableRetryOnFailure() /// A default value 30 seconds for the maximum default delay is used. /// /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public virtual SqlServerDbContextOptionsBuilder EnableRetryOnFailure(int maxRetryCount) => ExecutionStrategy(c => new SqlServerRetryingExecutionStrategy(c, maxRetryCount)); @@ -68,6 +76,10 @@ public virtual SqlServerDbContextOptionsBuilder EnableRetryOnFailure(int maxRetr /// error numbers for transient errors that can be retried, but additional error numbers can also be supplied. /// /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The maximum number of retry attempts. /// The maximum delay between retries. /// Additional SQL error numbers that should be considered transient. diff --git a/src/EFCore.SqlServer/Metadata/Builders/TemporalPeriodPropertyBuilder.cs b/src/EFCore.SqlServer/Metadata/Builders/TemporalPeriodPropertyBuilder.cs index cb4103146eb..eeae2335f63 100644 --- a/src/EFCore.SqlServer/Metadata/Builders/TemporalPeriodPropertyBuilder.cs +++ b/src/EFCore.SqlServer/Metadata/Builders/TemporalPeriodPropertyBuilder.cs @@ -33,6 +33,10 @@ public TemporalPeriodPropertyBuilder(IMutableEntityType entityType, string perio /// /// Configures the column name the period property maps to. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The name of the column. /// The same builder instance so that multiple calls can be chained. public virtual TemporalPeriodPropertyBuilder HasColumnName(string name) diff --git a/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder.cs b/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder.cs index c37acb47fee..6b8f0460e7b 100644 --- a/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder.cs +++ b/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder.cs @@ -31,6 +31,10 @@ public TemporalTableBuilder(IMutableEntityType entityType) /// /// Configures a history table for the entity mapped to a temporal table. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The name of the history table. /// The same builder instance so that multiple calls can be chained. public virtual TemporalTableBuilder UseHistoryTable(string name) @@ -43,6 +47,10 @@ public virtual TemporalTableBuilder UseHistoryTable(string name) /// /// Configures a history table for the entity mapped to a temporal table. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The name of the history table. /// The schema of the history table. /// The same builder instance so that multiple calls can be chained. @@ -57,6 +65,10 @@ public virtual TemporalTableBuilder UseHistoryTable(string name, string? schema) /// /// Returns an object that can be used to configure a period start property of the entity type mapped to a temporal table. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The name of the period start property. /// An object that can be used to configure the period start property. public virtual TemporalPeriodPropertyBuilder HasPeriodStart(string propertyName) @@ -69,6 +81,10 @@ public virtual TemporalPeriodPropertyBuilder HasPeriodStart(string propertyName) /// /// Returns an object that can be used to configure a period end property of the entity type mapped to a temporal table. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The name of the period end property. /// An object that can be used to configure the period end property. public virtual TemporalPeriodPropertyBuilder HasPeriodEnd(string propertyName) diff --git a/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs b/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs index 4c064a7f29b..0263273ad3a 100644 --- a/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs +++ b/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs @@ -30,6 +30,10 @@ public TemporalTableBuilder(IMutableEntityType entityType) /// /// Configures a history table for the entity mapped to a temporal table. /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// /// The name of the history table. /// The schema of the history table. /// The same builder instance so that multiple calls can be chained. diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs index 150e16a393e..9642ddcac1e 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs @@ -21,6 +21,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// The implementations do not need to be thread-safe. /// /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerConventionSetBuilder : RelationalConventionSetBuilder { private readonly ISqlGenerationHelper _sqlGenerationHelper; diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs index 62ac66a17a8..43671ff4820 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs @@ -12,6 +12,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that ensures that is populated for database functions which /// have flag set to . /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerDbFunctionConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs index 3afee975d04..d856c448442 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs @@ -15,6 +15,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures the filter for unique non-clustered indexes with nullable columns /// to filter out null values. /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerIndexConvention : IEntityTypeBaseTypeChangedConvention, IIndexAddedConvention, diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs index 90475134a8a..47fd8245509 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs @@ -12,6 +12,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures indexes as non-clustered for memory-optimized tables. /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerMemoryOptimizedTablesConvention : IEntityTypeAnnotationChangedConvention, IKeyAddedConvention, diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs index 73f0f8cb3ca..38ba14c544e 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs @@ -12,6 +12,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures the OnDelete behavior for foreign keys on the join entity type for /// self-referencing skip navigations /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerOnDeleteConvention : CascadeDeleteConvention, ISkipNavigationForeignKeyChangedConvention { /// diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerRuntimeModelConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerRuntimeModelConvention.cs index 7dc047b1e59..8e87f14d34f 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerRuntimeModelConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerRuntimeModelConvention.cs @@ -12,6 +12,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that creates an optimized copy of the mutable model. /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerRuntimeModelConvention : RelationalRuntimeModelConvention { /// diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerSharedTableConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerSharedTableConvention.cs index 97b85e2564e..fa571bfaa8e 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerSharedTableConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerSharedTableConvention.cs @@ -10,6 +10,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that manipulates names of database objects for entity types that share a table to avoid clashes. /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerSharedTableConvention : SharedTableConvention { /// diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs index 37aa9e40c21..c6dab889d8a 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs @@ -13,6 +13,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that ensures that properties aren't configured to have a default value, as computed column /// or using a at the same time. /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerStoreGenerationConvention : StoreGenerationConvention { /// diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs index 9b2bc61faec..d3074c19e9c 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs @@ -11,6 +11,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that manipulates temporal settings for an entity mapped to a temporal table. /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerTemporalConvention : IEntityTypeAnnotationChangedConvention, ISkipNavigationForeignKeyChangedConvention { private const string PeriodStartDefaultName = "PeriodStart"; diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs index 2c832eeb574..4e89dcc080b 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs @@ -15,6 +15,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// or were configured to use a . /// It also configures properties as if they were configured as computed columns. /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerValueGenerationConvention : RelationalValueGenerationConvention { /// diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs index 5251103e3e3..51afca77fbb 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs @@ -12,6 +12,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures the default model as /// . /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerValueGenerationStrategyConvention : IModelInitializedConvention, IModelFinalizingConvention { /// diff --git a/src/EFCore.SqlServer/Metadata/SqlServerValueGenerationStrategy.cs b/src/EFCore.SqlServer/Metadata/SqlServerValueGenerationStrategy.cs index 5654c0c9ee6..bd446b33299 100644 --- a/src/EFCore.SqlServer/Metadata/SqlServerValueGenerationStrategy.cs +++ b/src/EFCore.SqlServer/Metadata/SqlServerValueGenerationStrategy.cs @@ -9,6 +9,11 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Defines two strategies to use across the EF Core stack when generating key values /// from SQL Server database columns. /// + /// + /// See Model building conventions, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public enum SqlServerValueGenerationStrategy { /// diff --git a/src/EFCore.SqlServer/Migrations/Operations/SqlServerCreateDatabaseOperation.cs b/src/EFCore.SqlServer/Migrations/Operations/SqlServerCreateDatabaseOperation.cs index db4f0b79614..dd4af37577f 100644 --- a/src/EFCore.SqlServer/Migrations/Operations/SqlServerCreateDatabaseOperation.cs +++ b/src/EFCore.SqlServer/Migrations/Operations/SqlServerCreateDatabaseOperation.cs @@ -8,6 +8,11 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A SQL Server-specific to create a database. /// + /// + /// See Database migrations, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// [DebuggerDisplay("CREATE DATABASE {Name}")] public class SqlServerCreateDatabaseOperation : DatabaseOperation { diff --git a/src/EFCore.SqlServer/Migrations/Operations/SqlServerDropDatabaseOperation.cs b/src/EFCore.SqlServer/Migrations/Operations/SqlServerDropDatabaseOperation.cs index 005aed76237..f2f2e03c532 100644 --- a/src/EFCore.SqlServer/Migrations/Operations/SqlServerDropDatabaseOperation.cs +++ b/src/EFCore.SqlServer/Migrations/Operations/SqlServerDropDatabaseOperation.cs @@ -6,6 +6,11 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A SQL Server-specific to drop a database. /// + /// + /// See Database migrations, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerDropDatabaseOperation : MigrationOperation { /// diff --git a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs index f81dc53089f..f0221440284 100644 --- a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs +++ b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs @@ -33,6 +33,11 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation does not need to be thread-safe. /// /// + /// + /// See Database migrations, and + /// Accessing SQL Server and SQL Azure databases with EF Core + /// for more information. + /// public class SqlServerMigrationsSqlGenerator : MigrationsSqlGenerator { private IReadOnlyList _operations = null!; diff --git a/src/EFCore.Sqlite.Core/Diagnostics/SqliteEventId.cs b/src/EFCore.Sqlite.Core/Diagnostics/SqliteEventId.cs index 51b55b67076..ef61a3fba50 100644 --- a/src/EFCore.Sqlite.Core/Diagnostics/SqliteEventId.cs +++ b/src/EFCore.Sqlite.Core/Diagnostics/SqliteEventId.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// behavior of warnings. /// /// + /// + /// See Logging, events, and diagnostics, and + /// Accessing SQLite databases with EF Core for more information. + /// public static class SqliteEventId { // Warning: These values must not change between releases. diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteDatabaseFacadeExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteDatabaseFacadeExtensions.cs index c1df8c408ae..30d43c2f989 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqliteDatabaseFacadeExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqliteDatabaseFacadeExtensions.cs @@ -24,6 +24,9 @@ public static class SqliteDatabaseFacadeExtensions /// provider to use as part of configuring the context. /// /// + /// + /// See Accessing SQLite databases with EF Core for more information. + /// /// The facade from . /// if SQLite is being used; otherwise. public static bool IsSqlite(this DatabaseFacade database) diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteDbContextOptionsBuilderExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteDbContextOptionsBuilderExtensions.cs index 9979130b315..a305659e245 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqliteDbContextOptionsBuilderExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqliteDbContextOptionsBuilderExtensions.cs @@ -3,7 +3,6 @@ using System; using System.Data.Common; -using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Sqlite.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.Utilities; @@ -14,6 +13,10 @@ namespace Microsoft.EntityFrameworkCore /// /// SQLite specific extension methods for . /// + /// + /// See Using DbContextOptions, and + /// Accessing SQLite databases with EF Core for more information. + /// public static class SqliteDbContextOptionsBuilderExtensions { /// @@ -27,6 +30,10 @@ public static class SqliteDbContextOptionsBuilderExtensions /// Set a connection string using . /// /// + /// + /// See Using DbContextOptions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The builder being used to configure the context. /// An optional action to allow additional SQLite specific configuration. /// The options builder so that further configuration can be chained. @@ -48,6 +55,10 @@ public static DbContextOptionsBuilder UseSqlite( /// /// Configures the context to connect to a SQLite database. /// + /// + /// See Using DbContextOptions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The builder being used to configure the context. /// The connection string of the database to connect to. /// An optional action to allow additional SQLite specific configuration. @@ -73,6 +84,10 @@ public static DbContextOptionsBuilder UseSqlite( /// /// Configures the context to connect to a SQLite database. /// + /// + /// See Using DbContextOptions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The builder being used to configure the context. /// /// An existing to be used to connect to the database. If the connection is @@ -110,6 +125,10 @@ public static DbContextOptionsBuilder UseSqlite( /// Set a connection string using . /// /// + /// + /// See Using DbContextOptions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The builder being used to configure the context. /// An optional action to allow additional SQLite specific configuration. /// The options builder so that further configuration can be chained. @@ -123,6 +142,10 @@ public static DbContextOptionsBuilder UseSqlite( /// /// Configures the context to connect to a SQLite database. /// + /// + /// See Using DbContextOptions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The type of context to be configured. /// The builder being used to configure the context. /// The connection string of the database to connect to. @@ -139,6 +162,10 @@ public static DbContextOptionsBuilder UseSqlite( /// /// Configures the context to connect to a SQLite database. /// + /// + /// See Using DbContextOptions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The type of context to be configured. /// The builder being used to configure the context. /// diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteDbFunctionsExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteDbFunctionsExtensions.cs index db5a83aedf9..60c382fb8a2 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqliteDbFunctionsExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqliteDbFunctionsExtensions.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore /// /// Contains extension methods on for the Microsoft.EntityFrameworkCore.Sqlite provider. /// + /// + /// See Database functions, and + /// Accessing SQLite databases with EF Core for more information. + /// public static class SqliteDbFunctionsExtensions { /// @@ -17,6 +21,10 @@ public static class SqliteDbFunctionsExtensions /// but uses the file system globbing /// syntax instead. /// + /// + /// See Database functions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The instance. /// The string that is to be matched. /// The pattern which may involve wildcards *,?,[,^,-,]. @@ -27,6 +35,10 @@ public static bool Glob(this DbFunctions _, string matchExpression, string patte /// /// Maps to the SQLite hex function which returns a hexadecimal string representing the specified value. /// + /// + /// See Database functions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The instance. /// The binary value. /// A hexadecimal string. @@ -37,6 +49,10 @@ public static string Hex(this DbFunctions _, byte[] bytes) /// 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. /// + /// + /// See Database functions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The instance. /// The binary value. /// The 1-based starting index. If negative, the index is relative to the end of the value. @@ -51,6 +67,10 @@ public static byte[] Substr(this DbFunctions _, byte[] bytes, int startIndex) /// Maps to the SQLite substr function which returns a subarray of the specified value. The subarray starts /// at and has the specified . /// + /// + /// See Database functions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The instance. /// The binary value. /// The 1-based starting index. If negative, the index is relative to the end of the value. diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteMigrationBuilderExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteMigrationBuilderExtensions.cs index 56a07bc0649..7706ee20fc5 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqliteMigrationBuilderExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqliteMigrationBuilderExtensions.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// /// SQLite specific extension methods for . /// + /// + /// See Accessing SQLite databases with EF Core for more information. + /// public static class SqliteMigrationBuilderExtensions { /// @@ -17,6 +20,9 @@ public static class SqliteMigrationBuilderExtensions /// Returns if the database provider currently in use is the SQLite provider. /// /// + /// + /// See Accessing SQLite databases with EF Core for more information. + /// /// /// The migrationBuilder from the parameters on or /// . diff --git a/src/EFCore.Sqlite.Core/Extensions/SqlitePropertyBuilderExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqlitePropertyBuilderExtensions.cs index f3d26691208..7868392cf36 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqlitePropertyBuilderExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqlitePropertyBuilderExtensions.cs @@ -11,11 +11,19 @@ namespace Microsoft.EntityFrameworkCore /// /// SQLite-specific extension methods for . /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQLite databases with EF Core for more information. + /// public static class SqlitePropertyBuilderExtensions { /// /// 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. + /// /// The builder for the property being configured. /// The SRID. /// The same builder instance so that multiple calls can be chained. @@ -31,6 +39,10 @@ public static PropertyBuilder HasSrid(this PropertyBuilder propertyBuilder, int /// /// 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. + /// /// The builder for the property being configured. /// The SRID. /// The same builder instance so that multiple calls can be chained. @@ -42,6 +54,10 @@ public static PropertyBuilder HasSrid( /// /// 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. + /// /// The builder for the property being configured. /// The SRID. /// Indicates whether the configuration was specified using a data annotation. @@ -67,6 +83,10 @@ public static PropertyBuilder HasSrid( /// /// Returns a value indicating whether the given value can be set as the SRID for the column. /// + /// + /// See Spatial data, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The builder for the property being configured. /// The SRID. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.Sqlite.Core/Extensions/SqlitePropertyExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqlitePropertyExtensions.cs index 957b4ff85d9..ae0d915b133 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqlitePropertyExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqlitePropertyExtensions.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore /// /// Extension methods for for SQLite metadata. /// + /// + /// See Modeling entity types and relationships, and + /// Accessing SQLite databases with EF Core for more information. + /// public static class SqlitePropertyExtensions { /// diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs index a38a2a8e8f8..abdc67d31b6 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs @@ -55,6 +55,10 @@ public static class SqliteServiceCollectionExtensions /// See Using DbContext with dependency injection for more information. /// /// + /// + /// See Using DbContextOptions, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The type of context to be registered. /// The to add services to. /// The connection string of the database to connect to. diff --git a/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs b/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs index eaac6d0250c..60e35af0261 100644 --- a/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs +++ b/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs @@ -19,6 +19,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// Finds and loads SpatiaLite. /// + /// + /// See Spatial data, and + /// Accessing SQLite databases with EF Core for more information. + /// public static class SpatialiteLoader { private static readonly string? _sharedLibraryExtension; diff --git a/src/EFCore.Sqlite.Core/Infrastructure/SqliteDbContextOptionsBuilder.cs b/src/EFCore.Sqlite.Core/Infrastructure/SqliteDbContextOptionsBuilder.cs index 0951f62a079..c57622daee1 100644 --- a/src/EFCore.Sqlite.Core/Infrastructure/SqliteDbContextOptionsBuilder.cs +++ b/src/EFCore.Sqlite.Core/Infrastructure/SqliteDbContextOptionsBuilder.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// and it is not designed to be directly constructed in your application code. /// /// + /// + /// See Using DbContextOptions, and + /// Accessing SQLite databases with EF Core for more information. + /// public class SqliteDbContextOptionsBuilder : RelationalDbContextOptionsBuilder { /// diff --git a/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteConventionSetBuilder.cs b/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteConventionSetBuilder.cs index 67e3b6c933a..3b8677ca51f 100644 --- a/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteConventionSetBuilder.cs +++ b/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteConventionSetBuilder.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// The implementations do not need to be thread-safe. /// /// + /// + /// See Model building conventions, and + /// Accessing SQLite databases with EF Core for more information. + /// public class SqliteConventionSetBuilder : RelationalConventionSetBuilder { /// diff --git a/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteRuntimeModelConvention.cs b/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteRuntimeModelConvention.cs index d144fabad92..aee32780d14 100644 --- a/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteRuntimeModelConvention.cs +++ b/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteRuntimeModelConvention.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that creates an optimized copy of the mutable model. /// + /// + /// See Model building conventions, and + /// Accessing SQLite databases with EF Core for more information. + /// public class SqliteRuntimeModelConvention : RelationalRuntimeModelConvention { /// diff --git a/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteSharedTableConvention.cs b/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteSharedTableConvention.cs index ee2f603f51e..49bcba1a23e 100644 --- a/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteSharedTableConvention.cs +++ b/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteSharedTableConvention.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that manipulates names of database objects for entity types that share a table to avoid clashes. /// + /// + /// See Model building conventions, and + /// Accessing SQLite databases with EF Core for more information. + /// public class SqliteSharedTableConvention : SharedTableConvention { /// diff --git a/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs b/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs index 18412b2ffce..8f85d47e404 100644 --- a/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs +++ b/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs @@ -29,6 +29,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation does not need to be thread-safe. /// /// + /// + /// See Database migrations, and + /// Accessing SQLite databases with EF Core for more information. + /// public class SqliteMigrationsSqlGenerator : MigrationsSqlGenerator { /// diff --git a/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteDbContextOptionsBuilderExtensions.cs b/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteDbContextOptionsBuilderExtensions.cs index 01420186d36..410daeacbd7 100644 --- a/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteDbContextOptionsBuilderExtensions.cs +++ b/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteDbContextOptionsBuilderExtensions.cs @@ -11,11 +11,19 @@ namespace Microsoft.EntityFrameworkCore /// /// NetTopologySuite specific extension methods for . /// + /// + /// See Spatial data, and + /// Accessing SQLite databases with EF Core for more information. + /// public static class SqliteNetTopologySuiteDbContextOptionsBuilderExtensions { /// /// Use NetTopologySuite to access SpatiaLite data. /// + /// + /// See Spatial data, and + /// Accessing SQLite databases with EF Core for more information. + /// /// The build being used to configure SQLite. /// The options builder so that further configuration can be chained. public static SqliteDbContextOptionsBuilder UseNetTopologySuite( diff --git a/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteServiceCollectionExtensions.cs b/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteServiceCollectionExtensions.cs index 7e9b3f23692..ff69657367a 100644 --- a/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteServiceCollectionExtensions.cs +++ b/src/EFCore.Sqlite.NTS/Extensions/SqliteNetTopologySuiteServiceCollectionExtensions.cs @@ -16,6 +16,10 @@ namespace Microsoft.Extensions.DependencyInjection /// /// EntityFrameworkCore.Sqlite.NetTopologySuite extension methods for . /// + /// + /// See Spatial data, and + /// Accessing SQLite databases with EF Core for more information. + /// public static class SqliteNetTopologySuiteServiceCollectionExtensions { /// diff --git a/src/EFCore/Diagnostics/LazyLoadingEventData.cs b/src/EFCore/Diagnostics/LazyLoadingEventData.cs index aba6f80c2dd..9b7ed9d4ae2 100644 --- a/src/EFCore/Diagnostics/LazyLoadingEventData.cs +++ b/src/EFCore/Diagnostics/LazyLoadingEventData.cs @@ -21,7 +21,7 @@ public class LazyLoadingEventData : DbContextEventData /// The event definition. /// A delegate that generates a log message for this event. /// The current . - /// The entity instance on which lazy-loading was initiated. + /// The entity instance on which lazy loading was initiated. /// The navigation property name of the relationship to be loaded. public LazyLoadingEventData( EventDefinitionBase eventDefinition, @@ -36,7 +36,7 @@ public LazyLoadingEventData( } /// - /// The entity instance on which lazy-loading was initiated. + /// The entity instance on which lazy loading was initiated. /// public virtual object Entity { get; } diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index b0f9342c3db..a13989e5284 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -3291,7 +3291,7 @@ public static EventDefinition LogContextDisposed(IDiagnosticsLogger logg } /// - /// An attempt was made to lazy-load navigation '{navigation}' on a detached entity of type '{entityType}'. Lazy-loading is not supported for detached entities or entities that are loaded with 'AsNoTracking'. + /// An attempt was made to lazy-load navigation '{navigation}' on a detached entity of type '{entityType}'. Lazy loading is not supported for detached entities or entities that are loaded with 'AsNoTracking'. /// public static EventDefinition LogDetachedLazyLoading(IDiagnosticsLogger logger) { diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index 0e69a329177..da665f56181 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -759,7 +759,7 @@ Information CoreEventId.ContextInitialized string string string? string? string - An attempt was made to lazy-load navigation '{navigation}' on a detached entity of type '{entityType}'. Lazy-loading is not supported for detached entities or entities that are loaded with 'AsNoTracking'. + An attempt was made to lazy-load navigation '{navigation}' on a detached entity of type '{entityType}'. Lazy loading is not supported for detached entities or entities that are loaded with 'AsNoTracking'. Warning CoreEventId.DetachedLazyLoadingWarning string string diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/ProxyGraphUpdatesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/ProxyGraphUpdatesSqlServerTest.cs index 2b826577f9c..18f75c48fdb 100644 --- a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/ProxyGraphUpdatesSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/ProxyGraphUpdatesSqlServerTest.cs @@ -70,7 +70,7 @@ public ChangeTracking(ProxyGraphUpdatesWithChangeTrackingSqlServerFixture fixtur { } - // Needs lazy-loading + // Needs lazy loading public override void Attempting_to_save_two_entity_cycle_with_lazy_loading_throws() { } diff --git a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/ProxyGraphUpdatesSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/ProxyGraphUpdatesSqliteTest.cs index 03899e19776..625d03a967a 100644 --- a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/ProxyGraphUpdatesSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/ProxyGraphUpdatesSqliteTest.cs @@ -64,7 +64,7 @@ public ChangeTracking(ProxyGraphUpdatesWithChangeTrackingSqliteFixture fixture) { } - // Needs lazy-loading + // Needs lazy loading public override void Attempting_to_save_two_entity_cycle_with_lazy_loading_throws() { } From 8098a16b1fbc9a3891a630163152f3e88de8041f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 11 Sep 2021 13:20:27 +0000 Subject: [PATCH 090/346] Update dependencies from https://github.com/dotnet/runtime build 20210911.1 (#25978) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1370c9c1e9b..8d37bb0a99b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c - + https://github.com/dotnet/runtime - 46c7023a3de4d6df7f9b001ce46f22f482168dfa + 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c diff --git a/eng/Versions.props b/eng/Versions.props index fe505c17c06..58bcda78739 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 - 6.0.0-rc.2.21460.14 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21461.1 3.7.0 From 6a405cddc88a068854eae0447b65f9268a8b6779 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 13 Sep 2021 12:38:32 +0000 Subject: [PATCH 091/346] Update dependencies from https://github.com/dotnet/runtime build 20210913.1 (#25993) [main] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index aa8253c432c..5adadaeae28 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 - + https://github.com/dotnet/runtime - b7e10374429b5af32debc4660aa9bce41cfb903e + 0becd27f728f9e1eeb2a168789418ad4191ade99 diff --git a/eng/Versions.props b/eng/Versions.props index 84d4ff6f7ae..7d312024f2a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 - 7.0.0-alpha.1.21456.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 + 7.0.0-alpha.1.21463.1 3.7.0 From 9eaa9195d9f7e62e407d8a8993e53d94573abff2 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 13 Sep 2021 12:49:02 +0000 Subject: [PATCH 092/346] Update dependencies from https://github.com/dotnet/arcade build 20210909.5 (#25994) [main] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 8 ++++---- global.json | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5adadaeae28..a363a74f113 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -47,13 +47,13 @@ - + https://github.com/dotnet/arcade - 0ec8dbacaefa7ccdb4bc96e120e07dc60c6eda98 + fa4a48044d33222537e6dbd000f8a2adaa7a15c7 - + https://github.com/dotnet/arcade - 0ec8dbacaefa7ccdb4bc96e120e07dc60c6eda98 + fa4a48044d33222537e6dbd000f8a2adaa7a15c7 diff --git a/global.json b/global.json index eef3634046b..5628ad02f5d 100644 --- a/global.json +++ b/global.json @@ -18,7 +18,7 @@ "rollForward": "latestMajor" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21453.2", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.21453.2" + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21459.5", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.21459.5" } } From b6d45abcd560068e947aaf8a556f253344a1c747 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Mon, 13 Sep 2021 08:54:17 -0700 Subject: [PATCH 093/346] InMemory: Read nullable value for derived properties (#25968) So that when that property is being read outside of entity materialization, we get null value rather than default of non-nullable type Resolves #25735 --- .../Query/Internal/InMemoryQueryExpression.cs | 8 +++++--- .../Query/GearsOfWarQueryInMemoryTest.cs | 6 ------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs index b693d555579..0989f52abfa 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs @@ -93,13 +93,15 @@ public InMemoryQueryExpression(IEntityType entityType) foreach (var property in derivedEntityType.GetDeclaredProperties()) { + // We read nullable value from property of derived type since it could be null. + var typeToRead = property.ClrType.MakeNullable(); var propertyExpression = Condition( entityCheck, - CreateReadValueExpression(property.ClrType, property.GetIndex(), property), - Default(property.ClrType)); + CreateReadValueExpression(typeToRead, property.GetIndex(), property), + Default(typeToRead)); selectorExpressions.Add(propertyExpression); - var readExpression = CreateReadValueExpression(property.ClrType, selectorExpressions.Count - 1, property); + var readExpression = CreateReadValueExpression(propertyExpression.Type, selectorExpressions.Count - 1, property); propertyExpressionsMap[property] = readExpression; _projectionMappingExpressions.Add(readExpression); } diff --git a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs index 19ce4f49885..7b4d689a42a 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs @@ -66,11 +66,5 @@ public override async Task Projecting_some_properties_as_well_as_correlated_coll Assert.Equal(InMemoryStrings.DistinctOnSubqueryNotSupported, message); } - - [ConditionalTheory(Skip = "Issue #25735")] - public override Task Project_navigation_defined_on_derived_from_entity_with_inheritance_using_soft_cast(bool async) - { - return base.Project_navigation_defined_on_derived_from_entity_with_inheritance_using_soft_cast(async); - } } } From 7dbc74af4d8ac9711d4c2b5494f5af980a9b9281 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Mon, 13 Sep 2021 08:54:34 -0700 Subject: [PATCH 094/346] Query: Convert result of Round appropriately for MathF functions (#25970) Resolves #25421 --- .../Query/Internal/SqlServerMathTranslator.cs | 28 ++++++++++----- .../Query/NorthwindFunctionsQueryTestBase.cs | 33 ++++++++++++++++++ .../NorthwindFunctionsQuerySqlServerTest.cs | 34 +++++++++++++++++-- 3 files changed, 85 insertions(+), 10 deletions(-) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs index 3139c8e1cd6..58e62388120 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerMathTranslator.cs @@ -144,28 +144,40 @@ public SqlServerMathTranslator(ISqlExpressionFactory sqlExpressionFactory) if (_truncateMethodInfos.Contains(method)) { var argument = arguments[0]; - - return _sqlExpressionFactory.Function( + // Result of ROUND for float/double is always double in server side + var result = (SqlExpression)_sqlExpressionFactory.Function( "ROUND", new[] { argument, _sqlExpressionFactory.Constant(0), _sqlExpressionFactory.Constant(1) }, nullable: true, argumentsPropagateNullability: new[] { true, false, false }, - method.ReturnType, - argument.TypeMapping); + typeof(double)); + + if (argument.Type == typeof(float)) + { + result = _sqlExpressionFactory.Convert(result, typeof(float)); + } + + return _sqlExpressionFactory.ApplyTypeMapping(result, argument.TypeMapping); } if (_roundMethodInfos.Contains(method)) { var argument = arguments[0]; var digits = arguments.Count == 2 ? arguments[1] : _sqlExpressionFactory.Constant(0); - - return _sqlExpressionFactory.Function( + // Result of ROUND for float/double is always double in server side + var result = (SqlExpression) _sqlExpressionFactory.Function( "ROUND", new[] { argument, digits }, nullable: true, argumentsPropagateNullability: new[] { true, true }, - method.ReturnType, - argument.TypeMapping); + typeof(double)); + + if (argument.Type == typeof(float)) + { + result = _sqlExpressionFactory.Convert(result, typeof(float)); + } + + return _sqlExpressionFactory.ApplyTypeMapping(result, argument.TypeMapping); } return null; diff --git a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs index 037c81e9708..6268fb54f7f 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs @@ -1120,6 +1120,28 @@ public virtual Task Where_mathf_round2(bool async) entryCount: 46); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Select_mathf_round(bool async) + { + return AssertQueryScalar( + async, + ss => ss.Set() + .Where(o => o.OrderID < 10250) + .Select(o => MathF.Round((float)o.OrderID))); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Select_mathf_round2(bool async) + { + return AssertQueryScalar( + async, + ss => ss.Set() + .Where(od => od.Quantity < 5) + .Select(od => MathF.Round((float)od.UnitPrice, 2))); + } + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Where_mathf_truncate(bool async) @@ -1132,6 +1154,17 @@ public virtual Task Where_mathf_truncate(bool async) entryCount: 137); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Select_mathf_truncate(bool async) + { + return AssertQueryScalar( + async, + ss => ss.Set() + .Where(od => od.Quantity < 5) + .Select(od => MathF.Truncate((float)od.UnitPrice))); + } + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Where_mathf_exp(bool async) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs index 680cf207440..47592328412 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs @@ -969,7 +969,27 @@ public override async Task Where_mathf_round2(bool async) AssertSql( @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice] FROM [Order Details] AS [o] -WHERE ROUND(CAST([o].[UnitPrice] AS real), 2) > CAST(100 AS real)"); +WHERE CAST(ROUND(CAST([o].[UnitPrice] AS real), 2) AS real) > CAST(100 AS real)"); + } + + public override async Task Select_mathf_round(bool async) + { + await base.Select_mathf_round(async); + + AssertSql( + @"SELECT CAST(ROUND(CAST([o].[OrderID] AS real), 0) AS real) +FROM [Orders] AS [o] +WHERE [o].[OrderID] < 10250"); + } + + public override async Task Select_mathf_round2(bool async) + { + await base.Select_mathf_round2(async); + + AssertSql( + @"SELECT CAST(ROUND(CAST([o].[UnitPrice] AS real), 2) AS real) +FROM [Order Details] AS [o] +WHERE [o].[Quantity] < CAST(5 AS smallint)"); } public override async Task Where_mathf_truncate(bool async) @@ -979,7 +999,17 @@ public override async Task Where_mathf_truncate(bool async) AssertSql( @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice] FROM [Order Details] AS [o] -WHERE ([o].[Quantity] < CAST(5 AS smallint)) AND (ROUND(CAST([o].[UnitPrice] AS real), 0, 1) > CAST(10 AS real))"); +WHERE ([o].[Quantity] < CAST(5 AS smallint)) AND (CAST(ROUND(CAST([o].[UnitPrice] AS real), 0, 1) AS real) > CAST(10 AS real))"); + } + + public override async Task Select_mathf_truncate(bool async) + { + await base.Select_mathf_truncate(async); + + AssertSql( + @"SELECT CAST(ROUND(CAST([o].[UnitPrice] AS real), 0, 1) AS real) +FROM [Order Details] AS [o] +WHERE [o].[Quantity] < CAST(5 AS smallint)"); } public override async Task Where_mathf_exp(bool async) From 2b158d5a678de30ef01a8b78f691c4ebc2bc8fe3 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Mon, 13 Sep 2021 08:54:51 -0700 Subject: [PATCH 095/346] Query: Add regression test for #24657 (#25972) Resolves #24657 --- .../Query/SimpleQueryTestBase.cs | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs index f2c623ada63..b896faf9c18 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs @@ -215,5 +215,90 @@ protected class Food public int Id { get; set; } public byte? Taste { get; set; } } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Bool_discriminator_column_works(bool async) + { + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + using var context = contextFactory.CreateContext(); + + var query = context.Authors.Include(e => e.Blog); + + var authors = async + ? await query.ToListAsync() + : query.ToList(); + + Assert.Equal(2, authors.Count); + } + + protected class Context24657 : DbContext + { + public Context24657(DbContextOptions options) + : base(options) + { + } + + public DbSet Authors { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity() + .HasDiscriminator(nameof(Blog.IsPhotoBlog)) + .HasValue(false) + .HasValue(true); + } + + public void Seed() + { + Add(new Author + { + Blog = new DevBlog + { + Title = "Dev Blog", + } + }); + Add(new Author + { + Blog = new PhotoBlog + { + Title = "Photo Blog", + } + }); + + SaveChanges(); + } + } + + protected class Author + { + public int Id { get; set; } + public Blog Blog { get; set; } + } + + protected abstract class Blog + { + public int Id { get; set; } + public bool IsPhotoBlog { get; set; } + public string Title { get; set; } + } + + protected class DevBlog : Blog + { + public DevBlog() + { + IsPhotoBlog = false; + } + } + + protected class PhotoBlog : Blog + { + public PhotoBlog() + { + IsPhotoBlog = true; + } + + public int NumberOfPhotos { get; set; } + } } } From 3f47c886d2ca9f4d79d15e5b19f3861a9dff1a03 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Mon, 13 Sep 2021 08:55:07 -0700 Subject: [PATCH 096/346] Query: Enable test for #24291 (#25974) Resolved #24291 --- .../Query/NorthwindMiscellaneousQueryInMemoryTest.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/EFCore.InMemory.FunctionalTests/Query/NorthwindMiscellaneousQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/NorthwindMiscellaneousQueryInMemoryTest.cs index f1f280388e1..d280ae42e9d 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/NorthwindMiscellaneousQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/NorthwindMiscellaneousQueryInMemoryTest.cs @@ -65,10 +65,6 @@ public override void Client_code_using_instance_in_static_method() public override void Client_code_using_instance_method_throws() => base.Client_code_using_instance_method_throws(); - [ConditionalTheory(Skip = "Issue#24291")] - public override Task Select_nested_collection_with_distinct(bool async) - => base.Select_nested_collection_with_distinct(async); - public override async Task Max_on_empty_sequence_throws(bool async) { using var context = CreateContext(); From babdcd1fb5d1eaf9f7fac002439bb5af826e361d Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Mon, 13 Sep 2021 08:55:23 -0700 Subject: [PATCH 097/346] Query: Re-enable few tests (#25976) Resolves #17540 Resolves #22692 --- ...yExpressionTranslatingExpressionVisitor.cs | 3 +- .../Query/GearsOfWarQueryInMemoryTest.cs | 12 +++++--- .../Query/SpatialQueryInMemoryTest.cs | 7 ++--- ...exNavigationsQueryRelationalFixtureBase.cs | 8 +++++ ...onsSharedTypeQueryRelationalFixtureBase.cs | 7 +++++ .../Query/ComplexNavigationsQueryTestBase.cs | 13 ++------- .../Query/GearsOfWarQueryTestBase.cs | 2 +- .../ComplexNavigationsQuerySqlServerTest.cs | 29 +++++++++---------- 8 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs index 6faa1a40e9c..e14fc1cab44 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs @@ -276,8 +276,7 @@ protected override Expression VisitExtension(Expression extensionExpression) case EntityShaperExpression entityShaperExpression: return new EntityReferenceExpression(entityShaperExpression); - case ProjectionBindingExpression projectionBindingExpression - when projectionBindingExpression.ProjectionMember != null: + case ProjectionBindingExpression projectionBindingExpression: return ((InMemoryQueryExpression)projectionBindingExpression.QueryExpression).GetProjection(projectionBindingExpression); default: diff --git a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs index 7b4d689a42a..ef47a27a104 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs @@ -25,11 +25,15 @@ public override Task Client_member_and_unsupported_string_Equals_in_the_same_que CoreStrings.QueryUnableToTranslateMember(nameof(Gear.IsMarcus), nameof(Gear))); } - [ConditionalTheory(Skip = "issue #17540")] - public override Task + public override async Task Null_semantics_is_correctly_applied_for_function_comparisons_that_take_arguments_from_optional_navigation_complex(bool async) - => base.Null_semantics_is_correctly_applied_for_function_comparisons_that_take_arguments_from_optional_navigation_complex( - async); + { + Assert.Equal( + "Nullable object must have a value.", + (await Assert.ThrowsAsync( + () => base.Null_semantics_is_correctly_applied_for_function_comparisons_that_take_arguments_from_optional_navigation_complex( + async))).Message); + } [ConditionalTheory(Skip = "issue #19683")] public override Task Group_by_on_StartsWith_with_null_parameter_as_argument(bool async) diff --git a/test/EFCore.InMemory.FunctionalTests/Query/SpatialQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/SpatialQueryInMemoryTest.cs index 30890ca9af6..5f741be38c5 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/SpatialQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/SpatialQueryInMemoryTest.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; using System.Threading.Tasks; using Xunit; @@ -19,16 +20,14 @@ public override Task Distance_constant_lhs(bool async) return base.Distance_constant_lhs(async); } - [ConditionalTheory(Skip = "issue #19664")] public override Task Intersects_equal_to_null(bool async) { - return base.Intersects_equal_to_null(async); + return Assert.ThrowsAsync(() => base.Intersects_equal_to_null(async)); } - [ConditionalTheory(Skip = "issue #19664")] public override Task Intersects_not_equal_to_null(bool async) { - return base.Intersects_not_equal_to_null(async); + return Assert.ThrowsAsync(() => base.Intersects_not_equal_to_null(async)); } public override Task GetGeometryN_with_null_argument(bool async) diff --git a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsQueryRelationalFixtureBase.cs b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsQueryRelationalFixtureBase.cs index 3fb2193ec61..00a646543fe 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsQueryRelationalFixtureBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsQueryRelationalFixtureBase.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 Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.TestUtilities; namespace Microsoft.EntityFrameworkCore.Query @@ -9,5 +10,12 @@ public abstract class ComplexNavigationsQueryRelationalFixtureBase : ComplexNavi { public TestSqlLoggerFactory TestSqlLoggerFactory => (TestSqlLoggerFactory)ListLoggerFactory; + + public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + => base.AddOptions(builder).ConfigureWarnings( + c => c + .Log(CoreEventId.DistinctAfterOrderByWithoutRowLimitingOperatorWarning) + .Log(CoreEventId.FirstWithoutOrderByAndFilterWarning)) + .EnableDetailedErrors(); } } diff --git a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryRelationalFixtureBase.cs b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryRelationalFixtureBase.cs index 1662deb5f6b..b61011d4d7b 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryRelationalFixtureBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsSharedTypeQueryRelationalFixtureBase.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 Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.TestModels.ComplexNavigationsModel; using Microsoft.EntityFrameworkCore.TestUtilities; @@ -18,6 +19,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity(eb => eb.ToTable(nameof(Level1))); } + public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + => base.AddOptions(builder).ConfigureWarnings( + c => c + .Log(CoreEventId.DistinctAfterOrderByWithoutRowLimitingOperatorWarning) + .Log(CoreEventId.FirstWithoutOrderByAndFilterWarning)) + .EnableDetailedErrors(); protected override void Configure(OwnedNavigationBuilder l2) { diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs index ead3811794c..77a32131c8d 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsQueryTestBase.cs @@ -2764,7 +2764,7 @@ where l1.Id < 3 select l3).Distinct().OrderBy(l => l.Id).Skip(1).FirstOrDefault().Name); } - [ConditionalTheory(Skip = "issue #8523")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(bool async) { @@ -3402,15 +3402,6 @@ public virtual void Join_with_navigations_in_the_result_selector2() var result = query.ToList(); } - [ConditionalFact(Skip = "issue #12200")] - public virtual void GroupJoin_with_navigations_in_the_result_selector() - { - using var ctx = CreateContext(); - var query = ctx.LevelOne.GroupJoin( - ctx.LevelTwo, l1 => l1.Id, l2 => l2.Level1_Required_Id, (o, i) => new { o.OneToOne_Optional_FK1, i }); - var result = query.ToList(); - } - [ConditionalFact] public virtual void Member_pushdown_chain_3_levels_deep() { @@ -3607,7 +3598,7 @@ public virtual Task Sum_with_selector_cast_using_as(bool async) ss => ss.Set().Select(s => s.Id as int?)); } - [ConditionalTheory(Skip = "Issue#12657")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Sum_with_filter_with_include_selector_cast_using_as(bool async) { diff --git a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs index 5efddcda681..7463273c50b 100644 --- a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs @@ -7885,7 +7885,7 @@ public virtual Task Cast_to_derived_followed_by_include_and_FirstOrDefault(bool } - [ConditionalTheory(Skip = "issue #22692")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Cast_to_derived_followed_by_multiple_includes(bool async) { diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs index e4297e065c4..ba668023866 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs @@ -2526,7 +2526,16 @@ public override async Task Subquery_with_Distinct_Skip_FirstOrDefault_without_Or await base.Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(async); AssertSql( - ""); + @"SELECT ( + SELECT [t].[Name] + FROM ( + SELECT DISTINCT [l0].[Id], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id] + FROM [LevelThree] AS [l0] + ) AS [t] + ORDER BY (SELECT 1) + OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY) +FROM [LevelOne] AS [l] +WHERE [l].[Id] < 3"); } public override async Task Project_collection_navigation_count(bool async) @@ -3106,14 +3115,6 @@ FROM [LevelOne] AS [l] ORDER BY [l].[Id], [l0].[Id], [l1].[Id]"); } - public override void GroupJoin_with_navigations_in_the_result_selector() - { - base.GroupJoin_with_navigations_in_the_result_selector(); - - AssertSql( - @""); - } - public override void Member_pushdown_chain_3_levels_deep() { base.Member_pushdown_chain_3_levels_deep(); @@ -3336,14 +3337,12 @@ public override async Task Sum_with_filter_with_include_selector_cast_using_as(b await base.Sum_with_filter_with_include_selector_cast_using_as(async); AssertSql( - @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id] + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id] FROM [LevelOne] AS [l] -LEFT JOIN [LevelTwo] AS [l0] ON [l].[Id] = [l0].[OneToMany_Optional_Inverse2Id] WHERE [l].[Id] > ( - SELECT SUM([l1].[Id]) - FROM [LevelTwo] AS [l1] - WHERE [l].[Id] = [l1].[OneToMany_Optional_Inverse2Id]) -ORDER BY [l].[Id], [l0].[Id]"); + SELECT COALESCE(SUM([l0].[Id]), 0) + FROM [LevelTwo] AS [l0] + WHERE [l].[Id] = [l0].[OneToMany_Optional_Inverse2Id])"); } public override async Task Select_with_joined_where_clause_cast_using_as(bool async) From 637b9a22fa48b5f4e2774ff0c230311f0549ea54 Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Wed, 1 Sep 2021 15:16:34 -0700 Subject: [PATCH 098/346] Migrations: Honor [Column(Order)] in CreateTable operation Resolves #10059 --- .../Internal/ScaffoldingAnnotationNames.cs | 8 -- .../Internal/ScaffoldingPropertyExtensions.cs | 34 ----- .../Internal/CSharpDbContextGenerator.cs | 4 +- .../Internal/CSharpEntityTypeGenerator.cs | 2 +- .../RelationalScaffoldingModelFactory.cs | 2 +- .../Design/AnnotationCodeGenerator.cs | 8 ++ ...nalCSharpRuntimeAnnotationCodeGenerator.cs | 1 + .../Diagnostics/ColumnsEventData.cs | 46 +++++++ .../MigrationColumnOperationEventData.cs | 34 +++++ .../Diagnostics/RelationalEventId.cs | 28 +++++ .../Diagnostics/RelationalLoggerExtensions.cs | 76 ++++++++++- .../RelationalLoggingDefinitions.cs | 18 +++ .../RelationalPropertyBuilderExtensions.cs | 56 +++++++++ .../RelationalPropertyExtensions.cs | 68 ++++++++++ .../RelationalModelValidator.cs | 36 ++++++ .../RelationalColumnAttributeConvention.cs | 5 + .../RelationalRuntimeModelConvention.cs | 1 + src/EFCore.Relational/Metadata/IColumn.cs | 7 ++ .../Metadata/RelationalAnnotationNames.cs | 5 + .../Internal/MigrationsModelDiffer.cs | 25 +++- .../Migrations/MigrationsSqlGenerator.cs | 5 + .../Properties/RelationalStrings.Designer.cs | 82 ++++++++++-- .../Properties/RelationalStrings.resx | 17 ++- .../SqlServerMigrationsSqlGenerator.cs | 6 + .../SqliteMigrationsSqlGenerator.cs | 3 +- .../Design/CSharpMigrationsGeneratorTest.cs | 5 + .../Migrations/ModelSnapshotSqlServerTest.cs | 31 +++++ .../Internal/CSharpModelGeneratorTest.cs | 2 +- .../CSharpRuntimeModelCodeGeneratorTest.cs | 7 +- .../RelationalScaffoldingModelFactoryTest.cs | 6 +- .../RelationalModelValidatorTest.cs | 29 +++++ ...lationalPropertyAttributeConventionTest.cs | 6 + .../Internal/MigrationsModelDifferTest.cs | 118 ++++++++++++++++++ .../RelationalEventIdTest.cs | 6 +- .../SqliteMigrationsSqlGeneratorTest.cs | 38 ++++++ 35 files changed, 755 insertions(+), 70 deletions(-) delete mode 100644 src/EFCore.Design/Metadata/Internal/ScaffoldingPropertyExtensions.cs create mode 100644 src/EFCore.Relational/Diagnostics/ColumnsEventData.cs create mode 100644 src/EFCore.Relational/Diagnostics/MigrationColumnOperationEventData.cs diff --git a/src/EFCore.Design/Metadata/Internal/ScaffoldingAnnotationNames.cs b/src/EFCore.Design/Metadata/Internal/ScaffoldingAnnotationNames.cs index 5ba3449b0db..d2be29a1ef5 100644 --- a/src/EFCore.Design/Metadata/Internal/ScaffoldingAnnotationNames.cs +++ b/src/EFCore.Design/Metadata/Internal/ScaffoldingAnnotationNames.cs @@ -19,14 +19,6 @@ public static class ScaffoldingAnnotationNames /// public const string Prefix = "Scaffolding:"; - /// - /// 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 ColumnOrdinal = Prefix + "ColumnOrdinal"; - /// /// 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.Design/Metadata/Internal/ScaffoldingPropertyExtensions.cs b/src/EFCore.Design/Metadata/Internal/ScaffoldingPropertyExtensions.cs deleted file mode 100644 index af53e2a46e1..00000000000 --- a/src/EFCore.Design/Metadata/Internal/ScaffoldingPropertyExtensions.cs +++ /dev/null @@ -1,34 +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.Metadata.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 static class ScaffoldingPropertyExtensions - { - /// - /// 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 static int GetColumnOrdinal(this IReadOnlyProperty property) - => (int?)property[ScaffoldingAnnotationNames.ColumnOrdinal] ?? -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. - /// - public static void SetColumnOrdinal(this IMutableProperty property, int? ordinal) - => property.SetOrRemoveAnnotation( - ScaffoldingAnnotationNames.ColumnOrdinal, - ordinal); - } -} diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs index c0aacc2a032..5a09c3d454d 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs @@ -600,7 +600,7 @@ private void GenerateProperty(IProperty property) .FilterIgnoredAnnotations(property.GetAnnotations()) .ToDictionary(a => a.Name, a => a); _annotationCodeGenerator.RemoveAnnotationsHandledByConventions(property, annotations); - annotations.Remove(ScaffoldingAnnotationNames.ColumnOrdinal); + annotations.Remove(RelationalAnnotationNames.ColumnOrder); if (_useDataAnnotations) { @@ -879,7 +879,7 @@ private void GenerateManyToMany(ISkipNavigation skipNavigation) .FilterIgnoredAnnotations(property.GetAnnotations()) .ToDictionary(a => a.Name, a => a); _annotationCodeGenerator.RemoveAnnotationsHandledByConventions(property, propertyAnnotations); - propertyAnnotations.Remove(ScaffoldingAnnotationNames.ColumnOrdinal); + propertyAnnotations.Remove(RelationalAnnotationNames.ColumnOrder); if ((!_useNullableReferenceTypes || property.ClrType.IsValueType) && !property.IsNullable diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs index 2269e313aa5..2ddd507fedd 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs @@ -272,7 +272,7 @@ protected virtual void GenerateProperties(IEntityType entityType) { Check.NotNull(entityType, nameof(entityType)); - foreach (var property in entityType.GetProperties().OrderBy(p => p.GetColumnOrdinal())) + foreach (var property in entityType.GetProperties().OrderBy(p => p.GetColumnOrder() ?? -1)) { GenerateComment(property.GetComment()); diff --git a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs index 57d3deefe53..39db30a020e 100644 --- a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs @@ -519,7 +519,7 @@ protected virtual EntityTypeBuilder VisitColumns(EntityTypeBuilder builder, ICol property.IsConcurrencyToken(); } - property.Metadata.SetColumnOrdinal(column.Table.Columns.IndexOf(column)); + property.Metadata.SetColumnOrder(column.Table.Columns.IndexOf(column)); property.Metadata.AddAnnotations( column.GetAnnotations().Where( diff --git a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs index 93548874e1d..f5dd8e73498 100644 --- a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs @@ -55,6 +55,10 @@ private static readonly MethodInfo _propertyHasColumnNameMethodInfo = typeof(RelationalPropertyBuilderExtensions).GetRequiredRuntimeMethod( nameof(RelationalPropertyBuilderExtensions.HasColumnName), typeof(PropertyBuilder), typeof(string)); + private static readonly MethodInfo _propertyHasColumnOrderMethodInfo + = typeof(RelationalPropertyBuilderExtensions).GetRequiredRuntimeMethod( + nameof(RelationalPropertyBuilderExtensions.HasColumnOrder), typeof(PropertyBuilder), typeof(int?)); + private static readonly MethodInfo _propertyHasDefaultValueSqlMethodInfo1 = typeof(RelationalPropertyBuilderExtensions).GetRequiredRuntimeMethod( nameof(RelationalPropertyBuilderExtensions.HasDefaultValueSql), typeof(PropertyBuilder)); @@ -221,6 +225,10 @@ public virtual IReadOnlyList GenerateFluentApiCalls( annotations, RelationalAnnotationNames.ColumnName, _propertyHasColumnNameMethodInfo, methodCallCodeFragments); + GenerateSimpleFluentApiCall( + annotations, + RelationalAnnotationNames.ColumnOrder, _propertyHasColumnOrderMethodInfo, methodCallCodeFragments); + if (TryGetAndRemove(annotations, RelationalAnnotationNames.DefaultValueSql, out string? defaultValueSql)) { methodCallCodeFragments.Add( diff --git a/src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs index 165fb5283e9..0789a825c32 100644 --- a/src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs @@ -367,6 +367,7 @@ public override void Generate(IProperty property, CSharpRuntimeAnnotationCodeGen } else { + annotations.Remove(RelationalAnnotationNames.ColumnOrder); annotations.Remove(RelationalAnnotationNames.Comment); annotations.Remove(RelationalAnnotationNames.Collation); diff --git a/src/EFCore.Relational/Diagnostics/ColumnsEventData.cs b/src/EFCore.Relational/Diagnostics/ColumnsEventData.cs new file mode 100644 index 00000000000..592979376ea --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/ColumnsEventData.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.EntityFrameworkCore.Metadata; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// A event payload class for events that have columns. + /// + public class ColumnsEventData : EventData + { + /// + /// Constructs the event payload. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The table. + /// The columns. + public ColumnsEventData( + EventDefinitionBase eventDefinition, + Func messageGenerator, + StoreObjectIdentifier storeObject, + IReadOnlyList columns) + : base(eventDefinition, messageGenerator) + { + StoreObject = storeObject; + Columns = columns; + } + + /// + /// Gets the table. + /// + /// The table. + public virtual StoreObjectIdentifier StoreObject { get; } + + /// + /// Gets the columns. + /// + /// The columns. + public virtual IReadOnlyList Columns { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/MigrationColumnOperationEventData.cs b/src/EFCore.Relational/Diagnostics/MigrationColumnOperationEventData.cs new file mode 100644 index 00000000000..e94b37fa0b4 --- /dev/null +++ b/src/EFCore.Relational/Diagnostics/MigrationColumnOperationEventData.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using Microsoft.EntityFrameworkCore.Migrations.Operations; + +namespace Microsoft.EntityFrameworkCore.Diagnostics +{ + /// + /// The event payload for events that reference a Migrations column operation. + /// + public class MigrationColumnOperationEventData : EventData + { + /// + /// Initializes a new instance of the class. + /// + /// The event definition. + /// A delegate that generates a log message for this event. + /// The column operation. + public MigrationColumnOperationEventData( + EventDefinitionBase eventDefinition, + Func messageGenerator, + ColumnOperation columnOperation) + : base(eventDefinition, messageGenerator) + => ColumnOperation = columnOperation; + + /// + /// Gets the column operation. + /// + /// The column operation. + public virtual ColumnOperation ColumnOperation { get; } + } +} diff --git a/src/EFCore.Relational/Diagnostics/RelationalEventId.cs b/src/EFCore.Relational/Diagnostics/RelationalEventId.cs index 0edfb562e47..04fdbf13ac8 100644 --- a/src/EFCore.Relational/Diagnostics/RelationalEventId.cs +++ b/src/EFCore.Relational/Diagnostics/RelationalEventId.cs @@ -72,6 +72,7 @@ private enum Id MigrationsNotApplied, MigrationsNotFound, MigrationAttributeMissingWarning, + ColumnOrderIgnoredWarning, // Query events QueryClientEvaluationWarning = CoreEventId.RelationalBaseId + 500, @@ -88,6 +89,7 @@ private enum Id IndexPropertiesMappedToNonOverlappingTables, ForeignKeyPropertiesMappedToUnrelatedTables, OptionalDependentWithoutIdentifyingPropertyWarning, + DuplicateColumnOrders, // Update events BatchReadyForExecution = CoreEventId.RelationalBaseId + 700, @@ -598,6 +600,19 @@ private static EventId MakeMigrationsId(Id id) /// public static readonly EventId MigrationAttributeMissingWarning = MakeMigrationsId(Id.MigrationAttributeMissingWarning); + /// + /// + /// Column order was ignored. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// + /// + public static readonly EventId ColumnOrderIgnoredWarning = MakeMigrationsId(Id.ColumnOrderIgnoredWarning); + private static readonly string _queryPrefix = DbLoggerCategory.Query.Name + "."; private static EventId MakeQueryId(Id id) @@ -739,6 +754,19 @@ private static EventId MakeValidationId(Id id) public static readonly EventId OptionalDependentWithoutIdentifyingPropertyWarning = MakeValidationId(Id.OptionalDependentWithoutIdentifyingPropertyWarning); + /// + /// + /// The configured column orders for a table contains duplicates. + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// + /// + public static readonly EventId DuplicateColumnOrders = MakeValidationId(Id.DuplicateColumnOrders); + private static readonly string _updatePrefix = DbLoggerCategory.Update.Name + "."; private static EventId MakeUpdateId(Id id) diff --git a/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs b/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs index 60c550ddbf2..c754ee114f2 100644 --- a/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs +++ b/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs @@ -6,7 +6,6 @@ using System.Data; using System.Data.Common; using System.Diagnostics; -using System.Globalization; using System.Linq; using System.Reflection; using System.Threading; @@ -18,9 +17,9 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Internal; +using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.Update; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.Logging; @@ -3033,5 +3032,78 @@ private static string OptionalDependentWithAllNullPropertiesWarningSensitive(Eve var p = (UpdateEntryEventData)payload; return d.GenerateMessage(p.EntityEntry.EntityType.DisplayName(), p.EntityEntry.BuildCurrentValuesString(p.EntityEntry.EntityType.FindPrimaryKey()!.Properties)); } + + /// + /// Logs the event. + /// + /// The diagnostics logger to use. + /// The table. + /// The columns. + public static void DuplicateColumnOrders( + this IDiagnosticsLogger diagnostics, + StoreObjectIdentifier storeObject, + IReadOnlyList columns) + { + var definition = RelationalResources.LogDuplicateColumnOrders(diagnostics); + + if (diagnostics.ShouldLog(definition)) + { + definition.Log(diagnostics, storeObject.DisplayName(), string.Join(", ", columns.Select(c => "'" + c + "'"))); + } + + if (diagnostics.NeedsEventData(definition, out var diagnosticSourceEnabled, out var simpleLogEnabled)) + { + var eventData = new ColumnsEventData( + definition, + DuplicateColumnOrders, + storeObject, + columns); + + diagnostics.DispatchEventData(definition, eventData, diagnosticSourceEnabled, simpleLogEnabled); + } + } + + private static string DuplicateColumnOrders(EventDefinitionBase definition, EventData payload) + { + var d = (EventDefinition)definition; + var p = (ColumnsEventData)payload; + + return d.GenerateMessage(p.StoreObject.DisplayName(), string.Join(", ", p.Columns.Select(c => "'" + c + "'"))); + } + + /// + /// 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 static void ColumnOrderIgnoredWarning( + this IDiagnosticsLogger diagnostics, + ColumnOperation operation) + { + var definition = RelationalResources.LogColumnOrderIgnoredWarning(diagnostics); + + if (diagnostics.ShouldLog(definition)) + { + definition.Log(diagnostics, (operation.Table, operation.Schema).FormatTable(), operation.Name); + } + + if (diagnostics.NeedsEventData(definition, out var diagnosticSourceEnabled, out var simpleLogEnabled)) + { + var eventData = new MigrationColumnOperationEventData( + definition, + ColumnOrderIgnoredWarning, + operation); + + diagnostics.DispatchEventData(definition, eventData, diagnosticSourceEnabled, simpleLogEnabled); + } + } + + private static string ColumnOrderIgnoredWarning(EventDefinitionBase definition, EventData payload) + { + var d = (EventDefinition)definition; + var p = (MigrationColumnOperationEventData)payload; + return d.GenerateMessage((p.ColumnOperation.Table, p.ColumnOperation.Schema).FormatTable(), p.ColumnOperation.Name); + } } } diff --git a/src/EFCore.Relational/Diagnostics/RelationalLoggingDefinitions.cs b/src/EFCore.Relational/Diagnostics/RelationalLoggingDefinitions.cs index d79b4e03445..ff254134937 100644 --- a/src/EFCore.Relational/Diagnostics/RelationalLoggingDefinitions.cs +++ b/src/EFCore.Relational/Diagnostics/RelationalLoggingDefinitions.cs @@ -530,5 +530,23 @@ public abstract class RelationalLoggingDefinitions : LoggingDefinitions /// [EntityFrameworkInternal] public EventDefinitionBase? LogOptionalDependentWithAllNullPropertiesSensitive; + + /// + /// 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 EventDefinitionBase? LogDuplicateColumnOrders; + + /// + /// 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 EventDefinitionBase? LogColumnOrderIgnoredWarning; } } diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyBuilderExtensions.cs index 83e4f2ef92a..d37f5f2eedc 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertyBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertyBuilderExtensions.cs @@ -129,6 +129,62 @@ public static bool CanSetColumnName( || overrides.ColumnName == name; } + /// + /// Configures the order of the column the property is mapped to. + /// + /// The builder of the property being configured. + /// The column order. + /// The same builder instance so that multiple calls can be chained. + public static PropertyBuilder HasColumnOrder(this PropertyBuilder propertyBuilder, int? order) + { + Check.NotNull(propertyBuilder, nameof(propertyBuilder)); + + propertyBuilder.Metadata.SetColumnOrder(order); + + return propertyBuilder; + } + + /// + /// Configures the order of the column the property is mapped to. + /// + /// The builder of the property being configured. + /// The column order. + /// The same builder instance so that multiple calls can be chained. + public static PropertyBuilder HasColumnOrder(this PropertyBuilder propertyBuilder, int? order) + => (PropertyBuilder)HasColumnOrder((PropertyBuilder)propertyBuilder, order); + + /// + /// Configures the order of the column the property is mapped to. + /// + /// The builder of the property being configured. + /// The column order. + /// A value indicating whether the configuration was specified using a data annotation. + /// The same builder instance if the configuration was applied, otherwise. + public static IConventionPropertyBuilder? HasColumnOrder( + this IConventionPropertyBuilder propertyBuilder, + int? order, + bool fromDataAnnotation = false) + { + if (!propertyBuilder.CanSetColumnOrder(order, fromDataAnnotation)) + { + return null; + } + + propertyBuilder.Metadata.SetColumnOrder(order, fromDataAnnotation); + + return propertyBuilder; + } + + /// + /// Gets a value indicating whether the given column order can be set for the property. + /// + /// The builder of the property being configured. + /// The column order. + /// A value indicating whether the configuration was specified using a data annotation. + /// if the column order can be set for the property. + public static bool CanSetColumnOrder(this IConventionPropertyBuilder propertyBuilder, int? order, bool fromDataAnnotation = false) + => propertyBuilder.CanSetAnnotation(RelationalAnnotationNames.ColumnOrder, order, fromDataAnnotation); + /// /// Configures the data type of the column that the property maps to when targeting a relational database. /// This should be the complete type name, including precision, scale, length, etc. diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs index c8174eb0649..87184726308 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs @@ -277,6 +277,74 @@ public static void SetColumnName( in StoreObjectIdentifier storeObject) => ((RelationalPropertyOverrides?)RelationalPropertyOverrides.Find(property, storeObject))?.GetColumnNameConfigurationSource(); + /// + /// Returns the order of the column this property is mapped to. + /// + /// The property. + /// The column order. + public static int? GetColumnOrder(this IReadOnlyProperty property) + => property is RuntimeProperty + ? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData) + : (int?)property.FindAnnotation(RelationalAnnotationNames.ColumnOrder)?.Value; + + /// + /// Returns the order of the column this property is mapped to for a particular table. + /// + /// The property. + /// The identifier of the table-like store object containing the column. + /// The column order. + public static int? GetColumnOrder(this IReadOnlyProperty property, in StoreObjectIdentifier storeObject) + { + if (property is RuntimeProperty) + { + throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData); + } + + var annotation = property.FindAnnotation(RelationalAnnotationNames.ColumnOrder); + if (annotation != null) + { + return (int?)annotation.Value; + } + + var sharedTableRootProperty = property.FindSharedStoreObjectRootProperty(storeObject); + if (sharedTableRootProperty != null) + { + return GetColumnOrder(sharedTableRootProperty, storeObject); + } + + return null; + } + + /// + /// Sets the order of the column the property is mapped to. + /// + /// The property. + /// The column order. + public static void SetColumnOrder(this IMutableProperty property, int? order) + => property.SetOrRemoveAnnotation(RelationalAnnotationNames.ColumnOrder, order); + + /// + /// Sets the order of the column the property is mapped to. + /// + /// The property. + /// The column order. + /// A value indicating whether the configuration was specified using a data annotation. + /// The configured value. + public static int? SetColumnOrder(this IConventionProperty property, int? order, bool fromDataAnnotation = false) + { + property.SetOrRemoveAnnotation(RelationalAnnotationNames.ColumnOrder, order, fromDataAnnotation); + + return order; + } + + /// + /// Gets the of the column order. + /// + /// The property. + /// The . + public static ConfigurationSource? GetColumnOrderConfigurationSource(this IConventionProperty property) + => property.FindAnnotation(RelationalAnnotationNames.ColumnName)?.GetConfigurationSource(); + /// /// Returns the database type of the column to which the property is mapped, or if the database type /// could not be found. diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs index 69ea9a40dad..166e8b99063 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs @@ -738,6 +738,26 @@ protected virtual void ValidateSharedColumnsCompatibility( } } } + + var columnOrders = new Dictionary>(); + foreach (var property in propertyMappings.Values) + { + var columnOrder = property.GetColumnOrder(storeObject); + if (!columnOrder.HasValue) + { + continue; + } + + var columns = columnOrders.GetOrAddNew(columnOrder.Value); + columns.Add(property.GetColumnName(storeObject)!); + } + + if (columnOrders.Any(g => g.Value.Count > 1)) + { + logger.DuplicateColumnOrders( + storeObject, + columnOrders.Where(g => g.Value.Count > 1).SelectMany(g => g.Value).ToList()); + } } /// @@ -972,6 +992,22 @@ protected virtual void ValidateCompatible( previousCollation, currentCollation)); } + + var currentColumnOrder = property.GetColumnOrder(storeObject); + var previousColumnOrder = duplicateProperty.GetColumnOrder(storeObject); + if (currentColumnOrder != previousColumnOrder) + { + throw new InvalidOperationException( + RelationalStrings.DuplicateColumnNameOrderMismatch( + duplicateProperty.DeclaringEntityType.DisplayName(), + duplicateProperty.Name, + property.DeclaringEntityType.DisplayName(), + property.Name, + columnName, + storeObject.DisplayName(), + previousColumnOrder, + currentColumnOrder)); + } } /// diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs index 38a2727d04e..02e7d426187 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs @@ -56,6 +56,11 @@ protected override void ProcessPropertyAdded( { propertyBuilder.HasColumnType(attribute.TypeName, fromDataAnnotation: true); } + + if (attribute.Order >= 0) + { + propertyBuilder.HasColumnOrder(attribute.Order, fromDataAnnotation: true); + } } } } diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalRuntimeModelConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalRuntimeModelConvention.cs index 0a6cae53807..a959d3b1cea 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalRuntimeModelConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalRuntimeModelConvention.cs @@ -255,6 +255,7 @@ protected override void ProcessPropertyAnnotations( } else { + annotations.Remove(RelationalAnnotationNames.ColumnOrder); annotations.Remove(RelationalAnnotationNames.Comment); annotations.Remove(RelationalAnnotationNames.Collation); diff --git a/src/EFCore.Relational/Metadata/IColumn.cs b/src/EFCore.Relational/Metadata/IColumn.cs index f9ea1081fa4..413f8f74631 100644 --- a/src/EFCore.Relational/Metadata/IColumn.cs +++ b/src/EFCore.Relational/Metadata/IColumn.cs @@ -64,6 +64,13 @@ bool IsRowVersion => PropertyMappings.First().Property.IsConcurrencyToken && PropertyMappings.First().Property.ValueGenerated == ValueGenerated.OnAddOrUpdate; + /// + /// Gets the column order. + /// + /// The column order. + public virtual int? Order + => PropertyMappings.First().Property.GetColumnOrder(StoreObjectIdentifier.Table(Table.Name, Table.Schema)); + /// /// Returns the object that is used as the default value for this column. /// diff --git a/src/EFCore.Relational/Metadata/RelationalAnnotationNames.cs b/src/EFCore.Relational/Metadata/RelationalAnnotationNames.cs index e1b3b0ecd1d..eca1b00e452 100644 --- a/src/EFCore.Relational/Metadata/RelationalAnnotationNames.cs +++ b/src/EFCore.Relational/Metadata/RelationalAnnotationNames.cs @@ -21,6 +21,11 @@ public static class RelationalAnnotationNames /// public const string ColumnName = Prefix + "ColumnName"; + /// + /// The name for column order annotations. + /// + public const string ColumnOrder = Prefix + "ColumnOrder"; + /// /// The name for column type annotations. /// diff --git a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs index ab09750a5ef..8952357e1ce 100644 --- a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs +++ b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs @@ -739,7 +739,11 @@ private static IEnumerable GetSortedColumns(ITable table) } } - return sortedColumns; + Check.DebugAssert(columns.Count == 0, "columns is not empty"); + + return sortedColumns.Where(c => c.Order.HasValue).OrderBy(c => c.Order) + .Concat(sortedColumns.Where(c => !c.Order.HasValue)) + .Concat(columns); } private static IEnumerable GetSortedProperties(IEntityType entityType, ITable table) @@ -1030,6 +1034,7 @@ protected virtual IEnumerable Diff( || !Equals(sourceDefault, targetDefault) || source.Comment != target.Comment || source.Collation != target.Collation + || source.Order != target.Order || HasDifferences(sourceMigrationsAnnotations, targetMigrationsAnnotations)) { var isDestructiveChange = isNullableChanged && source.IsNullable @@ -1055,6 +1060,19 @@ protected virtual IEnumerable Diff( alterColumnOperation.OldColumn, source, sourceTypeMapping, source.IsNullable, sourceMigrationsAnnotations, inline: true); + if (source.Order != target.Order) + { + if (source.Order.HasValue) + { + alterColumnOperation.OldColumn.AddAnnotation(RelationalAnnotationNames.ColumnOrder, source.Order.Value); + } + + if (target.Order.HasValue) + { + alterColumnOperation.AddAnnotation(RelationalAnnotationNames.ColumnOrder, target.Order.Value); + } + } + yield return alterColumnOperation; } } @@ -1086,6 +1104,11 @@ protected virtual IEnumerable Add( operation, target, targetTypeMapping, target.IsNullable, target.GetAnnotations(), inline); + if (!inline && target.Order.HasValue) + { + operation.AddAnnotation(RelationalAnnotationNames.ColumnOrder, target.Order.Value); + } + yield return operation; } diff --git a/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs b/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs index 2b9b4ae03e1..8ebacab078a 100644 --- a/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs +++ b/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs @@ -193,6 +193,11 @@ protected virtual void Generate( Check.NotNull(operation, nameof(operation)); Check.NotNull(builder, nameof(builder)); + if (operation[RelationalAnnotationNames.ColumnOrder] != null) + { + Dependencies.MigrationsLogger.ColumnOrderIgnoredWarning(operation); + } + builder .Append("ALTER TABLE ") .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema)) diff --git a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs index 4244c78f8db..34c87273ba9 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs +++ b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs @@ -1,7 +1,9 @@ // using System; +using System.Reflection; using System.Resources; +using System.Threading; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.Logging; @@ -403,6 +405,14 @@ public static string DuplicateColumnNameNullabilityMismatch(object? entityType1, GetString("DuplicateColumnNameNullabilityMismatch", nameof(entityType1), nameof(property1), nameof(entityType2), nameof(property2), nameof(columnName), nameof(table)), entityType1, property1, entityType2, property2, columnName, table); + /// + /// '{entityType1}.{property1}' and '{entityType2}.{property2}' are both mapped to column '{columnName}' in '{table}', but are configured to use different column orders ('{columnOrder1}' and '{columnOrder2}'). + /// + public static string DuplicateColumnNameOrderMismatch(object? entityType1, object? property1, object? entityType2, object? property2, object? columnName, object? table, object? columnOrder1, object? columnOrder2) + => string.Format( + GetString("DuplicateColumnNameOrderMismatch", nameof(entityType1), nameof(property1), nameof(entityType2), nameof(property2), nameof(columnName), nameof(table), nameof(columnOrder1), nameof(columnOrder2)), + entityType1, property1, entityType2, property2, columnName, table, columnOrder1, columnOrder2); + /// /// '{entityType1}.{property1}' and '{entityType2}.{property2}' are both mapped to column '{columnName}' in '{table}', but are configured with different precisions ('{precision1}' and '{precision2}'). /// @@ -483,6 +493,14 @@ public static string DuplicateIndexColumnMismatch(object? indexProperties1, obje GetString("DuplicateIndexColumnMismatch", nameof(indexProperties1), nameof(entityType1), nameof(indexProperties2), nameof(entityType2), nameof(table), nameof(indexName), nameof(columnNames1), nameof(columnNames2)), indexProperties1, entityType1, indexProperties2, entityType2, table, indexName, columnNames1, columnNames2); + /// + /// The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different filters ('{filter1}' and '{filter2}'). + /// + public static string DuplicateIndexFiltersMismatch(object? indexProperties1, object? entityType1, object? indexProperties2, object? entityType2, object? table, object? indexName, object? filter1, object? filter2) + => string.Format( + GetString("DuplicateIndexFiltersMismatch", nameof(indexProperties1), nameof(entityType1), nameof(indexProperties2), nameof(entityType2), nameof(table), nameof(indexName), nameof(filter1), nameof(filter2)), + indexProperties1, entityType1, indexProperties2, entityType2, table, indexName, filter1, filter2); + /// /// The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{indexName}', but are declared on different tables ('{table1}' and '{table2}'). /// @@ -499,14 +517,6 @@ public static string DuplicateIndexUniquenessMismatch(object? indexProperties1, GetString("DuplicateIndexUniquenessMismatch", nameof(indexProperties1), nameof(entityType1), nameof(indexProperties2), nameof(entityType2), nameof(table), nameof(indexName)), indexProperties1, entityType1, indexProperties2, entityType2, table, indexName); - /// - /// The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different filters ('{filter1}' and '{filter2}'). - /// - public static string DuplicateIndexFiltersMismatch(object? indexProperties1, object? entityType1, object? indexProperties2, object? entityType2, object? table, object? indexName, object? filter1, object? filter2) - => string.Format( - GetString("DuplicateIndexFiltersMismatch", nameof(indexProperties1), nameof(entityType1), nameof(indexProperties2), nameof(entityType2), nameof(table), nameof(indexName), nameof(filter1), nameof(filter2)), - indexProperties1, entityType1, indexProperties2, entityType2, table, indexName, filter1, filter2); - /// /// The keys {keyProperties1} on '{entityType1}' and {keyProperties2} on '{entityType2}' are both mapped to '{table}.{keyName}', but with different columns ({columnNames1} and {columnNames2}). /// @@ -1116,10 +1126,10 @@ public static string UnableToBindMemberToEntityProjection(object? memberType, ob /// /// Unhandled annotatable type '{annotatableType}'. /// - public static string UnhandledAnnotatableType(object? expressionType) + public static string UnhandledAnnotatableType(object? annotatableType) => string.Format( - GetString("UnhandledAnnotatableType", nameof(expressionType)), - expressionType); + GetString("UnhandledAnnotatableType", nameof(annotatableType)), + annotatableType); /// /// Unhandled expression '{expression}' of type '{expressionType}' encountered in '{visitor}'. @@ -1579,6 +1589,31 @@ public static EventDefinition LogClosingConnection(IDiagnosticsL return (EventDefinition)definition; } + /// + /// The order of column '{table}.{column}' was ignored. Column orders are only used when the table is first created. + /// + public static EventDefinition LogColumnOrderIgnoredWarning(IDiagnosticsLogger logger) + { + var definition = ((RelationalLoggingDefinitions)logger.Definitions).LogColumnOrderIgnoredWarning; + if (definition == null) + { + definition = NonCapturingLazyInitializer.EnsureInitialized( + ref ((RelationalLoggingDefinitions)logger.Definitions).LogColumnOrderIgnoredWarning, + logger, + static logger => new EventDefinition( + logger.Options, + RelationalEventId.ColumnOrderIgnoredWarning, + LogLevel.Warning, + "RelationalEventId.ColumnOrderIgnoredWarning", + level => LoggerMessage.Define( + level, + RelationalEventId.ColumnOrderIgnoredWarning, + _resourceManager.GetString("LogColumnOrderIgnoredWarning")!))); + } + + return (EventDefinition)definition; + } + /// /// Created DbCommand for '{executionType}' ({elapsed}ms). /// @@ -1854,6 +1889,31 @@ public static EventDefinition LogDisposingTransaction(IDiagnosticsLogger logger) return (EventDefinition)definition; } + /// + /// The configured column orders for the table '{table}' contains duplicates. Ensure the specified column order values are distinct. Conflicting columns: {columns} + /// + public static EventDefinition LogDuplicateColumnOrders(IDiagnosticsLogger logger) + { + var definition = ((RelationalLoggingDefinitions)logger.Definitions).LogDuplicateColumnOrders; + if (definition == null) + { + definition = NonCapturingLazyInitializer.EnsureInitialized( + ref ((RelationalLoggingDefinitions)logger.Definitions).LogDuplicateColumnOrders, + logger, + static logger => new EventDefinition( + logger.Options, + RelationalEventId.DuplicateColumnOrders, + LogLevel.Error, + "RelationalEventId.DuplicateColumnOrders", + level => LoggerMessage.Define( + level, + RelationalEventId.DuplicateColumnOrders, + _resourceManager.GetString("LogDuplicateColumnOrders")!))); + } + + return (EventDefinition)definition; + } + /// /// Executed DbCommand ({elapsed}ms) [Parameters=[{parameters}], CommandType='{commandType}', CommandTimeout='{commandTimeout}']{newLine}{commandText} /// diff --git a/src/EFCore.Relational/Properties/RelationalStrings.resx b/src/EFCore.Relational/Properties/RelationalStrings.resx index b0a1e6bada0..30ceccf692e 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.resx +++ b/src/EFCore.Relational/Properties/RelationalStrings.resx @@ -267,6 +267,9 @@ '{entityType1}.{property1}' and '{entityType2}.{property2}' are both mapped to column '{columnName}' in '{table}', but are configured with different nullability settings. + + '{entityType1}.{property1}' and '{entityType2}.{property2}' are both mapped to column '{columnName}' in '{table}', but are configured to use different column orders ('{columnOrder1}' and '{columnOrder2}'). + '{entityType1}.{property1}' and '{entityType2}.{property2}' are both mapped to column '{columnName}' in '{table}', but are configured with different precisions ('{precision1}' and '{precision2}'). @@ -297,15 +300,15 @@ The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different columns ({columnNames1} and {columnNames2}). + + The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different filters ('{filter1}' and '{filter2}'). + The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{indexName}', but are declared on different tables ('{table1}' and '{table2}'). The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different uniqueness configurations. - - The indexes {indexProperties1} on '{entityType1}' and {indexProperties2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different filters ('{filter1}' and '{filter2}'). - The keys {keyProperties1} on '{entityType1}' and {keyProperties2} on '{entityType2}' are both mapped to '{table}.{keyName}', but with different columns ({columnNames1} and {columnNames2}). @@ -456,6 +459,10 @@ Closing connection to database '{database}' on server '{server}'. Debug RelationalEventId.ConnectionClosing string string + + The order of column '{table}.{column}' was ignored. Column orders are only used when the table is first created. + Warning RelationalEventId.ColumnOrderIgnoredWarning string string + Created DbCommand for '{executionType}' ({elapsed}ms). Debug RelationalEventId.CommandCreated string int @@ -500,6 +507,10 @@ Disposing transaction. Debug RelationalEventId.TransactionDisposed + + The configured column orders for the table '{table}' contains duplicates. Ensure the specified column order values are distinct. Conflicting columns: {columns} + Error RelationalEventId.DuplicateColumnOrders string string + Executed DbCommand ({elapsed}ms) [Parameters=[{parameters}], CommandType='{commandType}', CommandTimeout='{commandTimeout}']{newLine}{commandText} Information RelationalEventId.CommandExecuted string string System.Data.CommandType int string string diff --git a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs index f0221440284..19289767eba 100644 --- a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs +++ b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations.Operations; @@ -244,6 +245,11 @@ protected override void Generate( Check.NotNull(operation, nameof(operation)); Check.NotNull(builder, nameof(builder)); + if (operation[RelationalAnnotationNames.ColumnOrder] != operation.OldColumn[RelationalAnnotationNames.ColumnOrder]) + { + Dependencies.MigrationsLogger.ColumnOrderIgnoredWarning(operation); + } + IEnumerable? indexesToRebuild = null; var column = model?.GetRelationalModel().FindTable(operation.Table, operation.Schema) ?.Columns.FirstOrDefault(c => c.Name == operation.Name); diff --git a/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs b/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs index 8f85d47e404..0dc4ed4c3e9 100644 --- a/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs +++ b/src/EFCore.Sqlite.Core/Migrations/SqliteMigrationsSqlGenerator.cs @@ -312,7 +312,8 @@ private IReadOnlyList RewriteOperations( createTableOperation.PrimaryKey = AddPrimaryKeyOperation.CreateFrom(primaryKey); } - foreach (var column in table.Columns) + foreach (var column in table.Columns.Where(c => c.Order.HasValue).OrderBy(c => c.Order.Value) + .Concat(table.Columns.Where(c => !c.Order.HasValue))) { if (!column.TryGetDefaultValue(out var defaultValue)) { diff --git a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.cs b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.cs index bcd377ce3ac..7f25686fcce 100644 --- a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.cs @@ -64,6 +64,7 @@ public void Test_new_annotations_handled_for_entity_types() CoreAnnotationNames.EagerLoaded, CoreAnnotationNames.DuplicateServiceProperties, RelationalAnnotationNames.ColumnName, + RelationalAnnotationNames.ColumnOrder, RelationalAnnotationNames.ColumnType, RelationalAnnotationNames.TableColumnMappings, RelationalAnnotationNames.ViewColumnMappings, @@ -245,6 +246,10 @@ public void Test_new_annotations_handled_for_properties() RelationalAnnotationNames.ColumnName, ("MyColumn", $@"{columnMapping}{_nl}.{nameof(RelationalPropertyBuilderExtensions.HasColumnName)}(""MyColumn"")") }, + { + RelationalAnnotationNames.ColumnOrder, + (1, $@"{columnMapping}{_nl}.{nameof(RelationalPropertyBuilderExtensions.HasColumnOrder)}(1)") + }, { RelationalAnnotationNames.ColumnType, ("int", $@"{_nl}.{nameof(RelationalPropertyBuilderExtensions.HasColumnType)}(""int"")") diff --git a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs index c031d6f994d..ecc0398c898 100644 --- a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs +++ b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs @@ -3763,6 +3763,37 @@ public virtual void Property_with_identity_column_custom_seed_increment() }); } + [ConditionalFact] + public virtual void Property_column_order_annotation_is_stored_in_snapshot_as_fluent_api() + { + Test( + builder => + { + builder.Entity().Property("AlternateId").HasColumnOrder(1); + builder.Ignore(); + }, + AddBoilerPlate( + GetHeading() + + @" + modelBuilder.Entity(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithTwoProperties"", b => + { + b.Property(""Id"") + .ValueGeneratedOnAdd() + .HasColumnType(""int""); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property(""Id""), 1L, 1); + + b.Property(""AlternateId"") + .HasColumnType(""int"") + .HasColumnOrder(1); + + b.HasKey(""Id""); + + b.ToTable(""EntityWithTwoProperties""); + });"), + o => Assert.Equal(1, o.GetEntityTypes().First().FindProperty("AlternateId").GetColumnOrder())); + } + #endregion #region HasKey diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpModelGeneratorTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpModelGeneratorTest.cs index 29066bf0bf8..216db0bb068 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpModelGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpModelGeneratorTest.cs @@ -29,7 +29,7 @@ public void WriteCode_works() { var generator = CreateGenerator(); var modelBuilder = RelationalTestHelpers.Instance.CreateConventionBuilder(); - modelBuilder.Entity("TestEntity").Property("Id").HasAnnotation(ScaffoldingAnnotationNames.ColumnOrdinal, 0); + modelBuilder.Entity("TestEntity").Property("Id"); var result = generator.GenerateModel( modelBuilder.FinalizeModel(designTime: true), diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs index 2cc88a9c5ef..c93b47dedc1 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs @@ -1929,6 +1929,10 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) Assert.Equal( CoreStrings.RuntimeModelMissingData, Assert.Throws(() => rowid.GetCollation()).Message); + Assert.Null(rowid[RelationalAnnotationNames.ColumnOrder]); + Assert.Equal( + CoreStrings.RuntimeModelMissingData, + Assert.Throws(() => rowid.GetColumnOrder()).Message); Assert.Null(rowid.GetValueConverter()); Assert.NotNull(rowid.GetValueComparer()); Assert.NotNull(rowid.GetKeyValueComparer()); @@ -2115,7 +2119,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) jb.Property("rowid") .IsRowVersion() .HasComment("RowVersion") - .UseCollation("ri"); + .UseCollation("ri") + .HasColumnOrder(1); }); eb.Navigation(e => e.Principals).AutoInclude(); diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs index f09d8645523..c2a84daa5a8 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs @@ -422,9 +422,9 @@ public void Column_ordinal_annotation() var property2 = (Property)entityTypeA.FindProperty("Col2"); var property3 = (Property)entityTypeA.FindProperty("Col3"); - Assert.Equal(0, property1.GetColumnOrdinal()); - Assert.Equal(1, property2.GetColumnOrdinal()); - Assert.Equal(2, property3.GetColumnOrdinal()); + Assert.Equal(0, property1.GetColumnOrder()); + Assert.Equal(1, property2.GetColumnOrder()); + Assert.Equal(2, property3.GetColumnOrder()); } [ConditionalTheory] diff --git a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs index 9049e58ca6b..add186ec9a9 100644 --- a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs +++ b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs @@ -820,6 +820,20 @@ public virtual void Detects_duplicate_column_names_within_hierarchy_with_differe modelBuilder); } + [ConditionalFact] + public virtual void Detects_duplicate_column_names_within_hierarchy_with_different_orders() + { + var modelBuilder = CreateConventionalModelBuilder(); + modelBuilder.Entity(); + modelBuilder.Entity().Property(c => c.Breed).HasColumnName("Breed").HasColumnOrder(0); + modelBuilder.Entity().Property(c => c.Breed).HasColumnName("Breed"); + + VerifyError( + RelationalStrings.DuplicateColumnNameOrderMismatch( + nameof(Cat), nameof(Cat.Breed), nameof(Dog), nameof(Dog.Breed), nameof(Cat.Breed), nameof(Animal), 0, null), + modelBuilder); + } + [ConditionalFact] public virtual void Detects_duplicate_column_names_within_hierarchy_with_different_precision() { @@ -2120,6 +2134,21 @@ public virtual void Passes_for_relational_override_without_inheritance() Assert.DoesNotContain(LoggerFactory.Log, l => l.Level == LogLevel.Warning); } + [ConditionalFact] + public virtual void Detects_duplicate_column_orders() + { + var modelBuilder = CreateConventionalModelBuilder(); + modelBuilder.Entity( + x => + { + x.Property(a => a.Id).HasColumnOrder(0); + x.Property(a => a.Name).HasColumnOrder(0); + }); + + var definition = RelationalResources.LogDuplicateColumnOrders(new TestLogger()); + VerifyWarning(definition.GenerateMessage("Animal", "'Id', 'Name'"), modelBuilder, LogLevel.Error); + } + protected override void SetBaseType(IMutableEntityType entityType, IMutableEntityType baseEntityType) { base.SetBaseType(entityType, baseEntityType); diff --git a/test/EFCore.Relational.Tests/Metadata/RelationalPropertyAttributeConventionTest.cs b/test/EFCore.Relational.Tests/Metadata/RelationalPropertyAttributeConventionTest.cs index 30e9f0775b8..1152e4c2777 100644 --- a/test/EFCore.Relational.Tests/Metadata/RelationalPropertyAttributeConventionTest.cs +++ b/test/EFCore.Relational.Tests/Metadata/RelationalPropertyAttributeConventionTest.cs @@ -25,6 +25,7 @@ public void ColumnAttribute_sets_column_name_and_type_with_conventional_builder( Assert.Equal("Post Name", entityBuilder.Property(e => e.Name).Metadata.GetColumnBaseName()); Assert.Equal("DECIMAL", entityBuilder.Property(e => e.Name).Metadata.GetColumnType()); + Assert.Equal(1, entityBuilder.Property(e => e.Name).Metadata.GetColumnOrder()); } [ConditionalFact] @@ -46,6 +47,7 @@ public void ColumnAttribute_on_field_sets_column_name_and_type_with_conventional Assert.Equal("Post Name", entityBuilder.Property(nameof(F.Name)).Metadata.GetColumnBaseName()); Assert.Equal("DECIMAL", entityBuilder.Property(nameof(F.Name)).Metadata.GetColumnType()); + Assert.Equal(1, entityBuilder.Property(nameof(F.Name)).Metadata.GetColumnOrder()); } [ConditionalFact] @@ -67,12 +69,14 @@ public void ColumnAttribute_overrides_configuration_from_convention_source() propertyBuilder.HasAnnotation(RelationalAnnotationNames.ColumnName, "ConventionalName", ConfigurationSource.Convention); propertyBuilder.HasAnnotation(RelationalAnnotationNames.ColumnType, "BYTE", ConfigurationSource.Convention); + propertyBuilder.HasAnnotation(RelationalAnnotationNames.ColumnOrder, 2, ConfigurationSource.Convention); propertyBuilder.HasAnnotation(RelationalAnnotationNames.Comment, "ConventionalName", ConfigurationSource.Convention); RunConvention(propertyBuilder); Assert.Equal("Post Name", propertyBuilder.Metadata.GetColumnBaseName()); Assert.Equal("DECIMAL", propertyBuilder.Metadata.GetColumnType()); + Assert.Equal(1, propertyBuilder.Metadata.GetColumnOrder()); Assert.Equal("Test column comment", propertyBuilder.Metadata.GetComment()); } @@ -99,12 +103,14 @@ public void ColumnAttribute_does_not_override_configuration_from_explicit_source propertyBuilder.HasAnnotation(RelationalAnnotationNames.ColumnName, "ExplicitName", ConfigurationSource.Explicit); propertyBuilder.HasAnnotation(RelationalAnnotationNames.ColumnType, "BYTE", ConfigurationSource.Explicit); + propertyBuilder.HasAnnotation(RelationalAnnotationNames.ColumnOrder, 2, ConfigurationSource.Explicit); propertyBuilder.HasAnnotation(RelationalAnnotationNames.Comment, "ExplicitComment", ConfigurationSource.Explicit); RunConvention(propertyBuilder); Assert.Equal("ExplicitName", propertyBuilder.Metadata.GetColumnBaseName()); Assert.Equal("BYTE", propertyBuilder.Metadata.GetColumnType()); + Assert.Equal(2, propertyBuilder.Metadata.GetColumnOrder()); Assert.Equal("ExplicitComment", propertyBuilder.Metadata.GetComment()); } diff --git a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs index 45aec7aaa3b..d96a079aad8 100644 --- a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs +++ b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs @@ -736,6 +736,34 @@ public void Create_table_columns_handles_self_referencing_one_to_one() }); } + [ConditionalFact] + public void Create_table_columns_use_explicit_order() + { + Execute( + _ => { }, + modelBuilder => modelBuilder.Entity( + b => + { + b.Property(e => e.C).HasColumnOrder(3); + b.Property(e => e.B).HasColumnOrder(1); + b.Property(e => e.A).HasColumnOrder(2); + }), + operations => + { + var operation = Assert.IsType(Assert.Single(operations)); + Assert.Collection( + operation.Columns, + x => + { + Assert.Equal("B", x.Name); + Assert.Null(operation.FindAnnotation(RelationalAnnotationNames.ColumnOrder)); + }, + x => Assert.Equal("A", x.Name), + x => Assert.Equal("C", x.Name), + x => Assert.Equal("Id", x.Name)); + }); + } + [ConditionalFact] public void Create_FK_to_excluded_principal() { @@ -1566,6 +1594,31 @@ public void Add_column_with_seed_data() })); } + [ConditionalFact] + public void Add_column_with_order() + { + Execute( + source => source.Entity("Peacock").Property("Id"), + target => target.Entity( + "Peacock", + x => + { + x.Property("Id"); + x.Property("Name") + .HasColumnOrder(1); + }), + operations => + { + Assert.Equal(1, operations.Count); + + var operation = Assert.IsType(operations[0]); + Assert.Equal("Peacock", operation.Table); + Assert.Equal("Name", operation.Name); + Assert.Equal(typeof(string), operation.ClrType); + Assert.Equal(1, operation[RelationalAnnotationNames.ColumnOrder]); + }); + } + [ConditionalFact] public void Add_seed_data_with_non_writable_column_insert_operations_with_batching() { @@ -2665,6 +2718,71 @@ public void Alter_column_comment() }); } + [ConditionalFact] + public void Alter_column_order() + { + Execute( + source => source.Entity( + "Pangolin", + x => + { + x.Property("Id"); + x.Property("Name") + .HasColumnOrder(1); + }), + target => target.Entity( + "Pangolin", + x => + { + x.Property("Id"); + x.Property("Name") + .HasColumnOrder(2); + }), + operations => + { + Assert.Equal(1, operations.Count); + + var operation = Assert.IsType(operations[0]); + Assert.Equal("Pangolin", operation.Table); + Assert.Equal("Name", operation.Name); + Assert.Equal(2, operation[RelationalAnnotationNames.ColumnOrder]); + Assert.Equal(1, operation.OldColumn[RelationalAnnotationNames.ColumnOrder]); + }); + } + + [ConditionalFact] + public void Alter_column_but_not_order() + { + Execute( + source => source.Entity( + "Crane", + x => + { + x.Property("Id"); + x.Property("Name") + .HasColumnOrder(1); + }), + target => target.Entity( + "Crane", + x => + { + x.Property("Id"); + x.Property("Name") + .HasColumnOrder(1) + .IsUnicode(false); + }), + operations => + { + Assert.Equal(1, operations.Count); + + var operation = Assert.IsType(operations[0]); + Assert.Equal("Crane", operation.Table); + Assert.Equal("Name", operation.Name); + Assert.Null(operation.FindAnnotation(RelationalAnnotationNames.ColumnOrder)); + Assert.Null(operation.OldColumn.FindAnnotation(RelationalAnnotationNames.ColumnOrder)); + }); + } + [ConditionalFact] public void Add_unique_constraint() { diff --git a/test/EFCore.Relational.Tests/RelationalEventIdTest.cs b/test/EFCore.Relational.Tests/RelationalEventIdTest.cs index 5cfdbcd2531..12cd97a2969 100644 --- a/test/EFCore.Relational.Tests/RelationalEventIdTest.cs +++ b/test/EFCore.Relational.Tests/RelationalEventIdTest.cs @@ -17,6 +17,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; @@ -46,11 +47,13 @@ public void Every_eventId_has_a_logger_method_and_logs_when_level_enabled() var index = new Index(new List { property }, "IndexName", entityType, ConfigurationSource.Convention); var contextServices = RelationalTestHelpers.Instance.CreateContextServices(model.FinalizeModel()); var updateEntry = new InternalEntityEntry(contextServices.GetRequiredService(), entityType, new object()); + var columnOperation = new AddColumnOperation { Name = "Column1", Table = "Table1", ClrType = typeof(int) }; var fakeFactories = new Dictionary> { { typeof(string), () => "Fake" }, { typeof(IList), () => new List { "Fake1", "Fake2" } }, + { typeof(IReadOnlyList), () => new List { "Fake1", "Fake2" } }, { typeof(IEnumerable), () => new List { @@ -81,7 +84,8 @@ public void Every_eventId_has_a_logger_method_and_logs_when_level_enabled() { typeof(ValueConverter), () => new BoolToZeroOneConverter() }, { typeof(DbContext), () => new FakeDbContext() }, { typeof(SqlExpression), () => new FakeSqlExpression() }, - { typeof(IUpdateEntry), () => updateEntry} + { typeof(IUpdateEntry), () => updateEntry }, + { typeof(ColumnOperation), () => columnOperation } }; TestEventLogging( diff --git a/test/EFCore.Sqlite.FunctionalTests/Migrations/SqliteMigrationsSqlGeneratorTest.cs b/test/EFCore.Sqlite.FunctionalTests/Migrations/SqliteMigrationsSqlGeneratorTest.cs index 03097b2f08b..2aaa778ef3e 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Migrations/SqliteMigrationsSqlGeneratorTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Migrations/SqliteMigrationsSqlGeneratorTest.cs @@ -1027,6 +1027,44 @@ public virtual void RenameTable_preserves_pending_rebuilds() ALTER TABLE ""ef_temp_Blog"" RENAME TO ""Blog""; GO +PRAGMA foreign_keys = 1; +"); + } + + [ConditionalFact] + public virtual void Rebuild_preserves_column_order() + { + Generate( + modelBuilder => modelBuilder.Entity( + "Ordinal", + e => + { + e.Property("B").HasColumnOrder(0); + e.Property("A").HasColumnOrder(1); + }), + migrationBuilder => migrationBuilder.DropColumn(name: "C", table: "Ordinal")); + + AssertSql( + @"CREATE TABLE ""ef_temp_Ordinal"" ( + ""B"" TEXT NULL, + ""A"" TEXT NULL +); +GO + +INSERT INTO ""ef_temp_Ordinal"" (""A"", ""B"") +SELECT ""A"", ""B"" +FROM ""Ordinal""; +GO + +PRAGMA foreign_keys = 0; +GO + +DROP TABLE ""Ordinal""; +GO + +ALTER TABLE ""ef_temp_Ordinal"" RENAME TO ""Ordinal""; +GO + PRAGMA foreign_keys = 1; "); } From 0720568217082b6eac1dcfe2aa37b9040ff15b3b Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Mon, 13 Sep 2021 10:25:29 -0700 Subject: [PATCH 099/346] Add a way for providers to filter out non-identity conditions. Fixes #23941 --- .../Update/UpdateSqlGenerator.cs | 24 +++++++++++++++---- .../Internal/SqlServerUpdateSqlGenerator.cs | 6 ++--- src/Shared/StringBuilderExtensions.cs | 22 ++++++++--------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/EFCore.Relational/Update/UpdateSqlGenerator.cs b/src/EFCore.Relational/Update/UpdateSqlGenerator.cs index 3496434b37c..ba53a3af12a 100644 --- a/src/EFCore.Relational/Update/UpdateSqlGenerator.cs +++ b/src/EFCore.Relational/Update/UpdateSqlGenerator.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; using Microsoft.Extensions.DependencyInjection; @@ -499,19 +500,32 @@ protected virtual void AppendWhereAffectedClause( { if (v.IsKey) { - if (v.IsRead) - { - AppendIdentityWhereCondition(sb, v); - } - else + if (!v.IsRead) { AppendWhereCondition(sb, v, v.UseOriginalValueParameter); + return true; } } + + if (IsIdentityOperation(v)) + { + AppendIdentityWhereCondition(sb, v); + return true; + } + + return false; }, " AND "); } } + /// + /// Returns a value indicating whether the given modification represents an auto-incrementing column. + /// + /// The column modification. + /// if the given modification represents an auto-incrementing column. + protected virtual bool IsIdentityOperation(IColumnModification modification) + => modification.IsKey && modification.IsRead; + /// /// Appends a WHERE condition checking rows affected. /// diff --git a/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs b/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs index 5bb527ad384..5f24d6e050b 100644 --- a/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs +++ b/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs @@ -295,10 +295,10 @@ private void AppendMergeCommandHeader( .Append('(') .AppendJoin( writeOperations, - toInsertTableAlias, - SqlGenerationHelper, - (sb, o, alias, helper) => + (toInsertTableAlias, SqlGenerationHelper), + static (sb, o, state) => { + var (alias, helper) = state; sb.Append(alias).Append('.'); helper.DelimitIdentifier(sb, o.ColumnName); }) diff --git a/src/Shared/StringBuilderExtensions.cs b/src/Shared/StringBuilderExtensions.cs index 781c193828a..eda4b05802e 100644 --- a/src/Shared/StringBuilderExtensions.cs +++ b/src/Shared/StringBuilderExtensions.cs @@ -45,20 +45,21 @@ public static StringBuilder AppendJoin( return stringBuilder; } - public static StringBuilder AppendJoin( + public static StringBuilder AppendJoin( this StringBuilder stringBuilder, IEnumerable values, - TParam param, - Action joinAction, + Func joinFunc, string separator = ", ") { var appended = false; foreach (var value in values) { - joinAction(stringBuilder, value, param); - stringBuilder.Append(separator); - appended = true; + if (joinFunc(stringBuilder, value)) + { + stringBuilder.Append(separator); + appended = true; + } } if (appended) @@ -69,19 +70,18 @@ public static StringBuilder AppendJoin( return stringBuilder; } - public static StringBuilder AppendJoin( + public static StringBuilder AppendJoin( this StringBuilder stringBuilder, IEnumerable values, - TParam1 param1, - TParam2 param2, - Action joinAction, + TParam param, + Action joinAction, string separator = ", ") { var appended = false; foreach (var value in values) { - joinAction(stringBuilder, value, param1, param2); + joinAction(stringBuilder, value, param); stringBuilder.Append(separator); appended = true; } From 753195e5b9012f2903b5f955b464c80fc964e90e Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Tue, 14 Sep 2021 08:58:05 +0100 Subject: [PATCH 100/346] Finish linking to conceptual docs (#25983) Fixes #17508 --- .../DesignTimeServiceCollectionExtensions.cs | 9 + .../Design/ILanguageBasedService.cs | 3 + src/EFCore.Design/Design/IPluralizer.cs | 3 + .../CSharpMigrationOperationGenerator.cs | 4 + .../Design/CSharpMigrationsGenerator.cs | 4 + .../Design/CSharpSnapshotGenerator.cs | 4 + .../ICSharpMigrationOperationGenerator.cs | 4 + .../Design/ICSharpSnapshotGenerator.cs | 4 + .../Design/IMigrationsCodeGenerator.cs | 4 + .../IMigrationsCodeGeneratorSelector.cs | 4 + .../Design/IMigrationsScaffolder.cs | 4 + .../Migrations/Design/MigrationsBundle.cs | 3 + .../Design/MigrationsCodeGenerator.cs | 4 + .../Migrations/Design/MigrationsScaffolder.cs | 4 + .../ICompiledModelCodeGenerator.cs | 4 + .../ICompiledModelCodeGeneratorSelector.cs | 4 + .../Scaffolding/ICompiledModelScaffolder.cs | 4 + .../Scaffolding/IModelCodeGenerator.cs | 3 + .../IModelCodeGeneratorSelector.cs | 3 + .../Scaffolding/IReverseEngineerScaffolder.cs | 4 + .../Scaffolding/IScaffoldingModelFactory.cs | 4 + .../Scaffolding/ModelCodeGenerator.cs | 3 + src/EFCore.Proxies/ProxiesExtensions.cs | 12 + .../Design/AnnotationCodeGenerator.cs | 4 + ...rameworkRelationalDesignServicesBuilder.cs | 4 + .../Design/IAnnotationCodeGenerator.cs | 4 + .../Diagnostics/BatchEventData.cs | 3 + .../Diagnostics/CommandCorrelatedEventData.cs | 3 + .../Diagnostics/CommandEndEventData.cs | 3 + .../Diagnostics/CommandErrorEventData.cs | 3 + .../Diagnostics/CommandEventData.cs | 3 + .../Diagnostics/CommandExecutedEventData.cs | 3 + .../Diagnostics/CommandSource.cs | 3 + .../Diagnostics/ConnectionEndEventData.cs | 3 + .../Diagnostics/ConnectionErrorEventData.cs | 3 + .../Diagnostics/ConnectionEventData.cs | 3 + .../DataReaderDisposingEventData.cs | 3 + .../Diagnostics/DbCommandInterceptor.cs | 3 + .../Diagnostics/DbConnectionInterceptor.cs | 3 + .../Diagnostics/DbTransactionInterceptor.cs | 3 + .../Diagnostics/EntityTypeSchemaEventData.cs | 3 + .../Diagnostics/IDbCommandInterceptor.cs | 3 + .../Diagnostics/IDbConnectionInterceptor.cs | 3 + .../Diagnostics/IDbTransactionInterceptor.cs | 3 + .../IRelationalCommandDiagnosticsLogger.cs | 4 + .../IRelationalConnectionDiagnosticsLogger.cs | 4 + .../Diagnostics/IndexEventData.cs | 3 + .../IndexWithPropertiesEventData.cs | 3 + .../Diagnostics/IndexWithPropertyEventData.cs | 3 + .../Diagnostics/MigrationAssemblyEventData.cs | 3 + .../Diagnostics/MigrationEventData.cs | 3 + .../MigrationScriptingEventData.cs | 3 + .../Diagnostics/MigrationTypeEventData.cs | 3 + .../MigratorConnectionEventData.cs | 3 + .../Diagnostics/MigratorEventData.cs | 3 + .../Diagnostics/MinBatchSizeEventData.cs | 3 + .../Diagnostics/RelationalEventId.cs | 3 + .../Diagnostics/RelationalLoggerExtensions.cs | 4 + .../RelationalLoggingDefinitions.cs | 4 + .../Diagnostics/SequenceEventData.cs | 3 + .../Diagnostics/TransactionEndEventData.cs | 3 + .../TransactionEnlistedEventData.cs | 3 + .../Diagnostics/TransactionErrorEventData.cs | 3 + .../Diagnostics/TransactionEventData.cs | 3 + .../TransactionStartingEventData.cs | 3 + .../Diagnostics/TwoSqlExpressionsEventData.cs | 3 + .../RelationalDatabaseFacadeExtensions.cs | 103 +++++++ .../RelationalDbFunctionsExtensions.cs | 6 +- .../RelationalEntityTypeBuilderExtensions.cs | 253 +++++++++++++++++- .../RelationalEntityTypeExtensions.cs | 3 + .../RelationalForeignKeyBuilderExtensions.cs | 27 ++ .../RelationalForeignKeyExtensions.cs | 5 +- .../RelationalIndexBuilderExtensions.cs | 39 +++ .../Extensions/RelationalIndexExtensions.cs | 3 + .../RelationalKeyBuilderExtensions.cs | 15 ++ .../Extensions/RelationalKeyExtensions.cs | 3 + .../RelationalModelBuilderExtensions.cs | 72 +++++ .../Extensions/RelationalModelExtensions.cs | 3 + ...ropertiesConfigurationBuilderExtensions.cs | 18 ++ .../RelationalPropertyBuilderExtensions.cs | 135 ++++++++++ .../RelationalPropertyExtensions.cs | 3 + .../RelationalQueryableExtensions.cs | 17 ++ ...peMappingConfigurationBuilderExtensions.cs | 15 ++ ...ntityFrameworkRelationalServicesBuilder.cs | 8 + ...alDbContextOptionsBuilderInfrastructure.cs | 4 + .../Infrastructure/ModelSnapshot.cs | 3 + .../RelationalDbContextOptionsBuilder.cs | 28 ++ .../RelationalModelCustomizer.cs | 4 + .../RelationalModelExtensions.cs | 4 + .../RelationalModelRuntimeInitializer.cs | 4 + .../RelationalModelValidator.cs | 4 + .../RelationalOptionsExtension.cs | 4 + .../Builders/CheckConstraintBuilder.cs | 6 + .../Metadata/Builders/DbFunctionBuilder.cs | 21 ++ .../Builders/DbFunctionBuilderBase.cs | 15 ++ .../Builders/DbFunctionParameterBuilder.cs | 6 + .../IConventionCheckConstraintBuilder.cs | 4 + .../Builders/IConventionDbFunctionBuilder.cs | 3 + .../IConventionDbFunctionParameterBuilder.cs | 3 + .../Builders/IConventionSequenceBuilder.cs | 3 + .../Metadata/Builders/SequenceBuilder.cs | 18 ++ .../Metadata/Builders/TableBuilder.cs | 3 + .../Metadata/Builders/TableBuilder`.cs | 3 + .../Builders/TableValuedFunctionBuilder.cs | 6 + .../Conventions/CheckConstraintConvention.cs | 3 + .../DbFunctionTypeMappingConvention.cs | 4 + .../EntityTypeHierarchyMappingConvention.cs | 4 + .../RelationalConventionSetBuilder.cs | 3 + .../RelationalColumnAttributeConvention.cs | 3 + ...ationalColumnCommentAttributeConvention.cs | 3 + ...RelationalDbFunctionAttributeConvention.cs | 4 + ...RelationalMaxIdentifierLengthConvention.cs | 3 + .../Conventions/RelationalModelConvention.cs | 3 + .../RelationalRuntimeModelConvention.cs | 3 + .../RelationalTableAttributeConvention.cs | 3 + ...lationalTableCommentAttributeConvention.cs | 3 + .../RelationalValueGenerationConvention.cs | 4 + .../SequenceUniquificationConvention.cs | 4 + .../Conventions/SharedTableConvention.cs | 3 + .../Conventions/StoreGenerationConvention.cs | 4 + .../TableNameFromDbSetConvention.cs | 3 + .../TableSharingConcurrencyTokenConvention.cs | 3 + .../TableValuedDbFunctionConvention.cs | 4 + .../Metadata/ICheckConstraint.cs | 3 + src/EFCore.Relational/Metadata/IColumn.cs | 3 + src/EFCore.Relational/Metadata/IColumnBase.cs | 3 + .../Metadata/IColumnMapping.cs | 3 + .../Metadata/IColumnMappingBase.cs | 3 + .../Metadata/IConventionCheckConstraint.cs | 3 + .../Metadata/IConventionDbFunction.cs | 3 + .../IConventionDbFunctionParameter.cs | 3 + .../Metadata/IConventionSequence.cs | 3 + src/EFCore.Relational/Metadata/IDbFunction.cs | 3 + .../Metadata/IDbFunctionParameter.cs | 3 + .../Metadata/IForeignKeyConstraint.cs | 3 + .../Metadata/IFunctionColumn.cs | 3 + .../Metadata/IFunctionColumnMapping.cs | 3 + .../Metadata/IFunctionMapping.cs | 3 + .../Metadata/IMutableCheckConstraint.cs | 3 + .../Metadata/IMutableDbFunction.cs | 3 + .../Metadata/IMutableDbFunctionParameter.cs | 3 + .../Metadata/IMutableSequence.cs | 3 + .../Metadata/IPrimaryKeyConstraint.cs | 3 + .../Metadata/IReadOnlyCheckConstraint.cs | 3 + .../Metadata/IReadOnlyDbFunction.cs | 3 + .../Metadata/IReadOnlyDbFunctionParameter.cs | 3 + .../Metadata/IReadOnlySequence.cs | 3 + .../Metadata/IRelationalAnnotationProvider.cs | 4 + .../Metadata/IRelationalModel.cs | 3 + src/EFCore.Relational/Metadata/ISequence.cs | 3 + src/EFCore.Relational/Metadata/ISqlQuery.cs | 4 + .../Metadata/ISqlQueryColumn.cs | 4 + .../Metadata/ISqlQueryColumnMapping.cs | 4 + .../Metadata/ISqlQueryMapping.cs | 4 + .../Metadata/IStoreFunction.cs | 3 + .../Metadata/IStoreFunctionParameter.cs | 3 + src/EFCore.Relational/Metadata/ITable.cs | 4 +- src/EFCore.Relational/Metadata/ITableBase.cs | 3 + src/EFCore.Relational/Metadata/ITableIndex.cs | 3 + .../Metadata/ITableMapping.cs | 3 + .../Metadata/ITableMappingBase.cs | 3 + .../Metadata/IUniqueConstraint.cs | 3 + src/EFCore.Relational/Metadata/IView.cs | 3 + src/EFCore.Relational/Metadata/IViewColumn.cs | 3 + .../Metadata/IViewColumnMapping.cs | 3 + .../Metadata/IViewMapping.cs | 3 + .../Metadata/RelationalAnnotationNames.cs | 3 + .../Metadata/RelationalAnnotationProvider.cs | 3 + .../Metadata/RuntimeDbFunction.cs | 3 + .../Metadata/RuntimeDbFunctionParameter.cs | 3 + .../RuntimeRelationalPropertyOverrides.cs | 3 + .../Metadata/RuntimeSequence.cs | 3 + .../Metadata/SqlQueryExtensions.cs | 4 + .../Metadata/StoreObjectIdentifier.cs | 3 + .../Metadata/StoreObjectType.cs | 3 + .../Migrations/HistoryRepository.cs | 3 + .../Migrations/HistoryRow.cs | 3 + .../Migrations/IHistoryRepository.cs | 3 + .../Migrations/IMigrationCommandExecutor.cs | 3 + .../IMigrationsAnnotationProvider.cs | 3 + .../Migrations/IMigrationsAssembly.cs | 3 + .../Migrations/IMigrationsIdGenerator.cs | 3 + .../Migrations/IMigrationsModelDiffer.cs | 3 + .../Migrations/IMigrationsSqlGenerator.cs | 3 + src/EFCore.Relational/Migrations/IMigrator.cs | 12 + src/EFCore.Relational/Migrations/Migration.cs | 24 ++ .../Migrations/MigrationAttribute.cs | 3 + .../Migrations/MigrationBuilder.cs | 183 +++++++++++++ .../Migrations/MigrationCommand.cs | 3 + .../Migrations/MigrationCommandListBuilder.cs | 3 + .../MigrationsAnnotationProvider.cs | 3 + .../MigrationsAssemblyExtensions.cs | 6 + .../MigrationsSqlGenerationOptions.cs | 3 + .../Migrations/MigrationsSqlGenerator.cs | 3 + .../Operations/AddCheckConstraintOperation.cs | 3 + .../Operations/AddColumnOperation.cs | 3 + .../Operations/AddForeignKeyOperation.cs | 3 + .../Operations/AddPrimaryKeyOperation.cs | 3 + .../AddUniqueConstraintOperation.cs | 3 + .../Operations/AlterColumnOperation.cs | 3 + .../Operations/AlterDatabaseOperation.cs | 3 + .../Operations/AlterSequenceOperation.cs | 3 + .../Operations/AlterTableOperation.cs | 3 + .../Migrations/Operations/ColumnOperation.cs | 3 + .../Operations/CreateIndexOperation.cs | 3 + .../Operations/CreateSequenceOperation.cs | 3 + .../Operations/CreateTableOperation.cs | 3 + .../Operations/DatabaseOperation.cs | 3 + .../Operations/DeleteDataOperation.cs | 3 + .../DropCheckConstraintOperation.cs | 3 + .../Operations/DropColumnOperation.cs | 3 + .../Operations/DropForeignKeyOperation.cs | 3 + .../Operations/DropIndexOperation.cs | 3 + .../Operations/DropPrimaryKeyOperation.cs | 3 + .../Operations/DropSchemaOperation.cs | 3 + .../Operations/DropSequenceOperation.cs | 3 + .../Operations/DropTableOperation.cs | 3 + .../DropUniqueConstraintOperation.cs | 3 + .../Operations/EnsureSchemaOperation.cs | 3 + .../Operations/IAlterMigrationOperation.cs | 3 + .../Operations/ITableMigrationOperation.cs | 3 + .../Operations/InsertDataOperation.cs | 3 + .../Operations/MigrationOperation.cs | 3 + .../Operations/RenameColumnOperation.cs | 3 + .../Operations/RenameIndexOperation.cs | 3 + .../Operations/RenameSequenceOperation.cs | 3 + .../Operations/RenameTableOperation.cs | 3 + .../Operations/RestartSequenceOperation.cs | 3 + .../Operations/SequenceOperation.cs | 3 + .../Migrations/Operations/SqlOperation.cs | 3 + .../Migrations/Operations/TableOperation.cs | 3 + .../Operations/UpdateDataOperation.cs | 3 + .../Migrations/ReferentialAction.cs | 3 + .../QuerySplittingBehavior.cs | 3 + .../Scaffolding/DatabaseModelFactory.cs | 4 + .../DatabaseModelFactoryOptions.cs | 4 + .../Scaffolding/IDatabaseModelFactory.cs | 4 + .../IProviderCodeGeneratorPlugin.cs | 4 + .../IProviderConfigurationCodeGenerator.cs | 4 + .../Scaffolding/Metadata/DatabaseColumn.cs | 4 + .../Metadata/DatabaseForeignKey.cs | 4 + .../Scaffolding/Metadata/DatabaseIndex.cs | 4 + .../Scaffolding/Metadata/DatabaseModel.cs | 4 + .../Metadata/DatabasePrimaryKey.cs | 4 + .../Scaffolding/Metadata/DatabaseSequence.cs | 4 + .../Scaffolding/Metadata/DatabaseTable.cs | 4 + .../Metadata/DatabaseUniqueConstraint.cs | 4 + .../Scaffolding/Metadata/DatabaseView.cs | 4 + .../Scaffolding/ProviderCodeGenerator.cs | 4 + .../ProviderCodeGeneratorPlugin.cs | 4 + .../Storage/BoolTypeMapping.cs | 4 + .../Storage/ByteArrayTypeMapping.cs | 4 + .../Storage/ByteTypeMapping.cs | 4 + .../Storage/CharTypeMapping.cs | 4 + .../Storage/DateOnlyTypeMapping.cs | 4 + .../Storage/DateTimeOffsetTypeMapping.cs | 4 + .../Storage/DateTimeTypeMapping.cs | 4 + .../Storage/DbContextTransactionExtensions.cs | 6 + .../Storage/DecimalTypeMapping.cs | 4 + .../Storage/DoubleTypeMapping.cs | 4 + .../Storage/FloatTypeMapping.cs | 4 + .../Storage/GuidTypeMapping.cs | 4 + .../Storage/IParameterNameGeneratorFactory.cs | 4 + .../Storage/IRawSqlCommandBuilder.cs | 4 + .../Storage/IRelationalCommand.cs | 4 + .../Storage/IRelationalCommandBuilder.cs | 4 + .../IRelationalCommandBuilderFactory.cs | 4 + .../Storage/IRelationalCommandTemplate.cs | 4 + .../Storage/IRelationalConnection.cs | 4 + .../Storage/IRelationalDatabaseCreator.cs | 4 + .../IRelationalDatabaseFacadeDependencies.cs | 4 + .../Storage/IRelationalParameter.cs | 4 + .../Storage/IRelationalTransactionFactory.cs | 4 + .../Storage/IRelationalTransactionManager.cs | 4 + .../Storage/IRelationalTypeMappingSource.cs | 4 + .../IRelationalTypeMappingSourcePlugin.cs | 4 + .../Storage/IRelationalValueBufferFactory.cs | 4 + .../IRelationalValueBufferFactoryFactory.cs | 4 + .../Storage/ISqlGenerationHelper.cs | 4 + .../Storage/IntTypeMapping.cs | 4 + .../Storage/LongTypeMapping.cs | 4 + .../Storage/ParameterNameGenerator.cs | 4 + .../Storage/ParameterNameGeneratorFactory.cs | 4 + .../Storage/RawSqlCommand.cs | 4 + src/EFCore.Relational/Storage/ReaderColumn.cs | 4 + .../Storage/ReaderColumn`.cs | 4 + .../Storage/RelationalCommand.cs | 4 + .../Storage/RelationalCommandBuilder.cs | 4 + .../RelationalCommandBuilderExtensions.cs | 4 + .../RelationalCommandBuilderFactory.cs | 4 + .../RelationalCommandParameterObject.cs | 4 + .../Storage/RelationalConnection.cs | 4 + .../Storage/RelationalDataReader.cs | 4 + .../Storage/RelationalDatabase.cs | 4 + .../Storage/RelationalDatabaseCreator.cs | 4 + .../RelationalExecutionStrategyExtensions.cs | 40 +++ .../RelationalExecutionStrategyFactory.cs | 4 + .../Storage/RelationalGeometryTypeMapping.cs | 4 + .../Storage/RelationalSqlGenerationHelper.cs | 4 + .../Storage/RelationalTransaction.cs | 3 + .../Storage/RelationalTransactionFactory.cs | 4 + .../Storage/RelationalTypeMapping.cs | 4 + .../Storage/RelationalTypeMappingInfo.cs | 4 + .../Storage/RelationalTypeMappingSource.cs | 4 + .../RelationalTypeMappingSourceExtensions.cs | 4 + .../Storage/SByteTypeMapping.cs | 4 + .../Storage/ShortTypeMapping.cs | 4 + .../Storage/StoreTypePostfix.cs | 4 + .../Storage/StringTypeMapping.cs | 4 + .../Storage/TimeOnlyTypeMapping.cs | 4 + .../Storage/TimeSpanTypeMapping.cs | 4 + .../Storage/TypeMaterializationInfo.cs | 4 + ...ypedRelationalValueBufferFactoryFactory.cs | 4 + .../Storage/UIntTypeMapping.cs | 4 + .../Storage/ULongTypeMapping.cs | 4 + .../Storage/UShortTypeMapping.cs | 4 + .../RelationalConverterMappingHints.cs | 3 + .../AffectedCountModificationCommandBatch.cs | 4 + .../Update/ColumnModification.cs | 4 + .../Update/ColumnModificationParameters.cs | 4 + .../Update/IBatchExecutor.cs | 4 + .../Update/IColumnModification.cs | 4 + .../Update/ICommandBatchPreparer.cs | 4 + .../Update/IModificationCommand.cs | 4 + .../IModificationCommandBatchFactory.cs | 4 + .../Update/IModificationCommandFactory.cs | 4 + .../Update/IReadOnlyModificationCommand.cs | 4 + .../Update/IUpdateSqlGenerator.cs | 4 + .../Update/ModificationCommand.cs | 4 + .../Update/ModificationCommandBatch.cs | 4 + .../Update/ModificationCommandParameters.cs | 4 + .../Update/ReaderModificationCommandBatch.cs | 4 + .../Update/ResultSetMapping.cs | 4 + .../SingularModificationCommandBatch.cs | 4 + .../Update/UpdateSqlGenerator.cs | 4 + .../RelationalValueGeneratorSelector.cs | 4 + src/EFCore/DbContext.cs | 2 +- src/EFCore/DbUpdateException.cs | 2 +- 338 files changed, 2167 insertions(+), 7 deletions(-) diff --git a/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs b/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs index 6da95d49211..0df4882a1d7 100644 --- a/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs +++ b/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs @@ -22,11 +22,17 @@ namespace Microsoft.EntityFrameworkCore.Design /// Extension methods for adding Entity Framework Core design-time services to an /// . /// + /// + /// See EF Core design-time services for more information. + /// public static class DesignTimeServiceCollectionExtensions { /// /// Adds the Entity Framework Core design-time services. /// + /// + /// See EF Core design-time services for more information. + /// /// The the services will be added to. /// Used to report design-time messages. /// An accessor to the application service provider. @@ -80,6 +86,9 @@ public static IServiceCollection AddEntityFrameworkDesignTimeServices( /// /// Adds services from the which are used at design time. /// + /// + /// See EF Core design-time services for more information. + /// /// The the services will be added to. /// The the services will be added from. /// The . This enables chaining additional method calls. diff --git a/src/EFCore.Design/Design/ILanguageBasedService.cs b/src/EFCore.Design/Design/ILanguageBasedService.cs index a95093bb980..50a052b15e8 100644 --- a/src/EFCore.Design/Design/ILanguageBasedService.cs +++ b/src/EFCore.Design/Design/ILanguageBasedService.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Design /// /// Represents a service that gets resolved based on the programming language it supports. /// + /// + /// See EF Core design-time services for more information. + /// public interface ILanguageBasedService { /// diff --git a/src/EFCore.Design/Design/IPluralizer.cs b/src/EFCore.Design/Design/IPluralizer.cs index 7fe5e07f2ac..dd4a53c3da9 100644 --- a/src/EFCore.Design/Design/IPluralizer.cs +++ b/src/EFCore.Design/Design/IPluralizer.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Design /// /// Converts identifiers to the plural and singular equivalents. /// + /// + /// See EF Core design-time services for more information. + /// public interface IPluralizer { /// diff --git a/src/EFCore.Design/Migrations/Design/CSharpMigrationOperationGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpMigrationOperationGenerator.cs index c6955ec094e..05d41c8e68e 100644 --- a/src/EFCore.Design/Migrations/Design/CSharpMigrationOperationGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/CSharpMigrationOperationGenerator.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Used to generate C# for creating objects. /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public class CSharpMigrationOperationGenerator : ICSharpMigrationOperationGenerator { /// diff --git a/src/EFCore.Design/Migrations/Design/CSharpMigrationsGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpMigrationsGenerator.cs index 7f9350cbb84..3bc435129f2 100644 --- a/src/EFCore.Design/Migrations/Design/CSharpMigrationsGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/CSharpMigrationsGenerator.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Used to generate C# code for migrations. /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public class CSharpMigrationsGenerator : MigrationsCodeGenerator { /// diff --git a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs index 715e509b506..1a4354ebf7a 100644 --- a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs @@ -19,6 +19,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Used to generate C# code for creating an . /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public class CSharpSnapshotGenerator : ICSharpSnapshotGenerator { private static readonly MethodInfo _hasAnnotationMethodInfo diff --git a/src/EFCore.Design/Migrations/Design/ICSharpMigrationOperationGenerator.cs b/src/EFCore.Design/Migrations/Design/ICSharpMigrationOperationGenerator.cs index b80cc165557..377ccfc8616 100644 --- a/src/EFCore.Design/Migrations/Design/ICSharpMigrationOperationGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/ICSharpMigrationOperationGenerator.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Used to generate C# code for creating objects. /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public interface ICSharpMigrationOperationGenerator { /// diff --git a/src/EFCore.Design/Migrations/Design/ICSharpSnapshotGenerator.cs b/src/EFCore.Design/Migrations/Design/ICSharpSnapshotGenerator.cs index aa9fd2673ce..54f53cd2cbc 100644 --- a/src/EFCore.Design/Migrations/Design/ICSharpSnapshotGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/ICSharpSnapshotGenerator.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Used to generate C# code for creating an . /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public interface ICSharpSnapshotGenerator { /// diff --git a/src/EFCore.Design/Migrations/Design/IMigrationsCodeGenerator.cs b/src/EFCore.Design/Migrations/Design/IMigrationsCodeGenerator.cs index 4938826af00..9891be65000 100644 --- a/src/EFCore.Design/Migrations/Design/IMigrationsCodeGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/IMigrationsCodeGenerator.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Used to generate code for migrations. /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public interface IMigrationsCodeGenerator : ILanguageBasedService { /// diff --git a/src/EFCore.Design/Migrations/Design/IMigrationsCodeGeneratorSelector.cs b/src/EFCore.Design/Migrations/Design/IMigrationsCodeGeneratorSelector.cs index 1d2ce8d233d..75322183472 100644 --- a/src/EFCore.Design/Migrations/Design/IMigrationsCodeGeneratorSelector.cs +++ b/src/EFCore.Design/Migrations/Design/IMigrationsCodeGeneratorSelector.cs @@ -6,6 +6,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Selects an service for a given programming language. /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public interface IMigrationsCodeGeneratorSelector { /// diff --git a/src/EFCore.Design/Migrations/Design/IMigrationsScaffolder.cs b/src/EFCore.Design/Migrations/Design/IMigrationsScaffolder.cs index 87aea4789b1..ed4ab2e226e 100644 --- a/src/EFCore.Design/Migrations/Design/IMigrationsScaffolder.cs +++ b/src/EFCore.Design/Migrations/Design/IMigrationsScaffolder.cs @@ -6,6 +6,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Used to scaffold new migrations. /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public interface IMigrationsScaffolder { /// diff --git a/src/EFCore.Design/Migrations/Design/MigrationsBundle.cs b/src/EFCore.Design/Migrations/Design/MigrationsBundle.cs index aa4edc9e113..5cccd2aeab4 100644 --- a/src/EFCore.Design/Migrations/Design/MigrationsBundle.cs +++ b/src/EFCore.Design/Migrations/Design/MigrationsBundle.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Defines the entry point for Migrations bundles. /// + /// + /// See EF Core migration bundles. + /// public static class MigrationsBundle { private static string? _context; diff --git a/src/EFCore.Design/Migrations/Design/MigrationsCodeGenerator.cs b/src/EFCore.Design/Migrations/Design/MigrationsCodeGenerator.cs index 3e524dc2653..f76c7c34627 100644 --- a/src/EFCore.Design/Migrations/Design/MigrationsCodeGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/MigrationsCodeGenerator.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Used to generate code for migrations. /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public abstract class MigrationsCodeGenerator : IMigrationsCodeGenerator { /// diff --git a/src/EFCore.Design/Migrations/Design/MigrationsScaffolder.cs b/src/EFCore.Design/Migrations/Design/MigrationsScaffolder.cs index 619a94a520c..31530628d17 100644 --- a/src/EFCore.Design/Migrations/Design/MigrationsScaffolder.cs +++ b/src/EFCore.Design/Migrations/Design/MigrationsScaffolder.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Design /// /// Used to scaffold new migrations. /// + /// + /// See Database migrations, and + /// EF Core design-time services for more information. + /// public class MigrationsScaffolder : IMigrationsScaffolder { private readonly Type _contextType; diff --git a/src/EFCore.Design/Scaffolding/ICompiledModelCodeGenerator.cs b/src/EFCore.Design/Scaffolding/ICompiledModelCodeGenerator.cs index 0af1801aebc..51f0e1a088b 100644 --- a/src/EFCore.Design/Scaffolding/ICompiledModelCodeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/ICompiledModelCodeGenerator.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Used to generate code for compiled model metadata. /// + /// + /// See EF Core compiled models, and + /// EF Core design-time services for more information. + /// public interface ICompiledModelCodeGenerator : ILanguageBasedService { /// diff --git a/src/EFCore.Design/Scaffolding/ICompiledModelCodeGeneratorSelector.cs b/src/EFCore.Design/Scaffolding/ICompiledModelCodeGeneratorSelector.cs index 3070c57972c..9b96657ebaf 100644 --- a/src/EFCore.Design/Scaffolding/ICompiledModelCodeGeneratorSelector.cs +++ b/src/EFCore.Design/Scaffolding/ICompiledModelCodeGeneratorSelector.cs @@ -6,6 +6,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Selects an service for given generation options. /// + /// + /// See EF Core compiled models, and + /// EF Core design-time services for more information. + /// public interface ICompiledModelCodeGeneratorSelector { /// diff --git a/src/EFCore.Design/Scaffolding/ICompiledModelScaffolder.cs b/src/EFCore.Design/Scaffolding/ICompiledModelScaffolder.cs index 38db3e1299a..bb4fe08ccc7 100644 --- a/src/EFCore.Design/Scaffolding/ICompiledModelScaffolder.cs +++ b/src/EFCore.Design/Scaffolding/ICompiledModelScaffolder.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Used to scaffold a compiled model from a model. /// + /// + /// See EF Core compiled models, and + /// EF Core design-time services for more information. + /// public interface ICompiledModelScaffolder { /// diff --git a/src/EFCore.Design/Scaffolding/IModelCodeGenerator.cs b/src/EFCore.Design/Scaffolding/IModelCodeGenerator.cs index f85f52dbc42..00b6e60311f 100644 --- a/src/EFCore.Design/Scaffolding/IModelCodeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/IModelCodeGenerator.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Used to generate code for a model. /// + /// + /// See EF Core design-time services for more information. + /// public interface IModelCodeGenerator : ILanguageBasedService { /// diff --git a/src/EFCore.Design/Scaffolding/IModelCodeGeneratorSelector.cs b/src/EFCore.Design/Scaffolding/IModelCodeGeneratorSelector.cs index 403c5b3a55a..4e123649d81 100644 --- a/src/EFCore.Design/Scaffolding/IModelCodeGeneratorSelector.cs +++ b/src/EFCore.Design/Scaffolding/IModelCodeGeneratorSelector.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Selects an service for a given programming language. /// + /// + /// See EF Core design-time services for more information. + /// public interface IModelCodeGeneratorSelector { /// diff --git a/src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs b/src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs index c4fb200f9ae..953c7f363b4 100644 --- a/src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs +++ b/src/EFCore.Design/Scaffolding/IReverseEngineerScaffolder.cs @@ -6,6 +6,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Used to scaffold a model from a database schema. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public interface IReverseEngineerScaffolder { /// diff --git a/src/EFCore.Design/Scaffolding/IScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/IScaffoldingModelFactory.cs index 005f5d6a137..42b8b92dad1 100644 --- a/src/EFCore.Design/Scaffolding/IScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/IScaffoldingModelFactory.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Used to create an from a . /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public interface IScaffoldingModelFactory { /// diff --git a/src/EFCore.Design/Scaffolding/ModelCodeGenerator.cs b/src/EFCore.Design/Scaffolding/ModelCodeGenerator.cs index e02c0ccbd58..ac313834c7b 100644 --- a/src/EFCore.Design/Scaffolding/ModelCodeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/ModelCodeGenerator.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Used to generate code for a model. /// + /// + /// See EF Core design-time services for more information. + /// public abstract class ModelCodeGenerator : IModelCodeGenerator { /// diff --git a/src/EFCore.Proxies/ProxiesExtensions.cs b/src/EFCore.Proxies/ProxiesExtensions.cs index 4b9d6f4be54..d4e5e1d7512 100644 --- a/src/EFCore.Proxies/ProxiesExtensions.cs +++ b/src/EFCore.Proxies/ProxiesExtensions.cs @@ -26,6 +26,9 @@ public static class ProxiesExtensions /// may be needed. /// /// + /// + /// See Notification entities for more information. + /// /// /// The options builder, as passed to /// or exposed AddDbContext. @@ -66,6 +69,9 @@ public static DbContextOptionsBuilder UseChangeTrackingProxies( /// may be needed. /// /// + /// + /// See Notification entities for more information. + /// /// The type. /// /// The options builder, as passed to @@ -98,6 +104,9 @@ public static DbContextOptionsBuilder UseChangeTrackingProxies may be needed. /// /// + /// + /// See Lazy loading for more information. + /// /// /// The options builder, as passed to /// or exposed AddDbContext. @@ -130,6 +139,9 @@ public static DbContextOptionsBuilder UseLazyLoadingProxies( /// may be needed. /// /// + /// + /// See Lazy loading for more information. + /// /// The type. /// /// The options builder, as passed to diff --git a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs index f5dd8e73498..19a656820f0 100644 --- a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs @@ -27,6 +27,10 @@ namespace Microsoft.EntityFrameworkCore.Design /// annotations that they understand. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class AnnotationCodeGenerator : IAnnotationCodeGenerator { private static readonly ISet _ignoredRelationalAnnotations = new HashSet diff --git a/src/EFCore.Relational/Design/EntityFrameworkRelationalDesignServicesBuilder.cs b/src/EFCore.Relational/Design/EntityFrameworkRelationalDesignServicesBuilder.cs index 5d4e8fefd44..940bbe3b1c9 100644 --- a/src/EFCore.Relational/Design/EntityFrameworkRelationalDesignServicesBuilder.cs +++ b/src/EFCore.Relational/Design/EntityFrameworkRelationalDesignServicesBuilder.cs @@ -25,6 +25,10 @@ namespace Microsoft.EntityFrameworkCore.Design /// can handle the new scope, and that it does not cause issue for services that depend on it. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class EntityFrameworkRelationalDesignServicesBuilder : EntityFrameworkDesignServicesBuilder { /// diff --git a/src/EFCore.Relational/Design/IAnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/IAnnotationCodeGenerator.cs index cb336112ba1..105c6c409c5 100644 --- a/src/EFCore.Relational/Design/IAnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/IAnnotationCodeGenerator.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Design /// have code generated (as opposed to being handled by convention) and then to generate /// the code if needed. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IAnnotationCodeGenerator { /// diff --git a/src/EFCore.Relational/Diagnostics/BatchEventData.cs b/src/EFCore.Relational/Diagnostics/BatchEventData.cs index a087acd12b2..cd811817200 100644 --- a/src/EFCore.Relational/Diagnostics/BatchEventData.cs +++ b/src/EFCore.Relational/Diagnostics/BatchEventData.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// batch events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class BatchEventData : EventData { /// diff --git a/src/EFCore.Relational/Diagnostics/CommandCorrelatedEventData.cs b/src/EFCore.Relational/Diagnostics/CommandCorrelatedEventData.cs index 934d04a8f83..62cc5d13483 100644 --- a/src/EFCore.Relational/Diagnostics/CommandCorrelatedEventData.cs +++ b/src/EFCore.Relational/Diagnostics/CommandCorrelatedEventData.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// The event payload for events correlated with a . /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class CommandCorrelatedEventData : DbContextEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/CommandEndEventData.cs b/src/EFCore.Relational/Diagnostics/CommandEndEventData.cs index 2f33d841a5a..9ef45f23434 100644 --- a/src/EFCore.Relational/Diagnostics/CommandEndEventData.cs +++ b/src/EFCore.Relational/Diagnostics/CommandEndEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// command end events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class CommandEndEventData : CommandEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/CommandErrorEventData.cs b/src/EFCore.Relational/Diagnostics/CommandErrorEventData.cs index 9ee75c8c8e3..b4deffd9c1a 100644 --- a/src/EFCore.Relational/Diagnostics/CommandErrorEventData.cs +++ b/src/EFCore.Relational/Diagnostics/CommandErrorEventData.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// The event payload for . /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class CommandErrorEventData : CommandEndEventData, IErrorEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/CommandEventData.cs b/src/EFCore.Relational/Diagnostics/CommandEventData.cs index cc8ff3f8cf5..8e8db3ff9a7 100644 --- a/src/EFCore.Relational/Diagnostics/CommandEventData.cs +++ b/src/EFCore.Relational/Diagnostics/CommandEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// command events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class CommandEventData : CommandCorrelatedEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/CommandExecutedEventData.cs b/src/EFCore.Relational/Diagnostics/CommandExecutedEventData.cs index 2498b4c5875..36cac1ffeb7 100644 --- a/src/EFCore.Relational/Diagnostics/CommandExecutedEventData.cs +++ b/src/EFCore.Relational/Diagnostics/CommandExecutedEventData.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// The event payload for . /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class CommandExecutedEventData : CommandEndEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/CommandSource.cs b/src/EFCore.Relational/Diagnostics/CommandSource.cs index cc56dcc6fb5..9a6909b2a74 100644 --- a/src/EFCore.Relational/Diagnostics/CommandSource.cs +++ b/src/EFCore.Relational/Diagnostics/CommandSource.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// Enum used by , and subclasses to indicate the /// source of the being used to execute the command. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public enum CommandSource { /// diff --git a/src/EFCore.Relational/Diagnostics/ConnectionEndEventData.cs b/src/EFCore.Relational/Diagnostics/ConnectionEndEventData.cs index faf3813e033..a8e4648f2c2 100644 --- a/src/EFCore.Relational/Diagnostics/ConnectionEndEventData.cs +++ b/src/EFCore.Relational/Diagnostics/ConnectionEndEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload class for /// connection ending events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class ConnectionEndEventData : ConnectionEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/ConnectionErrorEventData.cs b/src/EFCore.Relational/Diagnostics/ConnectionErrorEventData.cs index 465c7619bd0..3c0600dceb9 100644 --- a/src/EFCore.Relational/Diagnostics/ConnectionErrorEventData.cs +++ b/src/EFCore.Relational/Diagnostics/ConnectionErrorEventData.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// The event payload for . /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class ConnectionErrorEventData : ConnectionEndEventData, IErrorEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/ConnectionEventData.cs b/src/EFCore.Relational/Diagnostics/ConnectionEventData.cs index 7f42a9fae36..0a2282df649 100644 --- a/src/EFCore.Relational/Diagnostics/ConnectionEventData.cs +++ b/src/EFCore.Relational/Diagnostics/ConnectionEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for /// connection events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class ConnectionEventData : DbContextEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/DataReaderDisposingEventData.cs b/src/EFCore.Relational/Diagnostics/DataReaderDisposingEventData.cs index 15da99855df..9b8807baf51 100644 --- a/src/EFCore.Relational/Diagnostics/DataReaderDisposingEventData.cs +++ b/src/EFCore.Relational/Diagnostics/DataReaderDisposingEventData.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// event payload for . /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class DataReaderDisposingEventData : DbContextEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/DbCommandInterceptor.cs b/src/EFCore.Relational/Diagnostics/DbCommandInterceptor.cs index f485f566b81..e5f71385246 100644 --- a/src/EFCore.Relational/Diagnostics/DbCommandInterceptor.cs +++ b/src/EFCore.Relational/Diagnostics/DbCommandInterceptor.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// of the interface methods. /// /// + /// + /// See EF Core interceptors for more information. + /// public abstract class DbCommandInterceptor : IDbCommandInterceptor { /// diff --git a/src/EFCore.Relational/Diagnostics/DbConnectionInterceptor.cs b/src/EFCore.Relational/Diagnostics/DbConnectionInterceptor.cs index b74169b8d0d..f6bd82fe42e 100644 --- a/src/EFCore.Relational/Diagnostics/DbConnectionInterceptor.cs +++ b/src/EFCore.Relational/Diagnostics/DbConnectionInterceptor.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// of the interface methods. /// /// + /// + /// See EF Core interceptors for more information. + /// public abstract class DbConnectionInterceptor : IDbConnectionInterceptor { /// diff --git a/src/EFCore.Relational/Diagnostics/DbTransactionInterceptor.cs b/src/EFCore.Relational/Diagnostics/DbTransactionInterceptor.cs index 65a3c8968f7..d08ea5958a2 100644 --- a/src/EFCore.Relational/Diagnostics/DbTransactionInterceptor.cs +++ b/src/EFCore.Relational/Diagnostics/DbTransactionInterceptor.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// of the interface methods. /// /// + /// + /// See EF Core interceptors for more information. + /// public abstract class DbTransactionInterceptor : IDbTransactionInterceptor { /// diff --git a/src/EFCore.Relational/Diagnostics/EntityTypeSchemaEventData.cs b/src/EFCore.Relational/Diagnostics/EntityTypeSchemaEventData.cs index 03a6cf3d0db..01afebdded6 100644 --- a/src/EFCore.Relational/Diagnostics/EntityTypeSchemaEventData.cs +++ b/src/EFCore.Relational/Diagnostics/EntityTypeSchemaEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for events that /// reference an entity type and a schema /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class EntityTypeSchemaEventData : EventData { /// diff --git a/src/EFCore.Relational/Diagnostics/IDbCommandInterceptor.cs b/src/EFCore.Relational/Diagnostics/IDbCommandInterceptor.cs index 05915986874..c9f0816226f 100644 --- a/src/EFCore.Relational/Diagnostics/IDbCommandInterceptor.cs +++ b/src/EFCore.Relational/Diagnostics/IDbCommandInterceptor.cs @@ -29,6 +29,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// order that they are resolved from the service provider, and then the application interceptors are run last. /// /// + /// + /// See EF Core interceptors for more information. + /// public interface IDbCommandInterceptor : IInterceptor { /// diff --git a/src/EFCore.Relational/Diagnostics/IDbConnectionInterceptor.cs b/src/EFCore.Relational/Diagnostics/IDbConnectionInterceptor.cs index fa304d80ed4..b6c6dc9dc55 100644 --- a/src/EFCore.Relational/Diagnostics/IDbConnectionInterceptor.cs +++ b/src/EFCore.Relational/Diagnostics/IDbConnectionInterceptor.cs @@ -29,6 +29,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// order that they are resolved from the service provider, and then the application interceptors are run last. /// /// + /// + /// See EF Core interceptors for more information. + /// public interface IDbConnectionInterceptor : IInterceptor { /// diff --git a/src/EFCore.Relational/Diagnostics/IDbTransactionInterceptor.cs b/src/EFCore.Relational/Diagnostics/IDbTransactionInterceptor.cs index e27154e7ab2..b5079e13c09 100644 --- a/src/EFCore.Relational/Diagnostics/IDbTransactionInterceptor.cs +++ b/src/EFCore.Relational/Diagnostics/IDbTransactionInterceptor.cs @@ -30,6 +30,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// order that they are resolved from the service provider, and then the application interceptors are run last. /// /// + /// + /// See EF Core interceptors for more information. + /// public interface IDbTransactionInterceptor : IInterceptor { /// diff --git a/src/EFCore.Relational/Diagnostics/IRelationalCommandDiagnosticsLogger.cs b/src/EFCore.Relational/Diagnostics/IRelationalCommandDiagnosticsLogger.cs index 8f7ea020ad5..daefa206070 100644 --- a/src/EFCore.Relational/Diagnostics/IRelationalCommandDiagnosticsLogger.cs +++ b/src/EFCore.Relational/Diagnostics/IRelationalCommandDiagnosticsLogger.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// An with some extra functionality suited for high-performance logging. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalCommandDiagnosticsLogger : IDiagnosticsLogger { /// diff --git a/src/EFCore.Relational/Diagnostics/IRelationalConnectionDiagnosticsLogger.cs b/src/EFCore.Relational/Diagnostics/IRelationalConnectionDiagnosticsLogger.cs index 52ae6594875..0dd1866625d 100644 --- a/src/EFCore.Relational/Diagnostics/IRelationalConnectionDiagnosticsLogger.cs +++ b/src/EFCore.Relational/Diagnostics/IRelationalConnectionDiagnosticsLogger.cs @@ -11,6 +11,10 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// /// An with some extra functionality suited for high-performance logging. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalConnectionDiagnosticsLogger : IDiagnosticsLogger { /// diff --git a/src/EFCore.Relational/Diagnostics/IndexEventData.cs b/src/EFCore.Relational/Diagnostics/IndexEventData.cs index f7ced1b2fb6..74bcf217427 100644 --- a/src/EFCore.Relational/Diagnostics/IndexEventData.cs +++ b/src/EFCore.Relational/Diagnostics/IndexEventData.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// A event payload class for /// the events involving an invalid index. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class IndexEventData : EventData { /// diff --git a/src/EFCore.Relational/Diagnostics/IndexWithPropertiesEventData.cs b/src/EFCore.Relational/Diagnostics/IndexWithPropertiesEventData.cs index fc690634a08..1bf659892e8 100644 --- a/src/EFCore.Relational/Diagnostics/IndexWithPropertiesEventData.cs +++ b/src/EFCore.Relational/Diagnostics/IndexWithPropertiesEventData.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// A event payload class for the /// event. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class IndexWithPropertiesEventData : EventData { /// diff --git a/src/EFCore.Relational/Diagnostics/IndexWithPropertyEventData.cs b/src/EFCore.Relational/Diagnostics/IndexWithPropertyEventData.cs index e385d56f55e..ff95669d9ab 100644 --- a/src/EFCore.Relational/Diagnostics/IndexWithPropertyEventData.cs +++ b/src/EFCore.Relational/Diagnostics/IndexWithPropertyEventData.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// A event payload class for /// the events involving an invalid property name on an index. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class IndexWithPropertyEventData : EventData { /// diff --git a/src/EFCore.Relational/Diagnostics/MigrationAssemblyEventData.cs b/src/EFCore.Relational/Diagnostics/MigrationAssemblyEventData.cs index 66017c2eb13..9514cf1ea11 100644 --- a/src/EFCore.Relational/Diagnostics/MigrationAssemblyEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigrationAssemblyEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// migrations assembly events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class MigrationAssemblyEventData : MigratorEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/MigrationEventData.cs b/src/EFCore.Relational/Diagnostics/MigrationEventData.cs index 67294606c6e..45f74d431cf 100644 --- a/src/EFCore.Relational/Diagnostics/MigrationEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigrationEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// events of a specific migration. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class MigrationEventData : MigratorEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/MigrationScriptingEventData.cs b/src/EFCore.Relational/Diagnostics/MigrationScriptingEventData.cs index 8996c8724e0..f088fe4bb40 100644 --- a/src/EFCore.Relational/Diagnostics/MigrationScriptingEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigrationScriptingEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// migration scripting events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class MigrationScriptingEventData : MigrationEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/MigrationTypeEventData.cs b/src/EFCore.Relational/Diagnostics/MigrationTypeEventData.cs index 065ddf612c7..e690c882cce 100644 --- a/src/EFCore.Relational/Diagnostics/MigrationTypeEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigrationTypeEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// migration events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class MigrationTypeEventData : EventData { /// diff --git a/src/EFCore.Relational/Diagnostics/MigratorConnectionEventData.cs b/src/EFCore.Relational/Diagnostics/MigratorConnectionEventData.cs index bdc29d80ee3..f6b1e0f53e9 100644 --- a/src/EFCore.Relational/Diagnostics/MigratorConnectionEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigratorConnectionEventData.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// migration connection events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class MigratorConnectionEventData : MigratorEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/MigratorEventData.cs b/src/EFCore.Relational/Diagnostics/MigratorEventData.cs index a251c14b08f..00e88e8e617 100644 --- a/src/EFCore.Relational/Diagnostics/MigratorEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MigratorEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// migration events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class MigratorEventData : EventData { /// diff --git a/src/EFCore.Relational/Diagnostics/MinBatchSizeEventData.cs b/src/EFCore.Relational/Diagnostics/MinBatchSizeEventData.cs index 181eaba8ac5..750fa868e11 100644 --- a/src/EFCore.Relational/Diagnostics/MinBatchSizeEventData.cs +++ b/src/EFCore.Relational/Diagnostics/MinBatchSizeEventData.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// min batch size events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class MinBatchSizeEventData : BatchEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/RelationalEventId.cs b/src/EFCore.Relational/Diagnostics/RelationalEventId.cs index 04fdbf13ac8..b14129090ec 100644 --- a/src/EFCore.Relational/Diagnostics/RelationalEventId.cs +++ b/src/EFCore.Relational/Diagnostics/RelationalEventId.cs @@ -19,6 +19,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// behavior of warnings. /// /// + /// + /// See Logging, events, and diagnostics for more information. + /// public static class RelationalEventId { // Warning: These values must not change between releases. diff --git a/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs b/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs index c754ee114f2..95b704321a4 100644 --- a/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs +++ b/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs @@ -38,6 +38,10 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public static class RelationalLoggerExtensions { /// diff --git a/src/EFCore.Relational/Diagnostics/RelationalLoggingDefinitions.cs b/src/EFCore.Relational/Diagnostics/RelationalLoggingDefinitions.cs index ff254134937..49dfc24c230 100644 --- a/src/EFCore.Relational/Diagnostics/RelationalLoggingDefinitions.cs +++ b/src/EFCore.Relational/Diagnostics/RelationalLoggingDefinitions.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// to add caching for their events. It should not be used for any other purpose. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class RelationalLoggingDefinitions : LoggingDefinitions { /// diff --git a/src/EFCore.Relational/Diagnostics/SequenceEventData.cs b/src/EFCore.Relational/Diagnostics/SequenceEventData.cs index 6a2782c30e9..fb0066ab69a 100644 --- a/src/EFCore.Relational/Diagnostics/SequenceEventData.cs +++ b/src/EFCore.Relational/Diagnostics/SequenceEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for events that /// reference a sequence. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class SequenceEventData : EventData { /// diff --git a/src/EFCore.Relational/Diagnostics/TransactionEndEventData.cs b/src/EFCore.Relational/Diagnostics/TransactionEndEventData.cs index e4f46f32092..75d43788ca5 100644 --- a/src/EFCore.Relational/Diagnostics/TransactionEndEventData.cs +++ b/src/EFCore.Relational/Diagnostics/TransactionEndEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for /// transaction end events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class TransactionEndEventData : TransactionEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/TransactionEnlistedEventData.cs b/src/EFCore.Relational/Diagnostics/TransactionEnlistedEventData.cs index db9af79d986..988d81358cc 100644 --- a/src/EFCore.Relational/Diagnostics/TransactionEnlistedEventData.cs +++ b/src/EFCore.Relational/Diagnostics/TransactionEnlistedEventData.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload for /// transaction enlisted events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class TransactionEnlistedEventData : EventData { /// diff --git a/src/EFCore.Relational/Diagnostics/TransactionErrorEventData.cs b/src/EFCore.Relational/Diagnostics/TransactionErrorEventData.cs index 63c848ec416..94d9c4bb3d8 100644 --- a/src/EFCore.Relational/Diagnostics/TransactionErrorEventData.cs +++ b/src/EFCore.Relational/Diagnostics/TransactionErrorEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for /// transaction error events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class TransactionErrorEventData : TransactionEndEventData, IErrorEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/TransactionEventData.cs b/src/EFCore.Relational/Diagnostics/TransactionEventData.cs index 20ca9a6f8ba..9cef545c18f 100644 --- a/src/EFCore.Relational/Diagnostics/TransactionEventData.cs +++ b/src/EFCore.Relational/Diagnostics/TransactionEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for /// transaction events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class TransactionEventData : DbContextEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/TransactionStartingEventData.cs b/src/EFCore.Relational/Diagnostics/TransactionStartingEventData.cs index 1e503e51a3d..97592011fab 100644 --- a/src/EFCore.Relational/Diagnostics/TransactionStartingEventData.cs +++ b/src/EFCore.Relational/Diagnostics/TransactionStartingEventData.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for /// transaction events. /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class TransactionStartingEventData : DbContextEventData { /// diff --git a/src/EFCore.Relational/Diagnostics/TwoSqlExpressionsEventData.cs b/src/EFCore.Relational/Diagnostics/TwoSqlExpressionsEventData.cs index f80bbc86a47..489238fb8e2 100644 --- a/src/EFCore.Relational/Diagnostics/TwoSqlExpressionsEventData.cs +++ b/src/EFCore.Relational/Diagnostics/TwoSqlExpressionsEventData.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Diagnostics /// The event payload base class for events that /// references two . /// + /// + /// See Logging, events, and diagnostics for more information. + /// public class TwoSqlExpressionsEventData : EventData { /// diff --git a/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs b/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs index eaa012d0053..55e97fce583 100644 --- a/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs @@ -34,6 +34,9 @@ public static class RelationalDatabaseFacadeExtensions /// to create the database and therefore the database that is created cannot be later updated using migrations. /// /// + /// + /// See Database migrations for more information. + /// /// The for the context. public static void Migrate(this DatabaseFacade databaseFacade) => Check.NotNull(databaseFacade, nameof(databaseFacade)).GetRelationalService().Migrate(); @@ -41,6 +44,9 @@ public static void Migrate(this DatabaseFacade databaseFacade) /// /// Gets all the migrations that are defined in the configured migrations assembly. /// + /// + /// See Database migrations for more information. + /// /// The for the context. /// The list of migrations. public static IEnumerable GetMigrations(this DatabaseFacade databaseFacade) @@ -49,6 +55,9 @@ public static IEnumerable GetMigrations(this DatabaseFacade databaseFaca /// /// Gets all migrations that have been applied to the target database. /// + /// + /// See Database migrations for more information. + /// /// The for the context. /// The list of migrations. public static IEnumerable GetAppliedMigrations(this DatabaseFacade databaseFacade) @@ -58,6 +67,9 @@ public static IEnumerable GetAppliedMigrations(this DatabaseFacade datab /// /// Asynchronously gets all migrations that have been applied to the target database. /// + /// + /// See Database migrations for more information. + /// /// The for the context. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. @@ -71,6 +83,9 @@ public static async Task> GetAppliedMigrationsAsync( /// /// Gets all migrations that are defined in the assembly but haven't been applied to the target database. /// + /// + /// See Database migrations for more information. + /// /// The for the context. /// The list of migrations. public static IEnumerable GetPendingMigrations(this DatabaseFacade databaseFacade) @@ -79,6 +94,9 @@ public static IEnumerable GetPendingMigrations(this DatabaseFacade datab /// /// Asynchronously gets all migrations that are defined in the assembly but haven't been applied to the target database. /// + /// + /// See Database migrations for more information. + /// /// The for the context. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. @@ -100,6 +118,9 @@ public static async Task> GetPendingMigrationsAsync( /// that is created cannot be later updated using migrations. /// /// + /// + /// See Database migrations for more information. + /// /// The for the context. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous migration operation. @@ -139,6 +160,10 @@ public static Task MigrateAsync( /// consider using to create parameters. /// /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// /// The for the context. /// The SQL to execute. /// Parameters to use with the SQL. @@ -173,6 +198,10 @@ public static int ExecuteSqlRaw( /// context.Database.ExecuteSqlInterpolated($"UPDATE Blogs SET Rank = 50 WHERE Name = {userSuppliedSearchTerm})"); /// /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// /// The for the context. /// The interpolated string representing a SQL query with parameters. /// The number of rows affected. @@ -210,6 +239,10 @@ public static int ExecuteSqlInterpolated( /// consider using to create parameters. /// /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// /// The for the context. /// The SQL to execute. /// Parameters to use with the SQL. @@ -276,6 +309,10 @@ public static int ExecuteSqlRaw( /// context.Database.ExecuteSqlInterpolatedAsync($"UPDATE Blogs SET Rank = 50 WHERE Name = {userSuppliedSearchTerm})"); /// /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// /// The for the context. /// The interpolated string representing a SQL query with parameters. /// A to observe while waiting for the task to complete. @@ -312,6 +349,10 @@ public static Task ExecuteSqlInterpolatedAsync( /// into this method. Doing so may expose your application to SQL injection attacks. /// /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// /// The for the context. /// The SQL to execute. /// A to observe while waiting for the task to complete. @@ -354,6 +395,10 @@ public static Task ExecuteSqlRawAsync( /// consider using to create parameters. /// /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// /// The for the context. /// The SQL to execute. /// Parameters to use with the SQL. @@ -395,6 +440,10 @@ public static Task ExecuteSqlRawAsync( /// consider using to create parameters. /// /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// /// The for the context. /// The SQL to execute. /// Parameters to use with the SQL. @@ -455,6 +504,9 @@ public static async Task ExecuteSqlRawAsync( /// passed to Entity Framework in 'UseMyProvider'. /// /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. /// The public static DbConnection GetDbConnection(this DatabaseFacade databaseFacade) @@ -471,6 +523,9 @@ public static DbConnection GetDbConnection(this DatabaseFacade databaseFacade) /// Note that the given connection must be disposed by application code since it was not created by Entity Framework. /// /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. /// The connection. public static void SetDbConnection(this DatabaseFacade databaseFacade, DbConnection? connection) @@ -479,6 +534,9 @@ public static void SetDbConnection(this DatabaseFacade databaseFacade, DbConnect /// /// Gets the underlying connection string configured for this . /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. /// The connection string. public static string? GetConnectionString(this DatabaseFacade databaseFacade) @@ -492,6 +550,9 @@ public static void SetDbConnection(this DatabaseFacade databaseFacade, DbConnect /// It may not be possible to change the connection string if existing connection, if any, is open. /// /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. /// The connection string. public static void SetConnectionString(this DatabaseFacade databaseFacade, string? connectionString) @@ -500,6 +561,9 @@ public static void SetConnectionString(this DatabaseFacade databaseFacade, strin /// /// Opens the underlying . /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. public static void OpenConnection(this DatabaseFacade databaseFacade) => ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Dependencies.ExecutionStrategy @@ -508,6 +572,9 @@ public static void OpenConnection(this DatabaseFacade databaseFacade) /// /// Opens the underlying . /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. @@ -521,6 +588,9 @@ public static Task OpenConnectionAsync( /// /// Closes the underlying . /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. public static void CloseConnection(this DatabaseFacade databaseFacade) => GetFacadeDependencies(databaseFacade).RelationalConnection.Close(); @@ -528,6 +598,9 @@ public static void CloseConnection(this DatabaseFacade databaseFacade) /// /// Closes the underlying . /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. /// A task that represents the asynchronous operation. public static Task CloseConnectionAsync(this DatabaseFacade databaseFacade) @@ -536,6 +609,9 @@ public static Task CloseConnectionAsync(this DatabaseFacade databaseFacade) /// /// Starts a new transaction with a given . /// + /// + /// See Transactions in EF Core for more information. + /// /// The for the context. /// The to use. /// A that represents the started transaction. @@ -554,6 +630,9 @@ public static IDbContextTransaction BeginTransaction(this DatabaseFacade databas /// /// Asynchronously starts a new transaction with a given . /// + /// + /// See Transactions in EF Core for more information. + /// /// The for the context. /// The to use. /// A to observe while waiting for the task to complete. @@ -579,6 +658,9 @@ public static Task BeginTransactionAsync( /// /// Sets the to be used by database operations on the . /// + /// + /// See Transactions in EF Core for more information. + /// /// The for the context. /// The to use. /// A that encapsulates the given transaction. @@ -590,6 +672,9 @@ public static Task BeginTransactionAsync( /// /// Sets the to be used by database operations on the . /// + /// + /// See Transactions in EF Core for more information. + /// /// The for the context. /// The to use. /// The unique identifier for the transaction. @@ -605,6 +690,9 @@ public static Task BeginTransactionAsync( /// /// Sets the to be used by database operations on the . /// + /// + /// See Transactions in EF Core for more information. + /// /// The for the context. /// The to use. /// A to observe while waiting for the task to complete. @@ -619,6 +707,9 @@ public static Task BeginTransactionAsync( /// /// Sets the to be used by database operations on the . /// + /// + /// See Transactions in EF Core for more information. + /// /// The for the context. /// The to use. /// The unique identifier for the transaction. @@ -654,6 +745,9 @@ public static Task BeginTransactionAsync( /// will override any value set in the connection string. /// /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. /// The timeout to use, in seconds. public static void SetCommandTimeout(this DatabaseFacade databaseFacade, int? timeout) @@ -668,6 +762,9 @@ public static void SetCommandTimeout(this DatabaseFacade databaseFacade, int? ti /// . /// /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. /// The timeout to use. public static void SetCommandTimeout(this DatabaseFacade databaseFacade, TimeSpan timeout) @@ -700,6 +797,9 @@ public static void SetCommandTimeout(this DatabaseFacade databaseFacade, TimeSpa /// set on the database connection string. /// /// + /// + /// See Connections and connection strings for more information. + /// /// The for the context. /// The timeout, in seconds, or null if no timeout has been set. public static int? GetCommandTimeout(this DatabaseFacade databaseFacade) @@ -708,6 +808,9 @@ public static void SetCommandTimeout(this DatabaseFacade databaseFacade, TimeSpa /// /// Generates a script to create all tables for the current model. /// + /// + /// See Database migrations for more information. + /// /// /// A SQL script. /// diff --git a/src/EFCore.Relational/Extensions/RelationalDbFunctionsExtensions.cs b/src/EFCore.Relational/Extensions/RelationalDbFunctionsExtensions.cs index 8eb3a060539..5d906073c73 100644 --- a/src/EFCore.Relational/Extensions/RelationalDbFunctionsExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalDbFunctionsExtensions.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore /// Provides CLR methods that get translated to database functions when used in LINQ to Entities queries. /// The methods on this class are accessed via . /// + /// + /// See Database functions for more information. + /// public static class RelationalDbFunctionsExtensions { /// @@ -25,8 +28,7 @@ public static class RelationalDbFunctionsExtensions /// /// /// - /// This DbFunction method has no in-memory implementation and will throw if the query switches to client-evaluation. - /// This can happen if the query contains one or more expressions that could not be translated to the store. + /// See Database functions for more information. /// /// The type of the operand on which the collation is being specified. /// The instance. diff --git a/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs index 7c22f576506..d069c24c82a 100644 --- a/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs @@ -5,7 +5,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; -using System.Xml.Linq; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -17,11 +16,17 @@ namespace Microsoft.EntityFrameworkCore /// /// Relational database specific extension methods for . /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalEntityTypeBuilderExtensions { /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The same builder instance so that multiple calls can be chained. @@ -40,6 +45,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// An action that performs configuration of the table. /// The same builder instance so that multiple calls can be chained. @@ -57,6 +65,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// An action that performs configuration of the table. @@ -79,6 +90,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The name of the table. @@ -92,6 +106,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// An action that performs configuration of the table. @@ -111,6 +128,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The name of the table. @@ -135,6 +155,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The schema of the table. @@ -155,6 +178,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The schema of the table. @@ -180,6 +206,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The name of the table. @@ -195,6 +224,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The name of the table. @@ -222,6 +254,9 @@ public static EntityTypeBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The same builder instance so that multiple calls can be chained. @@ -240,6 +275,9 @@ public static OwnedNavigationBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// An action that performs configuration of the table. /// The same builder instance so that multiple calls can be chained. @@ -257,6 +295,9 @@ public static OwnedNavigationBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// An action that performs configuration of the table. /// The same builder instance so that multiple calls can be chained. @@ -276,6 +317,9 @@ public static OwnedNavigationBuilder ToTable /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// A value indicating whether the table should be managed by migrations. @@ -290,6 +334,9 @@ public static OwnedNavigationBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The same builder instance so that multiple calls can be chained. @@ -303,6 +350,9 @@ public static OwnedNavigationBuilder ToTable /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// An action that performs configuration of the table. @@ -325,6 +375,9 @@ public static OwnedNavigationBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// A value indicating whether the table should be managed by migrations. @@ -342,6 +395,9 @@ public static OwnedNavigationBuilder ToTable /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// An action that performs configuration of the table. @@ -366,6 +422,9 @@ public static OwnedNavigationBuilder ToTable /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The schema of the table. @@ -387,6 +446,9 @@ public static OwnedNavigationBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The schema of the table. @@ -409,6 +471,9 @@ public static OwnedNavigationBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The schema of the table. @@ -434,6 +499,9 @@ public static OwnedNavigationBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The schema of the table. @@ -449,6 +517,9 @@ public static OwnedNavigationBuilder ToTable /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The schema of the table. @@ -468,6 +539,9 @@ public static OwnedNavigationBuilder ToTable /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The schema of the table. @@ -513,6 +587,9 @@ private static OwnedNavigationBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// Indicates whether the configuration was specified using a data annotation. @@ -536,6 +613,9 @@ private static OwnedNavigationBuilder ToTable( /// /// Configures the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// The schema of the table. @@ -564,6 +644,9 @@ private static OwnedNavigationBuilder ToTable( /// Returns a value indicating whether the table name can be set for this entity type /// using the specified configuration source. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the table. /// Indicates whether the configuration was specified using a data annotation. @@ -581,6 +664,9 @@ public static bool CanSetTable( /// /// Configures the schema of the table that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The schema of the table. /// Indicates whether the configuration was specified using a data annotation. @@ -605,6 +691,9 @@ public static bool CanSetTable( /// Returns a value indicating whether the schema of the table name can be set for this entity type /// using the specified configuration source. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The schema of the table. /// Indicates whether the configuration was specified using a data annotation. @@ -622,6 +711,9 @@ public static bool CanSetSchema( /// /// Mark the table that this entity type is mapped to as excluded from migrations. /// + /// + /// See Database migrations for more information. + /// /// The builder for the entity type being configured. /// A value indicating whether the table should be managed by migrations. /// Indicates whether the configuration was specified using a data annotation. @@ -647,6 +739,9 @@ public static bool CanSetSchema( /// Returns a value indicating whether the table that this entity type is mapped to can be excluded from migrations /// using the specified configuration source. /// + /// + /// See Database migrations for more information. + /// /// The builder for the entity type being configured. /// A value indicating whether the table should be managed by migrations. /// Indicates whether the configuration was specified using a data annotation. @@ -661,6 +756,9 @@ public static bool CanExcludeTableFromMigrations( /// /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the view. /// The same builder instance so that multiple calls can be chained. @@ -672,6 +770,9 @@ public static EntityTypeBuilder ToView( /// /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The name of the view. @@ -685,6 +786,9 @@ public static EntityTypeBuilder ToView( /// /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the view. /// The schema of the view. @@ -708,6 +812,9 @@ public static EntityTypeBuilder ToView( /// /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The name of the view. @@ -723,6 +830,9 @@ public static EntityTypeBuilder ToView( /// /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the view. /// The same builder instance so that multiple calls can be chained. @@ -734,6 +844,9 @@ public static OwnedNavigationBuilder ToView( /// /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the view. /// The same builder instance so that multiple calls can be chained. @@ -747,6 +860,9 @@ public static OwnedNavigationBuilder ToView /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the view. /// The schema of the view. @@ -770,6 +886,9 @@ public static OwnedNavigationBuilder ToView( /// /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the view. /// The schema of the view. @@ -785,6 +904,9 @@ public static OwnedNavigationBuilder ToView /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the view. /// Indicates whether the configuration was specified using a data annotation. @@ -808,6 +930,9 @@ public static OwnedNavigationBuilder ToView /// Configures the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the view. /// The schema of the view. @@ -836,6 +961,9 @@ public static OwnedNavigationBuilder ToView + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the view. /// Indicates whether the configuration was specified using a data annotation. @@ -853,6 +981,9 @@ public static bool CanSetView( /// /// Configures the schema of the view that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The schema of the view. /// Indicates whether the configuration was specified using a data annotation. @@ -877,6 +1008,9 @@ public static bool CanSetView( /// Returns a value indicating whether the schema of the view can be set for this entity type /// using the specified configuration source. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The schema of the view. /// Indicates whether the configuration was specified using a data annotation. @@ -894,6 +1028,9 @@ public static bool CanSetViewSchema( /// /// Configures a SQL string used to provide data for the entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The SQL query that will provide the underlying data for the entity type. /// The same builder instance so that multiple calls can be chained. @@ -911,6 +1048,9 @@ public static EntityTypeBuilder ToSqlQuery( /// /// Configures a SQL string used to provide data for the entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The SQL query that will provide the underlying data for the entity type. /// The same builder instance so that multiple calls can be chained. @@ -923,6 +1063,9 @@ public static EntityTypeBuilder ToSqlQuery( /// /// Configures a SQL string used to provide data for the entity type. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The SQL query that will provide the underlying data for the entity type. /// Indicates whether the configuration was specified using a data annotation. @@ -949,6 +1092,9 @@ public static EntityTypeBuilder ToSqlQuery( /// Returns a value indicating whether the query SQL string can be set for this entity type /// using the specified configuration source. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The SQL query that will provide the underlying data for the entity type. /// Indicates whether the configuration was specified using a data annotation. @@ -966,6 +1112,9 @@ public static bool CanSetSqlQuery( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the function. /// The function configuration builder. @@ -984,6 +1133,9 @@ public static EntityTypeBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The method representing the function. /// The function configuration builder. @@ -1001,6 +1153,9 @@ public static EntityTypeBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the function. /// The function configuration action. @@ -1022,6 +1177,9 @@ public static EntityTypeBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The method representing the function. /// The function configuration action. @@ -1043,6 +1201,9 @@ public static EntityTypeBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The name of the function. @@ -1056,6 +1217,9 @@ public static EntityTypeBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The method representing the function. @@ -1069,6 +1233,9 @@ public static EntityTypeBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The name of the function. @@ -1084,6 +1251,9 @@ public static EntityTypeBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The builder for the entity type being configured. /// The method representing the function. @@ -1099,6 +1269,9 @@ public static EntityTypeBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the function. /// The function configuration builder. @@ -1117,6 +1290,9 @@ public static OwnedNavigationBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The method representing the function. /// The function configuration builder. @@ -1134,6 +1310,9 @@ public static OwnedNavigationBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the function. /// The function configuration action. @@ -1155,6 +1334,9 @@ public static OwnedNavigationBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The method representing the function. /// The function configuration action. @@ -1176,6 +1358,9 @@ public static OwnedNavigationBuilder ToFunction( /// /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the function. /// The function configuration builder. @@ -1189,6 +1374,9 @@ public static OwnedNavigationBuilder ToFunction /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The method representing the function. /// The function configuration builder. @@ -1202,6 +1390,9 @@ public static OwnedNavigationBuilder ToFunction /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the function. /// The function configuration action. @@ -1218,6 +1409,9 @@ public static OwnedNavigationBuilder ToFunction /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The method representing the function. /// The function configuration action. @@ -1283,6 +1477,9 @@ public static OwnedNavigationBuilder ToFunction /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the function. /// Indicates whether the configuration was specified using a data annotation. @@ -1314,6 +1511,9 @@ public static OwnedNavigationBuilder ToFunction /// Configures the function that the entity type maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The method representing the function. /// Indicates whether the configuration was specified using a data annotation. @@ -1347,6 +1547,9 @@ public static OwnedNavigationBuilder ToFunction + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The name of the function. /// Indicates whether the configuration was specified using a data annotation. @@ -1365,6 +1568,9 @@ public static bool CanSetFunction( /// Returns a value indicating whether the function name can be set for this entity type /// using the specified configuration source. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The method representing the function. /// Indicates whether the configuration was specified using a data annotation. @@ -1378,6 +1584,9 @@ public static bool CanSetFunction( /// /// Configures a database check constraint when targeting a relational database. /// + /// + /// See Database check constraints for more information. + /// /// The entity type builder. /// The name of the check constraint. /// The logical constraint sql used in the check constraint. @@ -1401,6 +1610,9 @@ public static EntityTypeBuilder HasCheckConstraint( /// /// Configures a database check constraint when targeting a relational database. /// + /// + /// See Database check constraints for more information. + /// /// The entity type builder. /// The name of the check constraint. /// The logical constraint sql used in the check constraint. @@ -1425,6 +1637,9 @@ public static EntityTypeBuilder HasCheckConstraint( /// /// Configures a database check constraint when targeting a relational database. /// + /// + /// See Database check constraints for more information. + /// /// The entity type being configured. /// The entity type builder. /// The name of the check constraint. @@ -1440,6 +1655,9 @@ public static EntityTypeBuilder HasCheckConstraint( /// /// Configures a database check constraint when targeting a relational database. /// + /// + /// See Database check constraints for more information. + /// /// The entity type being configured. /// The entity type builder. /// The name of the check constraint. @@ -1457,6 +1675,9 @@ public static EntityTypeBuilder HasCheckConstraint( /// /// Configures a database check constraint when targeting a relational database. /// + /// + /// See Database check constraints for more information. + /// /// The navigation builder for the owned type. /// The name of the check constraint. /// The logical constraint sql used in the check constraint. @@ -1480,6 +1701,9 @@ public static OwnedNavigationBuilder HasCheckConstraint( /// /// Configures a database check constraint when targeting a relational database. /// + /// + /// See Database check constraints for more information. + /// /// The navigation builder for the owned type. /// The name of the check constraint. /// The logical constraint sql used in the check constraint. @@ -1496,6 +1720,9 @@ public static OwnedNavigationBuilder HasCheckCon /// /// Configures a database check constraint when targeting a relational database. /// + /// + /// See Database check constraints for more information. + /// /// The navigation builder for the owned type. /// The name of the check constraint. /// The logical constraint sql used in the check constraint. @@ -1520,6 +1747,9 @@ public static OwnedNavigationBuilder HasCheckConstraint( /// /// Configures a database check constraint when targeting a relational database. /// + /// + /// See Database check constraints for more information. + /// /// The entity type owning the relationship. /// The dependent entity type of the relationship. /// The navigation builder for the owned type. @@ -1540,6 +1770,9 @@ public static OwnedNavigationBuilder HasCheckCon /// /// Configures a database check constraint when targeting a relational database. /// + /// + /// See Database check constraints for more information. + /// /// The entity type builder. /// The name of the check constraint. /// The logical constraint sql used in the check constraint. @@ -1563,6 +1796,9 @@ public static OwnedNavigationBuilder HasCheckCon /// /// Returns a value indicating whether the check constraint can be configured. /// + /// + /// See Database check constraints for more information. + /// /// The builder for the entity type being configured. /// The name of the check constraint. /// The logical constraint sql used in the check constraint. @@ -1579,6 +1815,9 @@ public static bool CanSetCheckConstraint( /// /// Returns a value indicating whether the check constraint can be configured. /// + /// + /// See Database check constraints for more information. + /// /// The builder for the entity type being configured. /// The name of the check constraint. /// The logical constraint sql used in the check constraint. @@ -1598,6 +1837,9 @@ public static bool CanHaveCheckConstraint( /// /// Configures a comment to be applied to the table /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The comment for the table. /// A builder to further configure the entity type. @@ -1614,6 +1856,9 @@ public static EntityTypeBuilder HasComment( /// /// Configures a comment to be applied to the table /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The entity type being configured. /// The entity type builder. /// The comment for the table. @@ -1627,6 +1872,9 @@ public static EntityTypeBuilder HasComment( /// /// Configures a comment to be applied to the table /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The comment for the table. /// Indicates whether the configuration was specified using a data annotation. @@ -1654,6 +1902,9 @@ public static EntityTypeBuilder HasComment( /// Returns a value indicating whether a comment can be set for this entity type /// using the specified configuration source. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the entity type being configured. /// The comment for the table. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs index ecfe1f5c0c3..c6813a1ba19 100644 --- a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Entity type extension methods for relational database metadata. /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalEntityTypeExtensions { /// diff --git a/src/EFCore.Relational/Extensions/RelationalForeignKeyBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalForeignKeyBuilderExtensions.cs index b23d7c859c1..f19aaf31500 100644 --- a/src/EFCore.Relational/Extensions/RelationalForeignKeyBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalForeignKeyBuilderExtensions.cs @@ -11,11 +11,17 @@ namespace Microsoft.EntityFrameworkCore /// /// Relational database specific extension methods for relationship builders. /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalForeignKeyBuilderExtensions { /// /// Configures the foreign key constraint name for this relationship when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder being used to configure the relationship. /// The name of the foreign key constraint. /// The same builder instance so that multiple calls can be chained. @@ -34,6 +40,9 @@ public static ReferenceCollectionBuilder HasConstraintName( /// /// Configures the foreign key constraint name for this relationship when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder being used to configure the relationship. /// The name of the foreign key constraint. /// The same builder instance so that multiple calls can be chained. @@ -50,6 +59,9 @@ public static ReferenceCollectionBuilder HasConstraintN /// /// Configures the foreign key constraint name for this relationship when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder being used to configure the relationship. /// The name of the foreign key constraint. /// The same builder instance so that multiple calls can be chained. @@ -68,6 +80,9 @@ public static ReferenceReferenceBuilder HasConstraintName( /// /// Configures the foreign key constraint name for this relationship when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder being used to configure the relationship. /// The name of the foreign key constraint. /// The same builder instance so that multiple calls can be chained. @@ -84,6 +99,9 @@ public static ReferenceReferenceBuilder HasConstraintNa /// /// Configures the foreign key constraint name for this relationship when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder being used to configure the relationship. /// The name of the foreign key constraint. /// The same builder instance so that multiple calls can be chained. @@ -101,6 +119,9 @@ public static OwnershipBuilder HasConstraintName( /// /// Configures the foreign key constraint name for this relationship when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder being used to configure the relationship. /// The name of the foreign key constraint. /// The same builder instance so that multiple calls can be chained. @@ -117,6 +138,9 @@ public static OwnershipBuilder HasConstraintName /// Configures the foreign key constraint name for this relationship when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder being used to configure the relationship. /// The name of the foreign key constraint. /// Indicates whether the configuration was specified using a data annotation. @@ -142,6 +166,9 @@ public static OwnershipBuilder HasConstraintName + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder being used to configure the relationship. /// The name of the foreign key constraint. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.Relational/Extensions/RelationalForeignKeyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalForeignKeyExtensions.cs index 441b5ffbbc8..e58eadd022a 100644 --- a/src/EFCore.Relational/Extensions/RelationalForeignKeyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalForeignKeyExtensions.cs @@ -12,8 +12,11 @@ namespace Microsoft.EntityFrameworkCore { /// - /// Foregn key extension methods for relational database metadata. + /// Foreign key extension methods for relational database metadata. /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalForeignKeyExtensions { /// diff --git a/src/EFCore.Relational/Extensions/RelationalIndexBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalIndexBuilderExtensions.cs index d9cc2f2ddff..4fa5412ee6a 100644 --- a/src/EFCore.Relational/Extensions/RelationalIndexBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalIndexBuilderExtensions.cs @@ -12,11 +12,17 @@ namespace Microsoft.EntityFrameworkCore /// /// Relational database specific extension methods for . /// + /// + /// See Indexes for more information. + /// public static class RelationalIndexBuilderExtensions { /// /// Configures the name of the index in the database when targeting a relational database. /// + /// + /// See Indexes for more information. + /// /// The builder for the index being configured. /// The name of the index. /// A builder to further configure the index. @@ -30,6 +36,9 @@ public static IndexBuilder HasDatabaseName(this IndexBuilder indexBuilder, strin /// /// Configures the name of the index in the database when targeting a relational database. /// + /// + /// See Indexes for more information. + /// /// The builder for the index being configured. /// The name of the index. /// A builder to further configure the index. @@ -40,6 +49,9 @@ public static IndexBuilder HasName(this IndexBuilder indexBuilder, string? name) /// /// Configures the name of the index in the database when targeting a relational database. /// + /// + /// See Indexes for more information. + /// /// The entity type being configured. /// The builder for the index being configured. /// The name of the index. @@ -56,6 +68,9 @@ public static IndexBuilder HasDatabaseName( /// /// Configures the name of the index in the database when targeting a relational database. /// + /// + /// See Indexes for more information. + /// /// The entity type being configured. /// The builder for the index being configured. /// The name of the index. @@ -67,6 +82,9 @@ public static IndexBuilder HasName(this IndexBuilder /// /// Configures the name of the index in the database when targeting a relational database. /// + /// + /// See Indexes for more information. + /// /// The builder for the index being configured. /// The name of the index. /// Indicates whether the configuration was specified using a data annotation. @@ -91,6 +109,9 @@ public static IndexBuilder HasName(this IndexBuilder /// /// Configures the name of the index in the database when targeting a relational database. /// + /// + /// See Indexes for more information. + /// /// The builder for the index being configured. /// The name of the index. /// Indicates whether the configuration was specified using a data annotation. @@ -108,6 +129,9 @@ public static IndexBuilder HasName(this IndexBuilder /// /// Returns a value indicating whether the given name can be set for the index. /// + /// + /// See Indexes for more information. + /// /// The builder for the index being configured. /// The name of the index. /// Indicates whether the configuration was specified using a data annotation. @@ -121,6 +145,9 @@ public static bool CanSetDatabaseName( /// /// Returns a value indicating whether the given name can be set for the index. /// + /// + /// See Indexes for more information. + /// /// The builder for the index being configured. /// The name of the index. /// Indicates whether the configuration was specified using a data annotation. @@ -135,6 +162,9 @@ public static bool CanSetName( /// /// Configures the filter expression for the index. /// + /// + /// See Indexes for more information. + /// /// The builder for the index being configured. /// The filter expression for the index. /// A builder to further configure the index. @@ -151,6 +181,9 @@ public static IndexBuilder HasFilter(this IndexBuilder indexBuilder, string? sql /// /// Configures the filter expression for the index. /// + /// + /// See Indexes for more information. + /// /// The entity type being configured. /// The builder for the index being configured. /// The filter expression for the index. @@ -161,6 +194,9 @@ public static IndexBuilder HasFilter(this IndexBuilder /// Configures the filter expression for the index. /// + /// + /// See Indexes for more information. + /// /// The builder for the index being configured. /// The filter expression for the index. /// Indicates whether the configuration was specified using a data annotation. @@ -185,6 +221,9 @@ public static IndexBuilder HasFilter(this IndexBuilder /// Returns a value indicating whether the given expression can be set as the filter for the index. /// + /// + /// See Indexes for more information. + /// /// The builder for the index being configured. /// The filter expression for the index. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.Relational/Extensions/RelationalIndexExtensions.cs b/src/EFCore.Relational/Extensions/RelationalIndexExtensions.cs index 1483d019a28..67a4bfdda29 100644 --- a/src/EFCore.Relational/Extensions/RelationalIndexExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalIndexExtensions.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Index extension methods for relational database metadata. /// + /// + /// See Indexes for more information. + /// public static class RelationalIndexExtensions { /// diff --git a/src/EFCore.Relational/Extensions/RelationalKeyBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalKeyBuilderExtensions.cs index ff42977b917..60e13c5efda 100644 --- a/src/EFCore.Relational/Extensions/RelationalKeyBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalKeyBuilderExtensions.cs @@ -11,11 +11,17 @@ namespace Microsoft.EntityFrameworkCore /// /// Relational database specific extension methods for . /// + /// + /// See Keys for more information. + /// public static class RelationalKeyBuilderExtensions { /// /// Configures the name of the key constraint in the database when targeting a relational database. /// + /// + /// See Keys for more information. + /// /// The builder for the key being configured. /// The name of the key. /// The same builder instance so that multiple calls can be chained. @@ -32,6 +38,9 @@ public static KeyBuilder HasName(this KeyBuilder keyBuilder, string? name) /// /// Configures the name of the key constraint in the database when targeting a relational database. /// + /// + /// See Keys for more information. + /// /// The builder for the key being configured. /// The name of the key. /// The same builder instance so that multiple calls can be chained. @@ -43,6 +52,9 @@ public static KeyBuilder HasName( /// /// Configures the name of the key constraint in the database when targeting a relational database. /// + /// + /// See Keys for more information. + /// /// The builder for the key being configured. /// The name of the key. /// Indicates whether the configuration was specified using a data annotation. @@ -67,6 +79,9 @@ public static KeyBuilder HasName( /// /// Returns a value indicating whether the given name can be set for the key constraint. /// + /// + /// See Keys for more information. + /// /// The builder for the key being configured. /// The name of the index. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.Relational/Extensions/RelationalKeyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalKeyExtensions.cs index 3cca77f3078..89efc02377c 100644 --- a/src/EFCore.Relational/Extensions/RelationalKeyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalKeyExtensions.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Key extension methods for relational database metadata. /// + /// + /// See Keys for more information. + /// public static class RelationalKeyExtensions { /// diff --git a/src/EFCore.Relational/Extensions/RelationalModelBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalModelBuilderExtensions.cs index eb16986ff66..416b3941653 100644 --- a/src/EFCore.Relational/Extensions/RelationalModelBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalModelBuilderExtensions.cs @@ -16,11 +16,17 @@ namespace Microsoft.EntityFrameworkCore /// /// Relational database specific extension methods for . /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalModelBuilderExtensions { /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The model builder. /// The name of the sequence. /// The schema of the sequence. @@ -39,6 +45,9 @@ public static SequenceBuilder HasSequence( /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The model builder. /// The name of the sequence. /// An action that performs configuration of the sequence. @@ -52,6 +61,9 @@ public static ModelBuilder HasSequence( /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The model builder. /// The name of the sequence. /// The schema of the sequence. @@ -73,6 +85,9 @@ public static ModelBuilder HasSequence( /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The type of values the sequence will generate. /// The model builder. /// The name of the sequence. @@ -96,6 +111,9 @@ public static SequenceBuilder HasSequence( /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The type of values the sequence will generate. /// The model builder. /// The name of the sequence. @@ -111,6 +129,9 @@ public static ModelBuilder HasSequence( /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The type of values the sequence will generate. /// The model builder. /// The name of the sequence. @@ -134,6 +155,9 @@ public static ModelBuilder HasSequence( /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The type of values the sequence will generate. /// The model builder. /// The name of the sequence. @@ -155,6 +179,9 @@ public static SequenceBuilder HasSequence( /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The type of values the sequence will generate. /// The model builder. /// The name of the sequence. @@ -169,6 +196,9 @@ public static ModelBuilder HasSequence( /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The type of values the sequence will generate. /// The model builder. /// The name of the sequence. @@ -191,6 +221,9 @@ public static ModelBuilder HasSequence( /// /// Configures a database sequence when targeting a relational database. /// + /// + /// See Database sequences for more information. + /// /// The model builder. /// The name of the sequence. /// The schema of the sequence. @@ -229,6 +262,9 @@ private static Sequence HasSequence( /// /// Configures a database function when targeting a relational database. /// + /// + /// See Database functions for more information. + /// /// The model builder. /// The methodInfo this dbFunction uses. /// A builder to further configure the function. @@ -255,6 +291,9 @@ public static DbFunctionBuilder HasDbFunction( /// /// Configures a database function when targeting a relational database. /// + /// + /// See Database functions for more information. + /// /// The model builder. /// The method this dbFunction uses. /// A builder to further configure the function. @@ -278,6 +317,9 @@ public static DbFunctionBuilder HasDbFunction( /// /// Configures a database function when targeting a relational database. /// + /// + /// See Database functions for more information. + /// /// The model builder. /// The methodInfo this dbFunction uses. /// An action that performs configuration of the sequence. @@ -297,6 +339,9 @@ public static ModelBuilder HasDbFunction( /// /// Configures a relational database function. /// + /// + /// See Database functions for more information. + /// /// The model builder. /// The method this function uses. /// Indicates whether the configuration was specified using a data annotation. @@ -326,6 +371,9 @@ public static IConventionDbFunctionBuilder HasDbFunction( /// /// Configures a relational database function. /// + /// + /// See Database functions for more information. + /// /// The model builder. /// The name of the function. /// The function's return type. @@ -358,6 +406,9 @@ public static IConventionDbFunctionBuilder HasDbFunction( /// Configures the default schema that database objects should be created in, if no schema /// is explicitly configured. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The model builder. /// The default schema. /// The same builder instance so that multiple calls can be chained. @@ -377,6 +428,9 @@ public static ModelBuilder HasDefaultSchema( /// Configures the default schema that database objects should be created in, if no schema /// is explicitly configured. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The model builder. /// The default schema. /// Indicates whether the configuration was specified using a data annotation. @@ -402,6 +456,9 @@ public static ModelBuilder HasDefaultSchema( /// /// Returns a value indicating whether the given schema can be set as default. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The model builder. /// The default schema. /// Indicates whether the configuration was specified using a data annotation. @@ -420,6 +477,9 @@ public static bool CanSetDefaultSchema( /// /// Configures the maximum length allowed for store identifiers. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The model builder. /// The value to set. /// Indicates whether the configuration was specified using a data annotation. @@ -445,6 +505,9 @@ public static bool CanSetDefaultSchema( /// /// Returns a value indicating whether the maximum length allowed for store identifiers can be set. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The model builder. /// The value to set. /// Indicates whether the configuration was specified using a data annotation. @@ -462,6 +525,9 @@ public static bool CanSetMaxIdentifierLength( /// /// Configures the database collation, which will be used by all columns without an explicit collation. /// + /// + /// See Database collations for more information. + /// /// The model builder. /// The collation. /// The same builder instance so that multiple calls can be chained. @@ -480,6 +546,9 @@ public static ModelBuilder UseCollation( /// /// Configures the database collation, which will be used by all columns without an explicit collation. /// + /// + /// See Database collations for more information. + /// /// The model builder. /// The collation. /// Indicates whether the configuration was specified using a data annotation. @@ -505,6 +574,9 @@ public static ModelBuilder UseCollation( /// /// Returns a value indicating whether the given collation can be set as default. /// + /// + /// See Database collations for more information. + /// /// The model builder. /// The collation. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.Relational/Extensions/RelationalModelExtensions.cs b/src/EFCore.Relational/Extensions/RelationalModelExtensions.cs index 80e4fc6581e..7509b21b560 100644 --- a/src/EFCore.Relational/Extensions/RelationalModelExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalModelExtensions.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Relational-specific model extension methods. /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalModelExtensions { /// diff --git a/src/EFCore.Relational/Extensions/RelationalPropertiesConfigurationBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertiesConfigurationBuilderExtensions.cs index b651b91e503..653e20ebd3b 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertiesConfigurationBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertiesConfigurationBuilderExtensions.cs @@ -17,6 +17,9 @@ public static class RelationalPropertiesConfigurationBuilderExtensions /// Configures the data type of the column that the property maps to when targeting a relational database. /// This should be the complete type name, including precision, scale, length, etc. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The name of the data type of the column. /// The same builder instance so that multiple calls can be chained. @@ -36,6 +39,9 @@ public static PropertiesConfigurationBuilder HaveColumnType( /// Configures the data type of the column that the property maps to when targeting a relational database. /// This should be the complete type name, including precision, scale, length, etc. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The name of the data type of the column. @@ -48,6 +54,9 @@ public static PropertiesConfigurationBuilder HaveColumnType /// Configures the property as capable of storing only fixed-length data, such as strings. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// A value indicating whether the property is constrained to fixed length values. /// The same builder instance so that multiple configuration calls can be chained. @@ -65,6 +74,9 @@ public static PropertiesConfigurationBuilder AreFixedLength( /// /// Configures the property as capable of storing only fixed-length data, such as strings. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// A value indicating whether the property is constrained to fixed length values. @@ -78,6 +90,9 @@ public static PropertiesConfigurationBuilder AreFixedLength + /// + /// See Database collations for more information. + /// /// The builder for the property being configured. /// The collation for the column. /// The same builder instance so that multiple calls can be chained. @@ -95,6 +110,9 @@ public static PropertiesConfigurationBuilder UseCollation(this PropertiesConfigu /// Configures the property to use the given collation. The database column will be created with the given /// collation, and it will be used implicitly in all collation-sensitive operations. /// + /// + /// See Database collations for more information. + /// /// The builder for the property being configured. /// The collation for the column. /// The same builder instance so that multiple calls can be chained. diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyBuilderExtensions.cs index d37f5f2eedc..e02658b2f15 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertyBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertyBuilderExtensions.cs @@ -13,11 +13,17 @@ namespace Microsoft.EntityFrameworkCore /// /// Relational database specific extension methods for . /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalPropertyBuilderExtensions { /// /// Configures the column that the property maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The name of the column. /// The same builder instance so that multiple calls can be chained. @@ -36,6 +42,9 @@ public static PropertyBuilder HasColumnName( /// /// Configures the column that the property maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The name of the column. @@ -48,6 +57,9 @@ public static PropertyBuilder HasColumnName( /// /// Configures the column that the property maps to when targeting a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The name of the column. /// Indicates whether the configuration was specified using a data annotation. @@ -72,6 +84,9 @@ public static PropertyBuilder HasColumnName( /// /// Configures the column that the property maps to in a particular table-like store object. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The name of the column. /// The identifier of the store object. @@ -98,6 +113,9 @@ public static PropertyBuilder HasColumnName( /// /// Returns a value indicating whether the given column can be set for the property. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The name of the column. /// Indicates whether the configuration was specified using a data annotation. @@ -111,6 +129,9 @@ public static bool CanSetColumnName( /// /// Returns a value indicating whether the given column for a particular table-like store object can be set for the property. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The name of the column. /// The identifier of the store object. @@ -189,6 +210,9 @@ public static bool CanSetColumnOrder(this IConventionPropertyBuilder propertyBui /// Configures the data type of the column that the property maps to when targeting a relational database. /// This should be the complete type name, including precision, scale, length, etc. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The name of the data type of the column. /// The same builder instance so that multiple calls can be chained. @@ -208,6 +232,9 @@ public static PropertyBuilder HasColumnType( /// Configures the data type of the column that the property maps to when targeting a relational database. /// This should be the complete type name, including precision, scale, length, etc. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The name of the data type of the column. @@ -221,6 +248,9 @@ public static PropertyBuilder HasColumnType( /// Configures the data type of the column that the property maps to when targeting a relational database. /// This should be the complete type name, including precision, scale, length, etc. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The name of the data type of the column. /// Indicates whether the configuration was specified using a data annotation. @@ -245,6 +275,9 @@ public static PropertyBuilder HasColumnType( /// /// Returns a value indicating whether the given data type can be set for the property. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The name of the data type of the column. /// Indicates whether the configuration was specified using a data annotation. @@ -258,6 +291,9 @@ public static bool CanSetColumnType( /// /// Configures the property as capable of storing only fixed-length data, such as strings. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// A value indicating whether the property is constrained to fixed length values. /// The same builder instance so that multiple configuration calls can be chained. @@ -275,6 +311,9 @@ public static PropertyBuilder IsFixedLength( /// /// Configures the property as capable of storing only fixed-length data, such as strings. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// A value indicating whether the property is constrained to fixed length values. @@ -287,6 +326,9 @@ public static PropertyBuilder IsFixedLength( /// /// Configures the property as capable of storing only fixed-length data, such as strings. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// A value indicating whether the property is constrained to fixed length values. /// Indicates whether the configuration was specified using a data annotation. @@ -311,6 +353,9 @@ public static PropertyBuilder IsFixedLength( /// /// Returns a value indicating whether the property can be configured as being fixed length or not. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// A value indicating whether the property is constrained to fixed length values. /// Indicates whether the configuration was specified using a data annotation. @@ -332,6 +377,9 @@ public static bool CanSetIsFixedLength( /// existing database. /// /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The same builder instance so that multiple calls can be chained. public static PropertyBuilder HasDefaultValueSql(this PropertyBuilder propertyBuilder) @@ -346,6 +394,9 @@ public static PropertyBuilder HasDefaultValueSql(this PropertyBuilder propertyBu /// /// Configures the default value expression for the column that the property maps to when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The SQL expression for the default value of the column. /// The same builder instance so that multiple calls can be chained. @@ -372,6 +423,9 @@ public static PropertyBuilder HasDefaultValueSql( /// existing database. /// /// + /// + /// See Database default values for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The same builder instance so that multiple calls can be chained. @@ -382,6 +436,9 @@ public static PropertyBuilder HasDefaultValueSql( /// /// Configures the default value expression for the column that the property maps to when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The SQL expression for the default value of the column. @@ -394,6 +451,9 @@ public static PropertyBuilder HasDefaultValueSql( /// /// Configures the default value expression for the column that the property maps to when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The SQL expression for the default value of the column. /// Indicates whether the configuration was specified using a data annotation. @@ -418,6 +478,9 @@ public static PropertyBuilder HasDefaultValueSql( /// /// Returns a value indicating whether the given default value expression can be set for the column. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The SQL expression for the default value of the column. /// Indicates whether the configuration was specified using a data annotation. @@ -441,6 +504,9 @@ public static bool CanSetDefaultValueSql( /// database. /// /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The same builder instance so that multiple calls can be chained. public static PropertyBuilder HasComputedColumnSql(this PropertyBuilder propertyBuilder) @@ -455,6 +521,9 @@ public static PropertyBuilder HasComputedColumnSql(this PropertyBuilder property /// /// Configures the property to map to a computed column when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The SQL expression that computes values for the column. /// The same builder instance so that multiple calls can be chained. @@ -466,6 +535,9 @@ public static PropertyBuilder HasComputedColumnSql( /// /// Configures the property to map to a computed column when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The SQL expression that computes values for the column. /// @@ -502,6 +574,9 @@ public static PropertyBuilder HasComputedColumnSql( /// database. /// /// + /// + /// See Database default values for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The same builder instance so that multiple calls can be chained. @@ -512,6 +587,9 @@ public static PropertyBuilder HasComputedColumnSql( /// /// Configures the property to map to a computed column when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The SQL expression that computes values for the column. @@ -524,6 +602,9 @@ public static PropertyBuilder HasComputedColumnSql( /// /// Configures the property to map to a computed column when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The SQL expression that computes values for the column. @@ -542,6 +623,9 @@ public static PropertyBuilder HasComputedColumnSql( /// /// Configures the property to map to a computed column when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The SQL expression that computes values for the column. /// Indicates whether the configuration was specified using a data annotation. @@ -566,6 +650,9 @@ public static PropertyBuilder HasComputedColumnSql( /// /// Configures the property to map to a computed column of the given type when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// /// If , the computed value is calculated on row modification and stored in the database like a regular column. @@ -593,6 +680,9 @@ public static PropertyBuilder HasComputedColumnSql( /// /// Returns a value indicating whether the given computed value SQL expression can be set for the column. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The SQL expression that computes values for the column. /// Indicates whether the configuration was specified using a data annotation. @@ -609,6 +699,9 @@ public static bool CanSetComputedColumnSql( /// /// Returns a value indicating whether the given computed column type can be set for the column. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// /// If , the computed value is calculated on row modification and stored in the database like a regular column. @@ -637,6 +730,9 @@ public static bool CanSetIsStoredComputedColumn( /// This can be useful when mapping EF to an existing database. /// /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The same builder instance so that multiple calls can be chained. public static PropertyBuilder HasDefaultValue(this PropertyBuilder propertyBuilder) @@ -652,6 +748,9 @@ public static PropertyBuilder HasDefaultValue(this PropertyBuilder propertyBuild /// Configures the default value for the column that the property maps /// to when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The default value of the column. /// The same builder instance so that multiple calls can be chained. @@ -677,6 +776,9 @@ public static PropertyBuilder HasDefaultValue( /// This can be useful when mapping EF to an existing database. /// /// + /// + /// See Database default values for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The same builder instance so that multiple calls can be chained. @@ -688,6 +790,9 @@ public static PropertyBuilder HasDefaultValue( /// Configures the default value for the column that the property maps /// to when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The default value of the column. @@ -700,6 +805,9 @@ public static PropertyBuilder HasDefaultValue( /// /// Configures the default value for the column that the property maps to when targeting a relational database. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The default value of the column. /// Indicates whether the configuration was specified using a data annotation. @@ -724,6 +832,9 @@ public static PropertyBuilder HasDefaultValue( /// /// Returns a value indicating whether the given value can be set as default for the column. /// + /// + /// See Database default values for more information. + /// /// The builder for the property being configured. /// The default value of the column. /// Indicates whether the configuration was specified using a data annotation. @@ -740,6 +851,9 @@ public static bool CanSetDefaultValue( /// /// Configures a comment to be applied to the column /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The comment for the column. /// The same builder instance so that multiple calls can be chained. @@ -757,6 +871,9 @@ public static PropertyBuilder HasComment( /// /// Configures a comment to be applied to the column /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the property being configured. /// The builder for the property being configured. /// The comment for the column. @@ -769,6 +886,9 @@ public static PropertyBuilder HasComment( /// /// Configures a comment to be applied to the column /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The comment for the column. /// Indicates whether the configuration was specified using a data annotation. @@ -793,6 +913,9 @@ public static PropertyBuilder HasComment( /// /// Returns a value indicating whether the given value can be set as comment for the column. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the property being configured. /// The comment for the column. /// Indicates whether the configuration was specified using a data annotation. @@ -810,6 +933,9 @@ public static bool CanSetComment( /// Configures the property to use the given collation. The database column will be created with the given /// collation, and it will be used implicitly in all collation-sensitive operations. /// + /// + /// See Database collations for more information. + /// /// The builder for the property being configured. /// The collation for the column. /// The same builder instance so that multiple calls can be chained. @@ -827,6 +953,9 @@ public static PropertyBuilder UseCollation(this PropertyBuilder propertyBuilder, /// Configures the property to use the given collation. The database column will be created with the given /// collation, and it will be used implicitly in all collation-sensitive operations. /// + /// + /// See Database collations for more information. + /// /// The builder for the property being configured. /// The collation for the column. /// The same builder instance so that multiple calls can be chained. @@ -839,6 +968,9 @@ public static PropertyBuilder UseCollation( /// Configures the property to use the given collation. The database column will be created with the given /// collation, and it will be used implicitly in all collation-sensitive operations. /// + /// + /// See Database collations for more information. + /// /// The builder for the property being configured. /// The collation. /// Indicates whether the configuration was specified using a data annotation. @@ -864,6 +996,9 @@ public static PropertyBuilder UseCollation( /// /// Returns a value indicating whether the given value can be set as the collation. /// + /// + /// See Database collations for more information. + /// /// The builder for the property being configured. /// The collation. /// Indicates whether the configuration was specified using a data annotation. diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs index 87184726308..6544ad97f2d 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Property extension methods for relational database metadata. /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalPropertyExtensions { /// diff --git a/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs b/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs index 384acc798fd..678a1f0dfe4 100644 --- a/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs @@ -42,6 +42,9 @@ public static class RelationalQueryableExtensions /// This is only typically supported by queries generated by Entity Framework Core. /// /// + /// + /// See Logging, events, and diagnostics for more information. + /// /// The query source. /// The query string for debugging. public static DbCommand CreateDbCommand(this IQueryable source) @@ -81,6 +84,10 @@ public static DbCommand CreateDbCommand(this IQueryable source) /// /// context.Blogs.FromSqlRaw("SELECT * FROM Blogs WHERE Name = @searchTerm", new SqlParameter("@searchTerm", userSuppliedSearchTerm)) /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// /// The type of the elements of . /// /// An to use as the base of the raw SQL query (typically a ). @@ -123,6 +130,10 @@ public static IQueryable FromSqlRaw( /// /// context.Blogs.FromSqlInterpolated($"SELECT * FROM Blogs WHERE Name = {userSuppliedSearchTerm}") /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// /// The type of the elements of . /// /// An to use as the base of the interpolated string SQL query (typically a ). @@ -182,6 +193,9 @@ private static FromSqlQueryRootExpression GenerateFromSqlQueryRoot( /// . /// /// + /// + /// See EF Core split queries for more information. + /// /// The type of entity being queried. /// The source query. /// A new query where collections will be loaded through single database query. @@ -215,6 +229,9 @@ internal static readonly MethodInfo AsSingleQueryMethodInfo /// . /// /// + /// + /// See EF Core split queries for more information. + /// /// The type of entity being queried. /// The source query. /// A new query where collections will be loaded through separate database queries. diff --git a/src/EFCore.Relational/Extensions/RelationalTypeMappingConfigurationBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalTypeMappingConfigurationBuilderExtensions.cs index 9e29bf5cac4..0b7f16be6e9 100644 --- a/src/EFCore.Relational/Extensions/RelationalTypeMappingConfigurationBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalTypeMappingConfigurationBuilderExtensions.cs @@ -11,12 +11,18 @@ namespace Microsoft.EntityFrameworkCore /// /// Relational database specific extension methods for . /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalTypeMappingConfigurationBuilderExtensions { /// /// Configures the data type of the column that the scalar maps to when targeting a relational database. /// This should be the complete type name, including precision, scale, length, etc. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the scalar being configured. /// The name of the data type of the column. /// The same builder instance so that multiple calls can be chained. @@ -36,6 +42,9 @@ public static TypeMappingConfigurationBuilder HasColumnType( /// Configures the data type of the column that the scalar maps to when targeting a relational database. /// This should be the complete type name, including precision, scale, length, etc. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the scalar being configured. /// The builder for the scalar being configured. /// The name of the data type of the column. @@ -48,6 +57,9 @@ public static TypeMappingConfigurationBuilder HasColumnType( /// /// Configures the scalar as capable of storing only fixed-length data, such as strings. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The builder for the scalar being configured. /// A value indicating whether the scalar is constrained to fixed length values. /// The same builder instance so that multiple configuration calls can be chained. @@ -65,6 +77,9 @@ public static TypeMappingConfigurationBuilder IsFixedLength( /// /// Configures the scalar as capable of storing only fixed-length data, such as strings. /// + /// + /// See Modeling entity types and relationships for more information. + /// /// The type of the scalar being configured. /// The builder for the scalar being configured. /// A value indicating whether the scalar is constrained to fixed length values. diff --git a/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs b/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs index 1910bf13bce..91b118ddda9 100644 --- a/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs +++ b/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs @@ -35,6 +35,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// can handle the new scope, and that it does not cause issue for services that depend on it. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class EntityFrameworkRelationalServicesBuilder : EntityFrameworkServicesBuilder { /// @@ -128,6 +132,10 @@ public EntityFrameworkRelationalServicesBuilder(IServiceCollection serviceCollec /// registered by the provider. Relational database providers must call this method as the last /// step of service registration--that is, after all provider services have been registered. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// /// This builder, such that further calls can be chained. public override EntityFrameworkServicesBuilder TryAddCoreServices() { diff --git a/src/EFCore.Relational/Infrastructure/IRelationalDbContextOptionsBuilderInfrastructure.cs b/src/EFCore.Relational/Infrastructure/IRelationalDbContextOptionsBuilderInfrastructure.cs index 91f9ecb6d44..bd4e0ce906a 100644 --- a/src/EFCore.Relational/Infrastructure/IRelationalDbContextOptionsBuilderInfrastructure.cs +++ b/src/EFCore.Relational/Infrastructure/IRelationalDbContextOptionsBuilderInfrastructure.cs @@ -8,6 +8,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// methods that are used by database provider extension methods but not intended to be called by application /// developers. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalDbContextOptionsBuilderInfrastructure { /// diff --git a/src/EFCore.Relational/Infrastructure/ModelSnapshot.cs b/src/EFCore.Relational/Infrastructure/ModelSnapshot.cs index 05fe38857ba..79adc4546b2 100644 --- a/src/EFCore.Relational/Infrastructure/ModelSnapshot.cs +++ b/src/EFCore.Relational/Infrastructure/ModelSnapshot.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// /// Base class for the snapshot of the state generated by Migrations. /// + /// + /// See Database migrations for more information. + /// public abstract class ModelSnapshot { private IModel? _model; diff --git a/src/EFCore.Relational/Infrastructure/RelationalDbContextOptionsBuilder.cs b/src/EFCore.Relational/Infrastructure/RelationalDbContextOptionsBuilder.cs index 8cce79ea7ee..8dc5c61dd2e 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalDbContextOptionsBuilder.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalDbContextOptionsBuilder.cs @@ -18,6 +18,9 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// particular relational database provider. /// /// + /// + /// See Using DbContextOptions for more information. + /// public abstract class RelationalDbContextOptionsBuilder : IRelationalDbContextOptionsBuilderInfrastructure where TBuilder : RelationalDbContextOptionsBuilder where TExtension : RelationalOptionsExtension, new() @@ -46,6 +49,9 @@ DbContextOptionsBuilder IRelationalDbContextOptionsBuilderInfrastructure.Options /// Configures the maximum number of statements that will be included in commands sent to the database /// during . /// + /// + /// See Saving data with EF Core for more information. + /// /// The maximum number of statements. /// The same builder instance so that multiple calls can be chained. public virtual TBuilder MaxBatchSize(int maxBatchSize) @@ -55,6 +61,9 @@ public virtual TBuilder MaxBatchSize(int maxBatchSize) /// Configures the minimum number of statements that are needed for a multi-statement command sent to the database /// during . /// + /// + /// See Saving data with EF Core for more information. + /// /// The minimum number of statements. /// The same builder instance so that multiple calls can be chained. public virtual TBuilder MinBatchSize(int minBatchSize) @@ -64,6 +73,9 @@ public virtual TBuilder MinBatchSize(int minBatchSize) /// Configures the wait time (in seconds) before terminating the attempt to execute a command and generating an error. /// /// + /// See Connections and connection strings for more information. + /// + /// /// This sets the property on the ADO.NET provider being used. /// An is generated if value is less than 0. /// Zero (0) typically means no timeout will be applied, consult your ADO.NET provider documentation. @@ -76,6 +88,9 @@ public virtual TBuilder CommandTimeout(int? commandTimeout) /// /// Configures the assembly where migrations are maintained for this context. /// + /// + /// See Database migrations for more information. + /// /// The name of the assembly. /// The same builder instance so that multiple calls can be chained. public virtual TBuilder MigrationsAssembly(string? assemblyName) @@ -84,6 +99,9 @@ public virtual TBuilder MigrationsAssembly(string? assemblyName) /// /// Configures the name of the table used to record which migrations have been applied to the database. /// + /// + /// See Database migrations for more information. + /// /// The name of the table. /// The schema of the table. /// The same builder instance so that multiple calls can be chained. @@ -100,6 +118,9 @@ public virtual TBuilder MigrationsHistoryTable(string tableName, string? schema /// Entity Framework will use C# semantics for null values, and generate SQL to compensate for differences /// in how the database handles nulls. /// + /// + /// See Relational database null semantics for more information. + /// /// The same builder instance so that multiple calls can be chained. public virtual TBuilder UseRelationalNulls(bool useRelationalNulls = true) => WithOption(e => (TExtension)e.WithUseRelationalNulls(useRelationalNulls)); @@ -107,6 +128,9 @@ public virtual TBuilder UseRelationalNulls(bool useRelationalNulls = true) /// /// Configures the to use when loading related collections in a query. /// + /// + /// See EF Core split queries for more information. + /// /// The same builder instance so that multiple calls can be chained. public virtual TBuilder UseQuerySplittingBehavior(QuerySplittingBehavior querySplittingBehavior) => WithOption(e => (TExtension)e.WithUseQuerySplittingBehavior(querySplittingBehavior)); @@ -114,6 +138,10 @@ public virtual TBuilder UseQuerySplittingBehavior(QuerySplittingBehavior querySp /// /// Configures the context to use the provided . /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// A function that returns a new instance of an execution strategy. public virtual TBuilder ExecutionStrategy( Func getExecutionStrategy) diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelCustomizer.cs b/src/EFCore.Relational/Infrastructure/RelationalModelCustomizer.cs index b178b17fa1e..6cd4d9e5e2c 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelCustomizer.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelCustomizer.cs @@ -19,6 +19,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalModelCustomizer : ModelCustomizer { /// diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelExtensions.cs b/src/EFCore.Relational/Infrastructure/RelationalModelExtensions.cs index bddc16e85ec..a84c692b4c4 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelExtensions.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelExtensions.cs @@ -16,6 +16,10 @@ public static class RelationalModelExtensions /// /// Returns the relational service dependencies. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// /// The model. /// The name of the calling method. /// The relational service dependencies. diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelRuntimeInitializer.cs b/src/EFCore.Relational/Infrastructure/RelationalModelRuntimeInitializer.cs index e350afda1ce..d9306ff36bd 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelRuntimeInitializer.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelRuntimeInitializer.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalModelRuntimeInitializer : ModelRuntimeInitializer { /// diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs index 166e8b99063..3d06b46bb59 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalModelValidator : ModelValidator { /// diff --git a/src/EFCore.Relational/Infrastructure/RelationalOptionsExtension.cs b/src/EFCore.Relational/Infrastructure/RelationalOptionsExtension.cs index c40b165c107..d74ab367514 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalOptionsExtension.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalOptionsExtension.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Infrastructure /// methods to obtain a new instance with the option changed. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class RelationalOptionsExtension : IDbContextOptionsExtension { // NB: When adding new options, make sure to update the copy constructor below. diff --git a/src/EFCore.Relational/Metadata/Builders/CheckConstraintBuilder.cs b/src/EFCore.Relational/Metadata/Builders/CheckConstraintBuilder.cs index a373096e0c3..589000f6328 100644 --- a/src/EFCore.Relational/Metadata/Builders/CheckConstraintBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/CheckConstraintBuilder.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a check constraint. /// + /// + /// See Database check constraints for more information. + /// public class CheckConstraintBuilder : IInfrastructure { /// @@ -52,6 +55,9 @@ public virtual IMutableCheckConstraint Metadata /// /// Sets the database name of the check constraint. /// + /// + /// See Database check constraints for more information. + /// /// The database name of the check constraint. /// The same builder instance so that multiple configuration calls can be chained. public virtual CheckConstraintBuilder HasName(string name) diff --git a/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilder.cs b/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilder.cs index cbf93fd412b..facdbb79b50 100644 --- a/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilder.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a . /// + /// + /// See Database functions for more information. + /// public class DbFunctionBuilder : DbFunctionBuilderBase { /// @@ -28,6 +31,9 @@ public DbFunctionBuilder(IMutableDbFunction function) /// /// Sets the name of the database function. /// + /// + /// See Database functions for more information. + /// /// The name of the function in the database. /// The same builder instance so that multiple configuration calls can be chained. public new virtual DbFunctionBuilder HasName(string name) @@ -36,6 +42,9 @@ public DbFunctionBuilder(IMutableDbFunction function) /// /// Sets the schema of the database function. /// + /// + /// See Database functions for more information. + /// /// The schema of the function in the database. /// The same builder instance so that multiple configuration calls can be chained. public new virtual DbFunctionBuilder HasSchema(string? schema) @@ -44,6 +53,9 @@ public DbFunctionBuilder(IMutableDbFunction function) /// /// Marks whether the database function is built-in. /// + /// + /// See Database functions for more information. + /// /// The value indicating whether the database function is built-in. /// The same builder instance so that multiple configuration calls can be chained. public new virtual DbFunctionBuilder IsBuiltIn(bool builtIn = true) @@ -52,6 +64,9 @@ public DbFunctionBuilder(IMutableDbFunction function) /// /// Marks whether the database function can return null value. /// + /// + /// See Database functions for more information. + /// /// The value indicating whether the database function can return null. /// The same builder instance so that multiple configuration calls can be chained. public virtual DbFunctionBuilderBase IsNullable(bool nullable = true) @@ -64,6 +79,9 @@ public virtual DbFunctionBuilderBase IsNullable(bool nullable = true) /// /// Sets the return store type of the database function. /// + /// + /// See Database functions for more information. + /// /// The return store type of the function in the database. /// The same builder instance so that multiple configuration calls can be chained. public virtual DbFunctionBuilder HasStoreType(string? storeType) @@ -84,6 +102,9 @@ public virtual DbFunctionBuilder HasStoreType(string? storeType) /// See https://go.microsoft.com/fwlink/?linkid=852477 for more information. /// /// + /// + /// See Database functions for more information. + /// /// The translation to use. /// The same builder instance so that multiple configuration calls can be chained. public virtual DbFunctionBuilder HasTranslation(Func, SqlExpression> translation) diff --git a/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilderBase.cs b/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilderBase.cs index 30881699bac..20cb0b7669c 100644 --- a/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilderBase.cs +++ b/src/EFCore.Relational/Metadata/Builders/DbFunctionBuilderBase.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a . /// + /// + /// See Database functions for more information. + /// public abstract class DbFunctionBuilderBase : IInfrastructure { /// @@ -52,6 +55,9 @@ public virtual IMutableDbFunction Metadata /// /// Sets the name of the database function. /// + /// + /// See Database functions for more information. + /// /// The name of the function in the database. /// The same builder instance so that multiple configuration calls can be chained. public virtual DbFunctionBuilderBase HasName(string name) @@ -64,6 +70,9 @@ public virtual DbFunctionBuilderBase HasName(string name) /// /// Sets the schema of the database function. /// + /// + /// See Database functions for more information. + /// /// The schema of the function in the database. /// The same builder instance so that multiple configuration calls can be chained. public virtual DbFunctionBuilderBase HasSchema(string? schema) @@ -76,6 +85,9 @@ public virtual DbFunctionBuilderBase HasSchema(string? schema) /// /// Marks whether the database function is built-in. /// + /// + /// See Database functions for more information. + /// /// The value indicating whether the database function is built-in. /// The same builder instance so that multiple configuration calls can be chained. public virtual DbFunctionBuilderBase IsBuiltIn(bool builtIn = true) @@ -89,6 +101,9 @@ public virtual DbFunctionBuilderBase IsBuiltIn(bool builtIn = true) /// Returns an object that can be used to configure a parameter with the given name. /// If no parameter with the given name exists, then a new parameter will be added. /// + /// + /// See Database functions for more information. + /// /// The parameter name. /// The builder to use for further parameter configuration. public virtual DbFunctionParameterBuilder HasParameter(string name) diff --git a/src/EFCore.Relational/Metadata/Builders/DbFunctionParameterBuilder.cs b/src/EFCore.Relational/Metadata/Builders/DbFunctionParameterBuilder.cs index a609c8f6587..eeaa61f40e2 100644 --- a/src/EFCore.Relational/Metadata/Builders/DbFunctionParameterBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/DbFunctionParameterBuilder.cs @@ -52,6 +52,9 @@ public virtual IMutableDbFunctionParameter Metadata /// /// Sets the store type of the function parameter in the database. /// + /// + /// See Database functions for more information. + /// /// The store type of the function parameter in the database. /// The same builder instance so that further configuration calls can be chained. public virtual DbFunctionParameterBuilder HasStoreType(string? storeType) @@ -64,6 +67,9 @@ public virtual DbFunctionParameterBuilder HasStoreType(string? storeType) /// /// Indicates whether parameter propagates nullability, meaning if it's value is null the database function itself returns null. /// + /// + /// See Database functions for more information. + /// /// Value which indicates whether parameter propagates nullability. /// The same builder instance so that further configuration calls can be chained. public virtual DbFunctionParameterBuilder PropagatesNullability(bool propagatesNullability = true) diff --git a/src/EFCore.Relational/Metadata/Builders/IConventionCheckConstraintBuilder.cs b/src/EFCore.Relational/Metadata/Builders/IConventionCheckConstraintBuilder.cs index 267cb4bd763..ec7fa21236a 100644 --- a/src/EFCore.Relational/Metadata/Builders/IConventionCheckConstraintBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/IConventionCheckConstraintBuilder.cs @@ -6,6 +6,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a check constraint. /// + /// + /// See Model building conventions and + /// Database check constraints for more information. + /// public interface IConventionCheckConstraintBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionBuilder.cs b/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionBuilder.cs index 96e982cc665..53eb0e0c26c 100644 --- a/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionBuilder.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a . /// + /// + /// See Model building conventions for more information. + /// public interface IConventionDbFunctionBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionParameterBuilder.cs b/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionParameterBuilder.cs index 6c3aad27c52..45bca3295ec 100644 --- a/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionParameterBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/IConventionDbFunctionParameterBuilder.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a . /// + /// + /// See Model building conventions for more information. + /// public interface IConventionDbFunctionParameterBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore.Relational/Metadata/Builders/IConventionSequenceBuilder.cs b/src/EFCore.Relational/Metadata/Builders/IConventionSequenceBuilder.cs index efb8f0fd5e7..3ca6bcbc9a2 100644 --- a/src/EFCore.Relational/Metadata/Builders/IConventionSequenceBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/IConventionSequenceBuilder.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a . /// + /// + /// See Model building conventions for more information. + /// public interface IConventionSequenceBuilder : IConventionAnnotatableBuilder { /// diff --git a/src/EFCore.Relational/Metadata/Builders/SequenceBuilder.cs b/src/EFCore.Relational/Metadata/Builders/SequenceBuilder.cs index 80667dc8e31..a6e6b7ebbbd 100644 --- a/src/EFCore.Relational/Metadata/Builders/SequenceBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/SequenceBuilder.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders /// /// Provides a simple API for configuring a . /// + /// + /// See Database sequences for more information. + /// public class SequenceBuilder : IInfrastructure { /// @@ -43,6 +46,9 @@ public virtual IMutableSequence Metadata /// /// Sets the to increment by the given amount when generating each next value. /// + /// + /// See Database sequences for more information. + /// /// The amount to increment between values. /// The same builder so that multiple calls can be chained. public virtual SequenceBuilder IncrementsBy(int increment) @@ -55,6 +61,9 @@ public virtual SequenceBuilder IncrementsBy(int increment) /// /// Sets the to start at the given value. /// + /// + /// See Database sequences for more information. + /// /// The starting value for the sequence. /// The same builder so that multiple calls can be chained. public virtual SequenceBuilder StartsAt(long startValue) @@ -67,6 +76,9 @@ public virtual SequenceBuilder StartsAt(long startValue) /// /// Sets the maximum value for the . /// + /// + /// See Database sequences for more information. + /// /// The maximum value for the sequence. /// The same builder so that multiple calls can be chained. public virtual SequenceBuilder HasMax(long maximum) @@ -79,6 +91,9 @@ public virtual SequenceBuilder HasMax(long maximum) /// /// Sets the minimum value for the . /// + /// + /// See Database sequences for more information. + /// /// The minimum value for the sequence. /// The same builder so that multiple calls can be chained. public virtual SequenceBuilder HasMin(long minimum) @@ -92,6 +107,9 @@ public virtual SequenceBuilder HasMin(long minimum) /// Sets whether or not the sequence will start again from the beginning once /// the maximum value is reached. /// + /// + /// See Database sequences for more information. + /// /// If , then the sequence will restart when the maximum is reached. /// The same builder so that multiple calls can be chained. public virtual SequenceBuilder IsCyclic(bool cyclic = true) diff --git a/src/EFCore.Relational/Metadata/Builders/TableBuilder.cs b/src/EFCore.Relational/Metadata/Builders/TableBuilder.cs index 0bd920c7bb8..81ba0958563 100644 --- a/src/EFCore.Relational/Metadata/Builders/TableBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/TableBuilder.cs @@ -34,6 +34,9 @@ public TableBuilder(string? name, string? schema, IMutableEntityType entityType) /// /// Configures the table to be ignored by migrations. /// + /// + /// See Database migrations for more information. + /// /// A value indicating whether the table should be managed by migrations. /// The same builder instance so that multiple calls can be chained. public virtual TableBuilder ExcludeFromMigrations(bool excluded = true) diff --git a/src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs b/src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs index be8f8317cb7..b8a8f3d3e3e 100644 --- a/src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs +++ b/src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs @@ -30,6 +30,9 @@ public TableBuilder(string? name, string? schema, IMutableEntityType entityType) /// /// Configures the table to be ignored by migrations. /// + /// + /// See Database migrations for more information. + /// /// A value indicating whether the table should be managed by migrations. /// The same builder instance so that multiple calls can be chained. public new virtual TableBuilder ExcludeFromMigrations(bool excluded = true) diff --git a/src/EFCore.Relational/Metadata/Builders/TableValuedFunctionBuilder.cs b/src/EFCore.Relational/Metadata/Builders/TableValuedFunctionBuilder.cs index 875977693d2..75c37d9c565 100644 --- a/src/EFCore.Relational/Metadata/Builders/TableValuedFunctionBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/TableValuedFunctionBuilder.cs @@ -25,6 +25,9 @@ public TableValuedFunctionBuilder(IMutableDbFunction function) /// /// Sets the name of the database function. /// + /// + /// See Database functions for more information. + /// /// The name of the function in the database. /// The same builder instance so that multiple configuration calls can be chained. public new virtual TableValuedFunctionBuilder HasName(string name) @@ -33,6 +36,9 @@ public TableValuedFunctionBuilder(IMutableDbFunction function) /// /// Sets the schema of the database function. /// + /// + /// See Database functions for more information. + /// /// The schema of the function in the database. /// The same builder instance so that multiple configuration calls can be chained. public new virtual TableValuedFunctionBuilder HasSchema(string? schema) diff --git a/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs b/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs index 38c6d35e622..d7f4451e502 100644 --- a/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that ensures that the check constraints on the derived types are compatible with /// the check constraints on the base type. /// + /// + /// See Model building conventions for more information. + /// public class CheckConstraintConvention : IEntityTypeBaseTypeChangedConvention { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/DbFunctionTypeMappingConvention.cs b/src/EFCore.Relational/Metadata/Conventions/DbFunctionTypeMappingConvention.cs index 6ae517e65ea..0d75c224879 100644 --- a/src/EFCore.Relational/Metadata/Conventions/DbFunctionTypeMappingConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/DbFunctionTypeMappingConvention.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention configure type mapping for instances. /// + /// + /// See Model building conventions and + /// Database functions for more information. + /// [Obsolete("Use IModelRuntimeInitializer.Initialize instead.")] public class DbFunctionTypeMappingConvention : IModelFinalizingConvention { diff --git a/src/EFCore.Relational/Metadata/Conventions/EntityTypeHierarchyMappingConvention.cs b/src/EFCore.Relational/Metadata/Conventions/EntityTypeHierarchyMappingConvention.cs index 4eb0e66aad2..4f2fe7f217e 100644 --- a/src/EFCore.Relational/Metadata/Conventions/EntityTypeHierarchyMappingConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/EntityTypeHierarchyMappingConvention.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that removes discriminators from non-TPH entity types and unmaps the inherited properties for TPT entity types. /// + /// + /// See Model building conventions and + /// Entity type hierarchy mapping for more information. + /// public class EntityTypeHierarchyMappingConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs index 3a25619006d..488c041fa01 100644 --- a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs +++ b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs @@ -28,6 +28,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure /// The implementation does not need to be thread-safe. /// /// + /// + /// See Model building conventions for more information. + /// public abstract class RelationalConventionSetBuilder : ProviderConventionSetBuilder { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs index 02e7d426187..bc2bdc9dcef 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures column name and type for a property based on the applied . /// + /// + /// See Model building conventions for more information. + /// public class RelationalColumnAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalColumnCommentAttributeConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalColumnCommentAttributeConvention.cs index 027f97795f0..79fed0d4152 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalColumnCommentAttributeConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalColumnCommentAttributeConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the column comment for a property or field based on the applied . /// + /// + /// See Model building conventions for more information. + /// public class RelationalColumnCommentAttributeConvention : PropertyAttributeConventionBase { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs index 11bf62ea215..1e1cb4a0209 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs @@ -13,6 +13,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that configures model function mappings based on public static methods on the context marked with /// . /// + /// + /// See Model building conventions and + /// Database functions for more information. + /// public class RelationalDbFunctionAttributeConvention : IModelInitializedConvention, IModelFinalizingConvention { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs index 6ada4be15be..f2c5824ebda 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the maximum object identifier length supported by the database. /// + /// + /// See Model building conventions for more information. + /// public class RelationalMaxIdentifierLengthConvention : IModelInitializedConvention { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalModelConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalModelConvention.cs index 0fe106e55bd..016abf44629 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalModelConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalModelConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that precomputes a relational model. /// + /// + /// See Model building conventions for more information. + /// [Obsolete("Use IModelRuntimeInitializer.Initialize instead.")] public class RelationalModelConvention : IModelFinalizedConvention { diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalRuntimeModelConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalRuntimeModelConvention.cs index a959d3b1cea..f947a6120ab 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalRuntimeModelConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalRuntimeModelConvention.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention that creates an optimized copy of the mutable model. This convention is typically /// implemented by database providers to update provider annotations when creating a read-only model. /// + /// + /// See Model building conventions for more information. + /// public class RelationalRuntimeModelConvention : RuntimeModelConvention { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalTableAttributeConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalTableAttributeConvention.cs index 2bbca136587..1613957eedc 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalTableAttributeConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalTableAttributeConvention.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the table name and schema for entity types based on the applied . /// + /// + /// See Model building conventions for more information. + /// public class RelationalTableAttributeConvention : EntityTypeAttributeConventionBase { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalTableCommentAttributeConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalTableCommentAttributeConvention.cs index 21921109e5f..87db51fda84 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalTableCommentAttributeConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalTableCommentAttributeConvention.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the table comment for an entity type based on the applied . /// + /// + /// See Model building conventions for more information. + /// public class RelationalTableCommentAttributeConvention : EntityTypeAttributeConventionBase { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalValueGenerationConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalValueGenerationConvention.cs index 91ebbcc24a6..32a2a8b523b 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalValueGenerationConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalValueGenerationConvention.cs @@ -13,6 +13,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// part of the primary key and not part of any foreign keys or were configured to have a database default value. /// It also configures properties as if they were configured as computed columns. /// + /// + /// See Model building conventions and + /// EF Core value generation for more information. + /// public class RelationalValueGenerationConvention : ValueGenerationConvention, IPropertyAnnotationChangedConvention, diff --git a/src/EFCore.Relational/Metadata/Conventions/SequenceUniquificationConvention.cs b/src/EFCore.Relational/Metadata/Conventions/SequenceUniquificationConvention.cs index 6a601da2c09..dcbe6f032ed 100644 --- a/src/EFCore.Relational/Metadata/Conventions/SequenceUniquificationConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/SequenceUniquificationConvention.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// A convention which ensures that all sequences in the model have unique names /// within a schema when truncated to the maximum identifier length for the model. /// + /// + /// See Model building conventions and + /// Database sequences for more information. + /// public class SequenceUniquificationConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs b/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs index 9c1662e11eb..793639c3e63 100644 --- a/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that manipulates names of database objects for entity types that share a table to avoid clashes. /// + /// + /// See Model building conventions for more information. + /// public class SharedTableConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/StoreGenerationConvention.cs b/src/EFCore.Relational/Metadata/Conventions/StoreGenerationConvention.cs index ccd30038185..24b900ecc82 100644 --- a/src/EFCore.Relational/Metadata/Conventions/StoreGenerationConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/StoreGenerationConvention.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that ensures that properties aren't configured to have a default value and as computed column at the same time. /// + /// + /// See Model building conventions and + /// EF Core value generation for more information. + /// public class StoreGenerationConvention : IPropertyAnnotationChangedConvention, IModelFinalizingConvention { /// diff --git a/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs b/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs index 8138ea6e8c8..3045f4edf80 100644 --- a/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the table name based on the property name. /// + /// + /// See Model building conventions for more information. + /// public class TableNameFromDbSetConvention : IEntityTypeAddedConvention, IEntityTypeBaseTypeChangedConvention, IModelFinalizingConvention { private readonly IDictionary _sets; diff --git a/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs b/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs index 73904efa77f..fff927feccc 100644 --- a/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// creates a shadow concurrency property mapped to that column /// on the base-most entity type(s). /// + /// + /// See Model building conventions for more information. + /// public class TableSharingConcurrencyTokenConvention : IModelFinalizingConvention { private const string ConcurrencyPropertyPrefix = "_TableSharingConcurrencyTokenConvention_"; diff --git a/src/EFCore.Relational/Metadata/Conventions/TableValuedDbFunctionConvention.cs b/src/EFCore.Relational/Metadata/Conventions/TableValuedDbFunctionConvention.cs index b36dd4ac73c..552275e60ec 100644 --- a/src/EFCore.Relational/Metadata/Conventions/TableValuedDbFunctionConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/TableValuedDbFunctionConvention.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// A convention that configures the entity type to which a queryable function is mapped. /// + /// + /// See Model building conventions and + /// Database functions for more information. + /// public class TableValuedDbFunctionConvention : IModelFinalizingConvention { /// diff --git a/src/EFCore.Relational/Metadata/ICheckConstraint.cs b/src/EFCore.Relational/Metadata/ICheckConstraint.cs index cd837ba55ab..c6af468dfa2 100644 --- a/src/EFCore.Relational/Metadata/ICheckConstraint.cs +++ b/src/EFCore.Relational/Metadata/ICheckConstraint.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a check constraint on the entity type. /// + /// + /// See Database check constraints for more information. + /// public interface ICheckConstraint : IReadOnlyCheckConstraint, IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IColumn.cs b/src/EFCore.Relational/Metadata/IColumn.cs index 413f8f74631..4f8a4a8664c 100644 --- a/src/EFCore.Relational/Metadata/IColumn.cs +++ b/src/EFCore.Relational/Metadata/IColumn.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a column in a table. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IColumn : IColumnBase { /// diff --git a/src/EFCore.Relational/Metadata/IColumnBase.cs b/src/EFCore.Relational/Metadata/IColumnBase.cs index 750504cbe86..23f2ea2b59c 100644 --- a/src/EFCore.Relational/Metadata/IColumnBase.cs +++ b/src/EFCore.Relational/Metadata/IColumnBase.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a column-like object in a table-like object. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IColumnBase : IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IColumnMapping.cs b/src/EFCore.Relational/Metadata/IColumnMapping.cs index 7f0c3548871..d711876fe6c 100644 --- a/src/EFCore.Relational/Metadata/IColumnMapping.cs +++ b/src/EFCore.Relational/Metadata/IColumnMapping.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents property mapping to a column. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IColumnMapping : IColumnMappingBase { /// diff --git a/src/EFCore.Relational/Metadata/IColumnMappingBase.cs b/src/EFCore.Relational/Metadata/IColumnMappingBase.cs index 774dddcf195..df5ff858fc4 100644 --- a/src/EFCore.Relational/Metadata/IColumnMappingBase.cs +++ b/src/EFCore.Relational/Metadata/IColumnMappingBase.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents property mapping to a column-like object. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IColumnMappingBase : IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IConventionCheckConstraint.cs b/src/EFCore.Relational/Metadata/IConventionCheckConstraint.cs index e8e1c949729..4b0e60cff8c 100644 --- a/src/EFCore.Relational/Metadata/IConventionCheckConstraint.cs +++ b/src/EFCore.Relational/Metadata/IConventionCheckConstraint.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a check constraint on the entity type. /// + /// + /// See Database check constraints for more information. + /// public interface IConventionCheckConstraint : IReadOnlyCheckConstraint, IConventionAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IConventionDbFunction.cs b/src/EFCore.Relational/Metadata/IConventionDbFunction.cs index d8074ee5558..d5edba7f7fe 100644 --- a/src/EFCore.Relational/Metadata/IConventionDbFunction.cs +++ b/src/EFCore.Relational/Metadata/IConventionDbFunction.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a relational database function in a model in /// the form that can be mutated while the model is being built. /// + /// + /// See Database functions for more information. + /// public interface IConventionDbFunction : IReadOnlyDbFunction, IConventionAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IConventionDbFunctionParameter.cs b/src/EFCore.Relational/Metadata/IConventionDbFunctionParameter.cs index 922f4ae4d16..075247136b8 100644 --- a/src/EFCore.Relational/Metadata/IConventionDbFunctionParameter.cs +++ b/src/EFCore.Relational/Metadata/IConventionDbFunctionParameter.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a parameter. /// + /// + /// See Database functions for more information. + /// public interface IConventionDbFunctionParameter : IConventionAnnotatable, IReadOnlyDbFunctionParameter { /// diff --git a/src/EFCore.Relational/Metadata/IConventionSequence.cs b/src/EFCore.Relational/Metadata/IConventionSequence.cs index 7bad67cf6c7..9751ffe5c0e 100644 --- a/src/EFCore.Relational/Metadata/IConventionSequence.cs +++ b/src/EFCore.Relational/Metadata/IConventionSequence.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a database sequence in the model in a form that /// can be mutated while building the model. /// + /// + /// See Database sequences for more information. + /// public interface IConventionSequence : IReadOnlySequence, IConventionAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IDbFunction.cs b/src/EFCore.Relational/Metadata/IDbFunction.cs index 4c9850adfac..8b383342eba 100644 --- a/src/EFCore.Relational/Metadata/IDbFunction.cs +++ b/src/EFCore.Relational/Metadata/IDbFunction.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a relational database function in a model. /// + /// + /// See Database functions for more information. + /// public interface IDbFunction : IReadOnlyDbFunction, IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IDbFunctionParameter.cs b/src/EFCore.Relational/Metadata/IDbFunctionParameter.cs index 0d3079db1f0..5a02633c838 100644 --- a/src/EFCore.Relational/Metadata/IDbFunctionParameter.cs +++ b/src/EFCore.Relational/Metadata/IDbFunctionParameter.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a function parameter. /// + /// + /// See Database functions for more information. + /// public interface IDbFunctionParameter : IReadOnlyDbFunctionParameter, IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IForeignKeyConstraint.cs b/src/EFCore.Relational/Metadata/IForeignKeyConstraint.cs index 91fcb042830..0871b00df26 100644 --- a/src/EFCore.Relational/Metadata/IForeignKeyConstraint.cs +++ b/src/EFCore.Relational/Metadata/IForeignKeyConstraint.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a foreign key constraint. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IForeignKeyConstraint : IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IFunctionColumn.cs b/src/EFCore.Relational/Metadata/IFunctionColumn.cs index e10ce0e0e7c..74e584d7e4e 100644 --- a/src/EFCore.Relational/Metadata/IFunctionColumn.cs +++ b/src/EFCore.Relational/Metadata/IFunctionColumn.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a column in a table-valued function. /// + /// + /// See Database functions for more information. + /// public interface IFunctionColumn : IColumnBase { /// diff --git a/src/EFCore.Relational/Metadata/IFunctionColumnMapping.cs b/src/EFCore.Relational/Metadata/IFunctionColumnMapping.cs index 688f8bad82b..464083ad57f 100644 --- a/src/EFCore.Relational/Metadata/IFunctionColumnMapping.cs +++ b/src/EFCore.Relational/Metadata/IFunctionColumnMapping.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents property mapping to a column. /// + /// + /// See Database functions for more information. + /// public interface IFunctionColumnMapping : IColumnMappingBase { /// diff --git a/src/EFCore.Relational/Metadata/IFunctionMapping.cs b/src/EFCore.Relational/Metadata/IFunctionMapping.cs index 66128cf816f..d57db2d93e7 100644 --- a/src/EFCore.Relational/Metadata/IFunctionMapping.cs +++ b/src/EFCore.Relational/Metadata/IFunctionMapping.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents entity type mapping to a function. /// + /// + /// See Database functions for more information. + /// public interface IFunctionMapping : ITableMappingBase { /// diff --git a/src/EFCore.Relational/Metadata/IMutableCheckConstraint.cs b/src/EFCore.Relational/Metadata/IMutableCheckConstraint.cs index abb829190f2..1296a82f46e 100644 --- a/src/EFCore.Relational/Metadata/IMutableCheckConstraint.cs +++ b/src/EFCore.Relational/Metadata/IMutableCheckConstraint.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a check constraint on the entity type. /// + /// + /// See Database check constraints for more information. + /// public interface IMutableCheckConstraint : IReadOnlyCheckConstraint, IMutableAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IMutableDbFunction.cs b/src/EFCore.Relational/Metadata/IMutableDbFunction.cs index 66672ae2ff9..41ce5753836 100644 --- a/src/EFCore.Relational/Metadata/IMutableDbFunction.cs +++ b/src/EFCore.Relational/Metadata/IMutableDbFunction.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Represents a relational database function in an model in /// the form that can be mutated while the model is being built. /// + /// + /// See Database functions for more information. + /// public interface IMutableDbFunction : IReadOnlyDbFunction, IMutableAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IMutableDbFunctionParameter.cs b/src/EFCore.Relational/Metadata/IMutableDbFunctionParameter.cs index 476a5c656a4..665b1568537 100644 --- a/src/EFCore.Relational/Metadata/IMutableDbFunctionParameter.cs +++ b/src/EFCore.Relational/Metadata/IMutableDbFunctionParameter.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a parameter. /// + /// + /// See Database functions for more information. + /// public interface IMutableDbFunctionParameter : IReadOnlyDbFunctionParameter, IMutableAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IMutableSequence.cs b/src/EFCore.Relational/Metadata/IMutableSequence.cs index 41c2c08515c..35c606ab3ae 100644 --- a/src/EFCore.Relational/Metadata/IMutableSequence.cs +++ b/src/EFCore.Relational/Metadata/IMutableSequence.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a database sequence in the model. /// + /// + /// See Database sequences for more information. + /// public interface IMutableSequence : IReadOnlySequence, IMutableAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IPrimaryKeyConstraint.cs b/src/EFCore.Relational/Metadata/IPrimaryKeyConstraint.cs index 6c54a4d6680..6219413ae1a 100644 --- a/src/EFCore.Relational/Metadata/IPrimaryKeyConstraint.cs +++ b/src/EFCore.Relational/Metadata/IPrimaryKeyConstraint.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a primary key constraint. /// + /// + /// See Keys for more information. + /// public interface IPrimaryKeyConstraint : IUniqueConstraint { } diff --git a/src/EFCore.Relational/Metadata/IReadOnlyCheckConstraint.cs b/src/EFCore.Relational/Metadata/IReadOnlyCheckConstraint.cs index 657be9424d0..7b43c061a58 100644 --- a/src/EFCore.Relational/Metadata/IReadOnlyCheckConstraint.cs +++ b/src/EFCore.Relational/Metadata/IReadOnlyCheckConstraint.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a check constraint on the entity type. /// + /// + /// See Database check constraints for more information. + /// public interface IReadOnlyCheckConstraint : IReadOnlyAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IReadOnlyDbFunction.cs b/src/EFCore.Relational/Metadata/IReadOnlyDbFunction.cs index 72261b75c77..fe30e8b52ce 100644 --- a/src/EFCore.Relational/Metadata/IReadOnlyDbFunction.cs +++ b/src/EFCore.Relational/Metadata/IReadOnlyDbFunction.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a relational database function in a model. /// + /// + /// See Database functions for more information. + /// public interface IReadOnlyDbFunction : IReadOnlyAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IReadOnlyDbFunctionParameter.cs b/src/EFCore.Relational/Metadata/IReadOnlyDbFunctionParameter.cs index 83a453ac7f8..cc01330fd7b 100644 --- a/src/EFCore.Relational/Metadata/IReadOnlyDbFunctionParameter.cs +++ b/src/EFCore.Relational/Metadata/IReadOnlyDbFunctionParameter.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a function parameter. /// + /// + /// See Database functions for more information. + /// public interface IReadOnlyDbFunctionParameter : IReadOnlyAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IReadOnlySequence.cs b/src/EFCore.Relational/Metadata/IReadOnlySequence.cs index f7093d075c0..4a5aaa78278 100644 --- a/src/EFCore.Relational/Metadata/IReadOnlySequence.cs +++ b/src/EFCore.Relational/Metadata/IReadOnlySequence.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a database sequence in the model. /// + /// + /// See Database sequences for more information. + /// public interface IReadOnlySequence : IReadOnlyAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IRelationalAnnotationProvider.cs b/src/EFCore.Relational/Metadata/IRelationalAnnotationProvider.cs index dafa445e409..5c557b37214 100644 --- a/src/EFCore.Relational/Metadata/IRelationalAnnotationProvider.cs +++ b/src/EFCore.Relational/Metadata/IRelationalAnnotationProvider.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalAnnotationProvider { /// diff --git a/src/EFCore.Relational/Metadata/IRelationalModel.cs b/src/EFCore.Relational/Metadata/IRelationalModel.cs index dd476f77d92..8a9059b8d75 100644 --- a/src/EFCore.Relational/Metadata/IRelationalModel.cs +++ b/src/EFCore.Relational/Metadata/IRelationalModel.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a relational database. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IRelationalModel : IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/ISequence.cs b/src/EFCore.Relational/Metadata/ISequence.cs index c45f388e81d..7bc21f5f733 100644 --- a/src/EFCore.Relational/Metadata/ISequence.cs +++ b/src/EFCore.Relational/Metadata/ISequence.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a database sequence in the model. /// + /// + /// See Database sequences for more information. + /// public interface ISequence : IReadOnlySequence, IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/ISqlQuery.cs b/src/EFCore.Relational/Metadata/ISqlQuery.cs index e0000ef501e..18d93b816e4 100644 --- a/src/EFCore.Relational/Metadata/ISqlQuery.cs +++ b/src/EFCore.Relational/Metadata/ISqlQuery.cs @@ -11,6 +11,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a SQL query string. /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// public interface ISqlQuery : ITableBase { /// diff --git a/src/EFCore.Relational/Metadata/ISqlQueryColumn.cs b/src/EFCore.Relational/Metadata/ISqlQueryColumn.cs index 2ba280b8571..45ac5e552c2 100644 --- a/src/EFCore.Relational/Metadata/ISqlQueryColumn.cs +++ b/src/EFCore.Relational/Metadata/ISqlQueryColumn.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a column in a SQL query. /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// public interface ISqlQueryColumn : IColumnBase { /// diff --git a/src/EFCore.Relational/Metadata/ISqlQueryColumnMapping.cs b/src/EFCore.Relational/Metadata/ISqlQueryColumnMapping.cs index 2c7b7afc2ae..2b2d0c19609 100644 --- a/src/EFCore.Relational/Metadata/ISqlQueryColumnMapping.cs +++ b/src/EFCore.Relational/Metadata/ISqlQueryColumnMapping.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents property mapping to a SQL query column. /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// public interface ISqlQueryColumnMapping : IColumnMappingBase { /// diff --git a/src/EFCore.Relational/Metadata/ISqlQueryMapping.cs b/src/EFCore.Relational/Metadata/ISqlQueryMapping.cs index 4ad8b418d6c..141c9e14f1e 100644 --- a/src/EFCore.Relational/Metadata/ISqlQueryMapping.cs +++ b/src/EFCore.Relational/Metadata/ISqlQueryMapping.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents entity type mapping to a SQL query. /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// public interface ISqlQueryMapping : ITableMappingBase { /// diff --git a/src/EFCore.Relational/Metadata/IStoreFunction.cs b/src/EFCore.Relational/Metadata/IStoreFunction.cs index 8b7a15a0d74..770e30e1183 100644 --- a/src/EFCore.Relational/Metadata/IStoreFunction.cs +++ b/src/EFCore.Relational/Metadata/IStoreFunction.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a function in the database. /// + /// + /// See Database functions for more information. + /// public interface IStoreFunction : ITableBase { /// diff --git a/src/EFCore.Relational/Metadata/IStoreFunctionParameter.cs b/src/EFCore.Relational/Metadata/IStoreFunctionParameter.cs index 34faaecfe28..185634c3ec8 100644 --- a/src/EFCore.Relational/Metadata/IStoreFunctionParameter.cs +++ b/src/EFCore.Relational/Metadata/IStoreFunctionParameter.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a parameter. /// + /// + /// See Database functions for more information. + /// public interface IStoreFunctionParameter : IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/ITable.cs b/src/EFCore.Relational/Metadata/ITable.cs index b70c017782a..c74193e90dd 100644 --- a/src/EFCore.Relational/Metadata/ITable.cs +++ b/src/EFCore.Relational/Metadata/ITable.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Text; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata @@ -13,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a table in the database. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface ITable : ITableBase { /// diff --git a/src/EFCore.Relational/Metadata/ITableBase.cs b/src/EFCore.Relational/Metadata/ITableBase.cs index 0c2eb256284..54faa704169 100644 --- a/src/EFCore.Relational/Metadata/ITableBase.cs +++ b/src/EFCore.Relational/Metadata/ITableBase.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a table-like object in the database. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface ITableBase : IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/ITableIndex.cs b/src/EFCore.Relational/Metadata/ITableIndex.cs index 6baa700b501..5a8d30f5bc4 100644 --- a/src/EFCore.Relational/Metadata/ITableIndex.cs +++ b/src/EFCore.Relational/Metadata/ITableIndex.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a table index. /// + /// + /// See Indexes for more information. + /// public interface ITableIndex : IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/ITableMapping.cs b/src/EFCore.Relational/Metadata/ITableMapping.cs index 8db7261e51a..28a6d6ae707 100644 --- a/src/EFCore.Relational/Metadata/ITableMapping.cs +++ b/src/EFCore.Relational/Metadata/ITableMapping.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents entity type mapping to a table. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface ITableMapping : ITableMappingBase { /// diff --git a/src/EFCore.Relational/Metadata/ITableMappingBase.cs b/src/EFCore.Relational/Metadata/ITableMappingBase.cs index 8056a5bcf12..c1a640aa214 100644 --- a/src/EFCore.Relational/Metadata/ITableMappingBase.cs +++ b/src/EFCore.Relational/Metadata/ITableMappingBase.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents entity type mapping to a table-like object. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface ITableMappingBase : IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IUniqueConstraint.cs b/src/EFCore.Relational/Metadata/IUniqueConstraint.cs index ff23acf276e..4fd25cf8cbe 100644 --- a/src/EFCore.Relational/Metadata/IUniqueConstraint.cs +++ b/src/EFCore.Relational/Metadata/IUniqueConstraint.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a unique constraint. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IUniqueConstraint : IAnnotatable { /// diff --git a/src/EFCore.Relational/Metadata/IView.cs b/src/EFCore.Relational/Metadata/IView.cs index abae909f0e2..ef4bd8383d7 100644 --- a/src/EFCore.Relational/Metadata/IView.cs +++ b/src/EFCore.Relational/Metadata/IView.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a view in the database. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IView : ITableBase { /// diff --git a/src/EFCore.Relational/Metadata/IViewColumn.cs b/src/EFCore.Relational/Metadata/IViewColumn.cs index 4f225f1bfcc..9ecd8ab22f3 100644 --- a/src/EFCore.Relational/Metadata/IViewColumn.cs +++ b/src/EFCore.Relational/Metadata/IViewColumn.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a column in a view. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IViewColumn : IColumnBase { /// diff --git a/src/EFCore.Relational/Metadata/IViewColumnMapping.cs b/src/EFCore.Relational/Metadata/IViewColumnMapping.cs index 84ff25c9f5a..373c44cf3e5 100644 --- a/src/EFCore.Relational/Metadata/IViewColumnMapping.cs +++ b/src/EFCore.Relational/Metadata/IViewColumnMapping.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents property mapping to a column. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IViewColumnMapping : IColumnMappingBase { /// diff --git a/src/EFCore.Relational/Metadata/IViewMapping.cs b/src/EFCore.Relational/Metadata/IViewMapping.cs index 9bacb63a51a..d56537ab10f 100644 --- a/src/EFCore.Relational/Metadata/IViewMapping.cs +++ b/src/EFCore.Relational/Metadata/IViewMapping.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents entity type mapping to a view. /// + /// + /// See Modeling entity types and relationships for more information. + /// public interface IViewMapping : ITableMappingBase { /// diff --git a/src/EFCore.Relational/Metadata/RelationalAnnotationNames.cs b/src/EFCore.Relational/Metadata/RelationalAnnotationNames.cs index eca1b00e452..fc3ba33ed38 100644 --- a/src/EFCore.Relational/Metadata/RelationalAnnotationNames.cs +++ b/src/EFCore.Relational/Metadata/RelationalAnnotationNames.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// Names for well-known relational model annotations. Applications should not use these names /// directly, but should instead use the extension methods on metadata objects. /// + /// + /// See Modeling entity types and relationships for more information. + /// public static class RelationalAnnotationNames { /// diff --git a/src/EFCore.Relational/Metadata/RelationalAnnotationProvider.cs b/src/EFCore.Relational/Metadata/RelationalAnnotationProvider.cs index b7212b06c4d..75cc7ad08d4 100644 --- a/src/EFCore.Relational/Metadata/RelationalAnnotationProvider.cs +++ b/src/EFCore.Relational/Metadata/RelationalAnnotationProvider.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// This service cannot depend on services registered as . /// /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RelationalAnnotationProvider : IRelationalAnnotationProvider { /// diff --git a/src/EFCore.Relational/Metadata/RuntimeDbFunction.cs b/src/EFCore.Relational/Metadata/RuntimeDbFunction.cs index 6240b5d9d58..6f8dd82a5c9 100644 --- a/src/EFCore.Relational/Metadata/RuntimeDbFunction.cs +++ b/src/EFCore.Relational/Metadata/RuntimeDbFunction.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a relational database function in a model. /// + /// + /// See Database functions for more information. + /// public class RuntimeDbFunction : AnnotatableBase, IRuntimeDbFunction { private readonly List _parameters = new(); diff --git a/src/EFCore.Relational/Metadata/RuntimeDbFunctionParameter.cs b/src/EFCore.Relational/Metadata/RuntimeDbFunctionParameter.cs index 9dbf094a778..f3564369984 100644 --- a/src/EFCore.Relational/Metadata/RuntimeDbFunctionParameter.cs +++ b/src/EFCore.Relational/Metadata/RuntimeDbFunctionParameter.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a function parameter. /// + /// + /// See Database functions for more information. + /// public class RuntimeDbFunctionParameter : AnnotatableBase, IRuntimeDbFunctionParameter { private readonly string _name; diff --git a/src/EFCore.Relational/Metadata/RuntimeRelationalPropertyOverrides.cs b/src/EFCore.Relational/Metadata/RuntimeRelationalPropertyOverrides.cs index 1df7f330414..aec39484e29 100644 --- a/src/EFCore.Relational/Metadata/RuntimeRelationalPropertyOverrides.cs +++ b/src/EFCore.Relational/Metadata/RuntimeRelationalPropertyOverrides.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents property facet overrides for a particular table-like store object. /// + /// + /// See Modeling entity types and relationships for more information. + /// public class RuntimeRelationalPropertyOverrides : AnnotatableBase, IRelationalPropertyOverrides { /// diff --git a/src/EFCore.Relational/Metadata/RuntimeSequence.cs b/src/EFCore.Relational/Metadata/RuntimeSequence.cs index 88bd1f37495..406418f89b1 100644 --- a/src/EFCore.Relational/Metadata/RuntimeSequence.cs +++ b/src/EFCore.Relational/Metadata/RuntimeSequence.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Represents a database sequence in the model. /// + /// + /// See Database sequences for more information. + /// public class RuntimeSequence : AnnotatableBase, ISequence { private readonly string? _schema; diff --git a/src/EFCore.Relational/Metadata/SqlQueryExtensions.cs b/src/EFCore.Relational/Metadata/SqlQueryExtensions.cs index 5358a1981e5..83eb2024704 100644 --- a/src/EFCore.Relational/Metadata/SqlQueryExtensions.cs +++ b/src/EFCore.Relational/Metadata/SqlQueryExtensions.cs @@ -8,6 +8,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// Extension methods for . /// + /// + /// See Executing raw SQL commands with EF Core + /// for more information. + /// public static class SqlQueryExtensions { /// diff --git a/src/EFCore.Relational/Metadata/StoreObjectIdentifier.cs b/src/EFCore.Relational/Metadata/StoreObjectIdentifier.cs index 9413fe12b98..4eb4f3dbf2a 100644 --- a/src/EFCore.Relational/Metadata/StoreObjectIdentifier.cs +++ b/src/EFCore.Relational/Metadata/StoreObjectIdentifier.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// A type that represents the id of a store object /// + /// + /// See Modeling entity types and relationships for more information. + /// public readonly struct StoreObjectIdentifier : IComparable, IEquatable { private StoreObjectIdentifier(StoreObjectType storeObjectType, string name, string? schema = null) diff --git a/src/EFCore.Relational/Metadata/StoreObjectType.cs b/src/EFCore.Relational/Metadata/StoreObjectType.cs index d95257f10dc..53891f0cf70 100644 --- a/src/EFCore.Relational/Metadata/StoreObjectType.cs +++ b/src/EFCore.Relational/Metadata/StoreObjectType.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata /// /// The table-like store object type. /// + /// + /// See Modeling entity types and relationships for more information. + /// public enum StoreObjectType { /// diff --git a/src/EFCore.Relational/Migrations/HistoryRepository.cs b/src/EFCore.Relational/Migrations/HistoryRepository.cs index 8b1fa775fb3..fc764f86d42 100644 --- a/src/EFCore.Relational/Migrations/HistoryRepository.cs +++ b/src/EFCore.Relational/Migrations/HistoryRepository.cs @@ -33,6 +33,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation does not need to be thread-safe. /// /// + /// + /// See Database migrations for more information. + /// // TODO: Leverage query pipeline for GetAppliedMigrations // TODO: Leverage update pipeline for GetInsertScript & GetDeleteScript public abstract class HistoryRepository : IHistoryRepository diff --git a/src/EFCore.Relational/Migrations/HistoryRow.cs b/src/EFCore.Relational/Migrations/HistoryRow.cs index 307bbb8248e..b81c71d6579 100644 --- a/src/EFCore.Relational/Migrations/HistoryRow.cs +++ b/src/EFCore.Relational/Migrations/HistoryRow.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// /// An entity type that represents a row in the Migrations history table. /// + /// + /// See Database migrations for more information. + /// public class HistoryRow { /// diff --git a/src/EFCore.Relational/Migrations/IHistoryRepository.cs b/src/EFCore.Relational/Migrations/IHistoryRepository.cs index f224cf703f1..66a23ffd054 100644 --- a/src/EFCore.Relational/Migrations/IHistoryRepository.cs +++ b/src/EFCore.Relational/Migrations/IHistoryRepository.cs @@ -24,6 +24,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation does not need to be thread-safe. /// /// + /// + /// See Database migrations for more information. + /// public interface IHistoryRepository { /// diff --git a/src/EFCore.Relational/Migrations/IMigrationCommandExecutor.cs b/src/EFCore.Relational/Migrations/IMigrationCommandExecutor.cs index 80b91b2ded0..ba0268aabad 100644 --- a/src/EFCore.Relational/Migrations/IMigrationCommandExecutor.cs +++ b/src/EFCore.Relational/Migrations/IMigrationCommandExecutor.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// This service cannot depend on services registered as . /// /// + /// + /// See Database migrations for more information. + /// public interface IMigrationCommandExecutor { /// diff --git a/src/EFCore.Relational/Migrations/IMigrationsAnnotationProvider.cs b/src/EFCore.Relational/Migrations/IMigrationsAnnotationProvider.cs index 2afb292c394..beaac1266c1 100644 --- a/src/EFCore.Relational/Migrations/IMigrationsAnnotationProvider.cs +++ b/src/EFCore.Relational/Migrations/IMigrationsAnnotationProvider.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// This service cannot depend on services registered as . /// /// + /// + /// See Database migrations for more information. + /// public interface IMigrationsAnnotationProvider { /// diff --git a/src/EFCore.Relational/Migrations/IMigrationsAssembly.cs b/src/EFCore.Relational/Migrations/IMigrationsAssembly.cs index e92d2498f2e..49117e7a007 100644 --- a/src/EFCore.Relational/Migrations/IMigrationsAssembly.cs +++ b/src/EFCore.Relational/Migrations/IMigrationsAssembly.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation does not need to be thread-safe. /// /// + /// + /// See Database migrations for more information. + /// public interface IMigrationsAssembly { /// diff --git a/src/EFCore.Relational/Migrations/IMigrationsIdGenerator.cs b/src/EFCore.Relational/Migrations/IMigrationsIdGenerator.cs index d427dd746eb..1a09867153e 100644 --- a/src/EFCore.Relational/Migrations/IMigrationsIdGenerator.cs +++ b/src/EFCore.Relational/Migrations/IMigrationsIdGenerator.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// This service cannot depend on services registered as . /// /// + /// + /// See Database migrations for more information. + /// public interface IMigrationsIdGenerator { /// diff --git a/src/EFCore.Relational/Migrations/IMigrationsModelDiffer.cs b/src/EFCore.Relational/Migrations/IMigrationsModelDiffer.cs index 7d63b67c656..e36cdc5bb6a 100644 --- a/src/EFCore.Relational/Migrations/IMigrationsModelDiffer.cs +++ b/src/EFCore.Relational/Migrations/IMigrationsModelDiffer.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation does not need to be thread-safe. /// /// + /// + /// See Database migrations for more information. + /// public interface IMigrationsModelDiffer { /// diff --git a/src/EFCore.Relational/Migrations/IMigrationsSqlGenerator.cs b/src/EFCore.Relational/Migrations/IMigrationsSqlGenerator.cs index 572319e0d61..388d1b2e1ce 100644 --- a/src/EFCore.Relational/Migrations/IMigrationsSqlGenerator.cs +++ b/src/EFCore.Relational/Migrations/IMigrationsSqlGenerator.cs @@ -20,6 +20,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation does not need to be thread-safe. /// /// + /// + /// See Database migrations for more information. + /// public interface IMigrationsSqlGenerator { /// diff --git a/src/EFCore.Relational/Migrations/IMigrator.cs b/src/EFCore.Relational/Migrations/IMigrator.cs index 0e99caa6a59..bb7a078a20e 100644 --- a/src/EFCore.Relational/Migrations/IMigrator.cs +++ b/src/EFCore.Relational/Migrations/IMigrator.cs @@ -20,12 +20,18 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation does not need to be thread-safe. /// /// + /// + /// See Database migrations for more information. + /// public interface IMigrator { /// /// Migrates the database to either a specified target migration or up to the latest /// migration that exists in the . /// + /// + /// See Database migrations for more information. + /// /// /// The target migration to migrate the database to, or to migrate to the latest. /// @@ -35,6 +41,9 @@ public interface IMigrator /// Migrates the database to either a specified target migration or up to the latest /// migration that exists in the . /// + /// + /// See Database migrations for more information. + /// /// /// The target migration to migrate the database to, or to migrate to the latest. /// @@ -49,6 +58,9 @@ Task MigrateAsync( /// Generates a SQL script to migrate a database either in its entirety, or starting and /// ending at specified migrations. /// + /// + /// See Database migrations for more information. + /// /// /// The migration to start from, or to start from the empty database. /// diff --git a/src/EFCore.Relational/Migrations/Migration.cs b/src/EFCore.Relational/Migrations/Migration.cs index 3d3ccd57d69..0523e3188e7 100644 --- a/src/EFCore.Relational/Migrations/Migration.cs +++ b/src/EFCore.Relational/Migrations/Migration.cs @@ -13,6 +13,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// /// A base class inherited by each EF Core migration. /// + /// + /// See Database migrations for more information. + /// public abstract class Migration { /// @@ -27,6 +30,9 @@ public abstract class Migration /// /// The that the database will map to after the migration has been applied. /// + /// + /// See Database migrations for more information. + /// public virtual IModel TargetModel { get @@ -53,6 +59,9 @@ IModel Create() /// with regard to this migration. /// /// + /// + /// See Database migrations for more information. + /// public virtual IReadOnlyList UpOperations => _upOperations ??= BuildOperations(Up); @@ -66,6 +75,9 @@ public virtual IReadOnlyList UpOperations /// state that it was in before this migration was applied. /// /// + /// + /// See Database migrations for more information. + /// public virtual IReadOnlyList DownOperations => _downOperations ??= BuildOperations(Down); @@ -78,12 +90,18 @@ public virtual IReadOnlyList DownOperations /// can be made to the database depending on the type of database being used. /// /// + /// + /// See Database migrations for more information. + /// [DisallowNull] public virtual string? ActiveProvider { get; set; } /// /// Implemented to build the . /// + /// + /// See Database migrations for more information. + /// /// The to use to build the model. protected virtual void BuildTargetModel(ModelBuilder modelBuilder) { @@ -101,6 +119,9 @@ protected virtual void BuildTargetModel(ModelBuilder modelBuilder) /// This method must be overridden in each class that inherits from . /// /// + /// + /// See Database migrations for more information. + /// /// The that will build the operations. protected abstract void Up(MigrationBuilder migrationBuilder); @@ -118,6 +139,9 @@ protected virtual void BuildTargetModel(ModelBuilder modelBuilder) /// will throw and it will not be possible to migrate in the 'down' direction. /// /// + /// + /// See Database migrations for more information. + /// /// The that will build the operations. protected virtual void Down(MigrationBuilder migrationBuilder) => throw new NotSupportedException(RelationalStrings.MigrationDownMissing); diff --git a/src/EFCore.Relational/Migrations/MigrationAttribute.cs b/src/EFCore.Relational/Migrations/MigrationAttribute.cs index 9bb18e0eb91..082d4349377 100644 --- a/src/EFCore.Relational/Migrations/MigrationAttribute.cs +++ b/src/EFCore.Relational/Migrations/MigrationAttribute.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// /// Indicates that a class is a and provides its identifier. /// + /// + /// See Database migrations for more information. + /// [AttributeUsage(AttributeTargets.Class)] public sealed class MigrationAttribute : Attribute { diff --git a/src/EFCore.Relational/Migrations/MigrationBuilder.cs b/src/EFCore.Relational/Migrations/MigrationBuilder.cs index bec36625467..725ac991eb7 100644 --- a/src/EFCore.Relational/Migrations/MigrationBuilder.cs +++ b/src/EFCore.Relational/Migrations/MigrationBuilder.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// /// A builder providing a fluentish API for building s. /// + /// + /// See Database migrations for more information. + /// public class MigrationBuilder { /// @@ -39,6 +42,9 @@ public MigrationBuilder(string? activeProvider) /// /// Builds an to add a new column to a table. /// + /// + /// See Database migrations for more information. + /// /// The CLR type that the column is mapped to. /// The column name. /// The name of the table that contains the column. @@ -120,6 +126,9 @@ public virtual OperationBuilder AddColumn( /// /// Builds an to add a new foreign key to a table. /// + /// + /// See Database migrations for more information. + /// /// The foreign key constraint name. /// The table that contains the foreign key. /// The column that is constrained. @@ -159,6 +168,9 @@ public virtual OperationBuilder AddForeignKey( /// /// Builds an to add a new composite (multi-column) foreign key to a table. /// + /// + /// See Database migrations for more information. + /// /// The foreign key constraint name. /// The table that contains the foreign key. /// The ordered list of columns that are constrained. @@ -210,6 +222,9 @@ public virtual OperationBuilder AddForeignKey( /// /// Builds an to add a new primary key to a table. /// + /// + /// See Database migrations for more information. + /// /// The primary key constraint name. /// The table that will contain the primary key. /// The column that constitutes the primary key. @@ -229,6 +244,9 @@ public virtual OperationBuilder AddPrimaryKey( /// /// Builds an to add a new composite (multi-column) primary key to a table. /// + /// + /// See Database migrations for more information. + /// /// The primary key constraint name. /// The table that will contain the primary key. /// The ordered list of columns that constitute the primary key. @@ -259,6 +277,9 @@ public virtual OperationBuilder AddPrimaryKey( /// /// Builds an to add a new unique constraint to a table. /// + /// + /// See Database migrations for more information. + /// /// The constraint name. /// The table that will contain the constraint. /// The column that is constrained. @@ -278,6 +299,9 @@ public virtual OperationBuilder AddUniqueConstrain /// /// Builds an to add a new composite (multi-column) unique constraint to a table. /// + /// + /// See Database migrations for more information. + /// /// The constraint name. /// The table that will contain the constraint. /// The ordered list of columns that are constrained. @@ -308,6 +332,9 @@ public virtual OperationBuilder AddUniqueConstrain /// /// Builds an to alter an existing column. /// + /// + /// See Database migrations for more information. + /// /// The CLR type that the column is mapped to. /// The column name. /// The name of the table that contains the column. @@ -469,6 +496,9 @@ public virtual AlterOperationBuilder AlterColumn( /// /// Builds an to alter an existing database. /// + /// + /// See Database migrations for more information. + /// /// A collation to apply to the column. /// The previous collation to apply to the column. /// A builder to allow annotations to be added to the operation. @@ -492,6 +522,9 @@ public virtual AlterOperationBuilder AlterDatabase( /// /// Builds an to alter an existing sequence. /// + /// + /// See Database migrations for more information. + /// /// The sequence name. /// The schema that contains the sequence, or to use the default schema. /// The amount to increment by when generating the next value in the sequence, defaulting to 1. @@ -541,6 +574,9 @@ public virtual AlterOperationBuilder AlterSequence( /// /// Builds an to alter an existing table. /// + /// + /// See Database migrations for more information. + /// /// The table name. /// The schema that contains the table, or to use the default schema. /// A comment to associate with the table. @@ -569,6 +605,9 @@ public virtual AlterOperationBuilder AlterTable( /// /// Builds a to create a new index. /// + /// + /// See Database migrations for more information. + /// /// The index name. /// The table that contains the index. /// The column that is indexed. @@ -594,6 +633,9 @@ public virtual OperationBuilder CreateIndex( /// /// Builds a to create a new composite (multi-column) index. /// + /// + /// See Database migrations for more information. + /// /// The index name. /// The table that contains the index. /// The ordered list of columns that are indexed. @@ -630,6 +672,9 @@ public virtual OperationBuilder CreateIndex( /// /// Builds an to ensure that a schema exists. /// + /// + /// See Database migrations for more information. + /// /// The name of the schema. /// A builder to allow annotations to be added to the operation. public virtual OperationBuilder EnsureSchema( @@ -646,6 +691,9 @@ public virtual OperationBuilder EnsureSchema( /// /// Builds a to create a new sequence. /// + /// + /// See Database migrations for more information. + /// /// The sequence name. /// The schema that contains the sequence, or to use the default schema. /// The value at which the sequence will start, defaulting to 1. @@ -667,6 +715,9 @@ public virtual OperationBuilder CreateSequence( /// /// Builds a to create a new sequence. /// + /// + /// See Database migrations for more information. + /// /// The CLR type of the values generated by the sequence. /// The sequence name. /// The schema that contains the sequence, or to use the default schema. @@ -711,6 +762,9 @@ public virtual OperationBuilder CreateSequence( /// Builds an to create a new check constraint. /// /// + /// + /// See Database migrations for more information. + /// /// The check constraint name. /// The name of the table for the check constraint. /// The constraint sql for the check constraint. @@ -727,6 +781,9 @@ public virtual OperationBuilder CreateCheckConstrai /// /// Builds an to add a new check constraint to a table. /// + /// + /// See Database migrations for more information. + /// /// The check constraint name. /// The name of the table for the check constraint. /// The constraint sql for the check constraint. @@ -755,6 +812,9 @@ public virtual OperationBuilder AddCheckConstraint( /// /// Builds a to create a new table. /// + /// + /// See Database migrations for more information. + /// /// Type of a typically anonymous type for building columns. /// The name of the table. /// @@ -809,6 +869,9 @@ public virtual CreateTableBuilder CreateTable( /// /// Builds a to drop an existing column. /// + /// + /// See Database migrations for more information. + /// /// The name of the column to drop. /// The table that contains the column. /// The schema that contains the table, or to use the default schema. @@ -835,6 +898,9 @@ public virtual OperationBuilder DropColumn( /// /// Builds a to drop an existing foreign key constraint. /// + /// + /// See Database migrations for more information. + /// /// The name of the foreign key constraint to drop. /// The table that contains the foreign key. /// The schema that contains the table, or to use the default schema. @@ -861,6 +927,9 @@ public virtual OperationBuilder DropForeignKey( /// /// Builds a to drop an existing index. /// + /// + /// See Database migrations for more information. + /// /// The name of the index to drop. /// The table that contains the index. /// The schema that contains the table, or to use the default schema. @@ -886,6 +955,9 @@ public virtual OperationBuilder DropIndex( /// /// Builds a to drop an existing primary key. /// + /// + /// See Database migrations for more information. + /// /// The name of the primary key constraint to drop. /// The table that contains the key. /// The schema that contains the table, or to use the default schema. @@ -912,6 +984,9 @@ public virtual OperationBuilder DropPrimaryKey( /// /// Builds a to drop an existing schema. /// + /// + /// See Database migrations for more information. + /// /// The name of the schema to drop. /// A builder to allow annotations to be added to the operation. public virtual OperationBuilder DropSchema( @@ -928,6 +1003,9 @@ public virtual OperationBuilder DropSchema( /// /// Builds a to drop an existing sequence. /// + /// + /// See Database migrations for more information. + /// /// The name of the sequence to drop. /// The schema that contains the sequence, or to use the default schema. /// A builder to allow annotations to be added to the operation. @@ -946,6 +1024,9 @@ public virtual OperationBuilder DropSequence( /// /// Builds a to drop an existing check constraint. /// + /// + /// See Database migrations for more information. + /// /// The name of the check constraint to drop. /// The name of the table for the check constraint to drop. /// The schema that contains the check constraint, or to use the default schema. @@ -971,6 +1052,9 @@ public virtual OperationBuilder DropCheckConstrain /// /// Builds a to drop an existing table. /// + /// + /// See Database migrations for more information. + /// /// The name of the table to drop. /// The schema that contains the table, or to use the default schema. /// A builder to allow annotations to be added to the operation. @@ -989,6 +1073,9 @@ public virtual OperationBuilder DropTable( /// /// Builds a to drop an existing unique constraint. /// + /// + /// See Database migrations for more information. + /// /// The name of the constraint to drop. /// The table that contains the constraint. /// The schema that contains the table, or to use the default schema. @@ -1015,6 +1102,9 @@ public virtual OperationBuilder DropUniqueConstra /// /// Builds a to rename an existing column. /// + /// + /// See Database migrations for more information. + /// /// The name of the column to be renamed. /// The table that contains the column. /// The new name for the column. @@ -1045,6 +1135,9 @@ public virtual OperationBuilder RenameColumn( /// /// Builds a to rename an existing index. /// + /// + /// See Database migrations for more information. + /// /// The name of the index to be renamed. /// The new name for the column. /// The table that contains the index. @@ -1075,6 +1168,9 @@ public virtual OperationBuilder RenameIndex( /// /// Builds a to rename an existing sequence. /// + /// + /// See Database migrations for more information. + /// /// The name of the sequence to be renamed. /// The schema that contains the sequence, or to use the default schema. /// The new sequence name or if only the schema has changed. @@ -1103,6 +1199,9 @@ public virtual OperationBuilder RenameSequence( /// /// Builds a to rename an existing table. /// + /// + /// See Database migrations for more information. + /// /// The name of the table to be renamed. /// The schema that contains the table, or to use the default schema. /// The new table name or if only the schema has changed. @@ -1131,6 +1230,9 @@ public virtual OperationBuilder RenameTable( /// /// Builds a to re-start an existing sequence. /// + /// + /// See Database migrations for more information. + /// /// The name of the sequence. /// The value at which the sequence will start, defaulting to 1. /// The schema that contains the sequence, or to use the default schema. @@ -1156,6 +1258,9 @@ public virtual OperationBuilder RestartSequence( /// /// Builds an to execute raw SQL. /// + /// + /// See Database migrations for more information. + /// /// The SQL string to be executed to perform the operation. /// /// Indicates whether or not transactions will be suppressed while executing the SQL. @@ -1176,6 +1281,9 @@ public virtual OperationBuilder Sql( /// /// Builds an to insert a single seed data value for a single column. /// + /// + /// See Database migrations for more information. + /// /// The table into which the data will be inserted. /// The name of the column into which the data will be inserted. /// The value to insert. @@ -1191,6 +1299,9 @@ public virtual OperationBuilder InsertData( /// /// Builds an to insert a single seed data value for a single column. /// + /// + /// See Database migrations for more information. + /// /// The table into which the data will be inserted. /// The name of the column into which the data will be inserted. /// The store type for the column into which data will be inserted. @@ -1212,6 +1323,9 @@ public virtual OperationBuilder InsertData( /// /// Builds an to insert a single row of seed data values. /// + /// + /// See Database migrations for more information. + /// /// The table into which the data will be inserted. /// The names of the columns into which the data will be inserted. /// The values to insert, one value for each column in 'columns'. @@ -1227,6 +1341,9 @@ public virtual OperationBuilder InsertData( /// /// Builds an to insert a single row of seed data values. /// + /// + /// See Database migrations for more information. + /// /// The table into which the data will be inserted. /// The names of the columns into which the data will be inserted. /// A list of store types for the columns into which data will be inserted. @@ -1244,6 +1361,9 @@ public virtual OperationBuilder InsertData( /// /// Builds an to insert multiple rows of seed data values for a single column. /// + /// + /// See Database migrations for more information. + /// /// The table into which the data will be inserted. /// The name of the column into which the data will be inserted. /// The values to insert, one value for each row. @@ -1264,6 +1384,9 @@ public virtual OperationBuilder InsertData( /// /// Builds an to insert multiple rows of seed data values for a single column. /// + /// + /// See Database migrations for more information. + /// /// The table into which the data will be inserted. /// The name of the column into which the data will be inserted. /// The store type for the column into which data will be inserted. @@ -1286,6 +1409,9 @@ public virtual OperationBuilder InsertData( /// /// Builds an to insert multiple rows of seed data values for multiple columns. /// + /// + /// See Database migrations for more information. + /// /// The table into which the data will be inserted. /// The names of the columns into which the data will be inserted. /// @@ -1304,6 +1430,9 @@ public virtual OperationBuilder InsertData( /// /// Builds an to insert multiple rows of seed data values for multiple columns. /// + /// + /// See Database migrations for more information. + /// /// The table into which the data will be inserted. /// The names of the columns into which the data will be inserted. /// A list of store types for the columns into which data will be inserted. @@ -1352,6 +1481,9 @@ private OperationBuilder InsertDataInternal( /// /// Builds a to delete a single row of seed data. /// + /// + /// See Database migrations for more information. + /// /// The table from which the data will be deleted. /// The name of the key column used to select the row to delete. /// The key value of the row to delete. @@ -1367,6 +1499,9 @@ public virtual OperationBuilder DeleteData( /// /// Builds a to delete a single row of seed data. /// + /// + /// See Database migrations for more information. + /// /// The table from which the data will be deleted. /// The name of the key column used to select the row to delete. /// @@ -1392,6 +1527,9 @@ public virtual OperationBuilder DeleteData( /// Builds a to delete a single row of seed data from /// a table with a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table from which the data will be deleted. /// The names of the key columns used to select the row to delete. /// The key values of the row to delete, one value for each column in 'keyColumns'. @@ -1412,6 +1550,9 @@ public virtual OperationBuilder DeleteData( /// Builds a to delete a single row of seed data from /// a table with a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table from which the data will be deleted. /// The names of the key columns used to select the row to delete. /// @@ -1436,6 +1577,9 @@ public virtual OperationBuilder DeleteData( /// /// Builds a to delete multiple rows of seed data. /// + /// + /// See Database migrations for more information. + /// /// The table from which the data will be deleted. /// The name of the key column used to select the row to delete. /// The key values of the rows to delete, one value per row. @@ -1455,6 +1599,9 @@ public virtual OperationBuilder DeleteData( /// /// Builds a to delete multiple rows of seed data. /// + /// + /// See Database migrations for more information. + /// /// The table from which the data will be deleted. /// The name of the key column used to select the row to delete. /// @@ -1480,6 +1627,9 @@ public virtual OperationBuilder DeleteData( /// Builds a to delete multiple rows of seed data from /// a table with a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table from which the data will be deleted. /// The names of the key columns used to select the rows to delete. /// @@ -1499,6 +1649,9 @@ public virtual OperationBuilder DeleteData( /// Builds a to delete multiple rows of seed data from /// a table with a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table from which the data will be deleted. /// The names of the key columns used to select the rows to delete. /// @@ -1549,6 +1702,9 @@ private OperationBuilder DeleteDataInternal( /// /// Builds an to update a single row of seed data. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The name of the key column used to select the row to update. /// The key value of the row to update. @@ -1574,6 +1730,9 @@ public virtual OperationBuilder UpdateData( /// /// Builds an to update a single row of seed data. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The name of the key column used to select the row to update. /// The key value of the row to update. @@ -1600,6 +1759,9 @@ public virtual OperationBuilder UpdateData( /// Builds an to update a single row of seed data for a table with /// a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The names of the key columns used to select the row to update. /// The key values of the row to update, one value for each column in 'keyColumns'. @@ -1626,6 +1788,9 @@ public virtual OperationBuilder UpdateData( /// Builds an to update a single row of seed data for a table with /// a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The names of the key columns used to select the row to update. /// The key values of the row to update, one value for each column in 'keyColumns'. @@ -1652,6 +1817,9 @@ public virtual OperationBuilder UpdateData( /// Builds an to update a single row of seed data for a table with /// a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The names of the key columns used to select the row to update. /// @@ -1685,6 +1853,9 @@ public virtual OperationBuilder UpdateData( /// /// Builds an to update multiple rows of seed data. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The name of the key column used to select the row to update. /// The key values of the rows to update, one value per row. @@ -1710,6 +1881,9 @@ public virtual OperationBuilder UpdateData( /// /// Builds an to update multiple rows of seed data. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The name of the key column used to select the row to update. /// The key values of the rows to update, one value per row. @@ -1739,6 +1913,9 @@ public virtual OperationBuilder UpdateData( /// Builds an to update multiple rows of seed data for a table with /// a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The names of the key columns used to select the rows to update. /// @@ -1768,6 +1945,9 @@ public virtual OperationBuilder UpdateData( /// Builds an to update multiple rows of seed data for a table with /// a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The names of the key columns used to select the rows to update. /// @@ -1794,6 +1974,9 @@ public virtual OperationBuilder UpdateData( /// Builds an to update multiple rows of seed data for a table with /// a composite (multi-column) key. /// + /// + /// See Database migrations for more information. + /// /// The table containing the data to be updated. /// The names of the key columns used to select the rows to update. /// diff --git a/src/EFCore.Relational/Migrations/MigrationCommand.cs b/src/EFCore.Relational/Migrations/MigrationCommand.cs index 2d9f2409614..76c8da95f5f 100644 --- a/src/EFCore.Relational/Migrations/MigrationCommand.cs +++ b/src/EFCore.Relational/Migrations/MigrationCommand.cs @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// /// Represents a command ready to be sent to the database to migrate it. /// + /// + /// See Database migrations for more information. + /// public class MigrationCommand { private readonly IRelationalCommand _relationalCommand; diff --git a/src/EFCore.Relational/Migrations/MigrationCommandListBuilder.cs b/src/EFCore.Relational/Migrations/MigrationCommandListBuilder.cs index 1afbe7c0ab6..a046a19e5ca 100644 --- a/src/EFCore.Relational/Migrations/MigrationCommandListBuilder.cs +++ b/src/EFCore.Relational/Migrations/MigrationCommandListBuilder.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// A builder for creating a list of s that can then be /// executed to migrate a database. /// + /// + /// See Database migrations for more information. + /// public class MigrationCommandListBuilder { private readonly List _commands = new(); diff --git a/src/EFCore.Relational/Migrations/MigrationsAnnotationProvider.cs b/src/EFCore.Relational/Migrations/MigrationsAnnotationProvider.cs index 2d536f2f278..f801aefb36b 100644 --- a/src/EFCore.Relational/Migrations/MigrationsAnnotationProvider.cs +++ b/src/EFCore.Relational/Migrations/MigrationsAnnotationProvider.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// This service cannot depend on services registered as . /// /// + /// + /// See Database migrations for more information. + /// public class MigrationsAnnotationProvider : IMigrationsAnnotationProvider { /// diff --git a/src/EFCore.Relational/Migrations/MigrationsAssemblyExtensions.cs b/src/EFCore.Relational/Migrations/MigrationsAssemblyExtensions.cs index 2b935cbcdae..ef36a36756f 100644 --- a/src/EFCore.Relational/Migrations/MigrationsAssemblyExtensions.cs +++ b/src/EFCore.Relational/Migrations/MigrationsAssemblyExtensions.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// /// Extension methods for . /// + /// + /// See Database migrations for more information. + /// public static class MigrationsAssemblyExtensions { /// @@ -22,6 +25,9 @@ public static class MigrationsAssemblyExtensions /// if the migration may not exist. /// /// + /// + /// See Database migrations for more information. + /// /// The assembly. /// The name or identifier to lookup. /// The identifier of the migration. diff --git a/src/EFCore.Relational/Migrations/MigrationsSqlGenerationOptions.cs b/src/EFCore.Relational/Migrations/MigrationsSqlGenerationOptions.cs index e7b38dcba3f..89af1c8ee74 100644 --- a/src/EFCore.Relational/Migrations/MigrationsSqlGenerationOptions.cs +++ b/src/EFCore.Relational/Migrations/MigrationsSqlGenerationOptions.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// /// The options to use when generating SQL for migrations. /// + /// + /// See Database migrations for more information. + /// [Flags] public enum MigrationsSqlGenerationOptions { diff --git a/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs b/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs index 8ebacab078a..1be4c4fbe03 100644 --- a/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs +++ b/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs @@ -33,6 +33,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// The implementation does not need to be thread-safe. /// /// + /// + /// See Database migrations for more information. + /// public class MigrationsSqlGenerator : IMigrationsSqlGenerator { private static readonly diff --git a/src/EFCore.Relational/Migrations/Operations/AddCheckConstraintOperation.cs b/src/EFCore.Relational/Migrations/Operations/AddCheckConstraintOperation.cs index 716538d4024..1e85bd1c825 100644 --- a/src/EFCore.Relational/Migrations/Operations/AddCheckConstraintOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/AddCheckConstraintOperation.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for creating a new check constraint. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} ADD CONSTRAINT {Name} CHECK")] public class AddCheckConstraintOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/AddColumnOperation.cs b/src/EFCore.Relational/Migrations/Operations/AddColumnOperation.cs index 1f65ab0a8bf..dce7b2945e2 100644 --- a/src/EFCore.Relational/Migrations/Operations/AddColumnOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/AddColumnOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A to add a new column. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} ADD {Name}")] public class AddColumnOperation : ColumnOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/AddForeignKeyOperation.cs b/src/EFCore.Relational/Migrations/Operations/AddForeignKeyOperation.cs index 3ae3d5686be..3aebfed2729 100644 --- a/src/EFCore.Relational/Migrations/Operations/AddForeignKeyOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/AddForeignKeyOperation.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A to add a new foreign key. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} ADD CONSTRAINT {Name} FOREIGN KEY")] public class AddForeignKeyOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/AddPrimaryKeyOperation.cs b/src/EFCore.Relational/Migrations/Operations/AddPrimaryKeyOperation.cs index 98cc283beae..002c0b723fe 100644 --- a/src/EFCore.Relational/Migrations/Operations/AddPrimaryKeyOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/AddPrimaryKeyOperation.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A to add a new foreign key. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} ADD CONSTRAINT {Name} PRIMARY KEY")] public class AddPrimaryKeyOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/AddUniqueConstraintOperation.cs b/src/EFCore.Relational/Migrations/Operations/AddUniqueConstraintOperation.cs index ad7ba3c947f..04078ba39a8 100644 --- a/src/EFCore.Relational/Migrations/Operations/AddUniqueConstraintOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/AddUniqueConstraintOperation.cs @@ -11,6 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A to add a new unique constraint. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} ADD CONSTRAINT {Name} UNIQUE")] public class AddUniqueConstraintOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/AlterColumnOperation.cs b/src/EFCore.Relational/Migrations/Operations/AlterColumnOperation.cs index 8c3c67fe5a4..ccbcf518be5 100644 --- a/src/EFCore.Relational/Migrations/Operations/AlterColumnOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/AlterColumnOperation.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A to alter an existing column. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} ALTER COLUMN {Name}")] public class AlterColumnOperation : ColumnOperation, IAlterMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/AlterDatabaseOperation.cs b/src/EFCore.Relational/Migrations/Operations/AlterDatabaseOperation.cs index adab92a4d32..967493f6976 100644 --- a/src/EFCore.Relational/Migrations/Operations/AlterDatabaseOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/AlterDatabaseOperation.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A to alter an existing database. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER DATABASE {Name}")] public class AlterDatabaseOperation : DatabaseOperation, IAlterMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/AlterSequenceOperation.cs b/src/EFCore.Relational/Migrations/Operations/AlterSequenceOperation.cs index 5ee29483149..3478cb56e58 100644 --- a/src/EFCore.Relational/Migrations/Operations/AlterSequenceOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/AlterSequenceOperation.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A to alter an existing sequence. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER SEQUENCE {Name}")] public class AlterSequenceOperation : SequenceOperation, IAlterMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/AlterTableOperation.cs b/src/EFCore.Relational/Migrations/Operations/AlterTableOperation.cs index c88df6dac9d..f5d1b4a775a 100644 --- a/src/EFCore.Relational/Migrations/Operations/AlterTableOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/AlterTableOperation.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A to alter an existing table. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Name}")] public class AlterTableOperation : TableOperation, IAlterMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/ColumnOperation.cs b/src/EFCore.Relational/Migrations/Operations/ColumnOperation.cs index 3bfee657c1a..f361dd48c52 100644 --- a/src/EFCore.Relational/Migrations/Operations/ColumnOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/ColumnOperation.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// A for operations on columns. /// See also and . /// + /// + /// See Database migrations for more information. + /// public abstract class ColumnOperation : MigrationOperation, ITableMigrationOperation { /// diff --git a/src/EFCore.Relational/Migrations/Operations/CreateIndexOperation.cs b/src/EFCore.Relational/Migrations/Operations/CreateIndexOperation.cs index b5f19dae3ad..115670f84c8 100644 --- a/src/EFCore.Relational/Migrations/Operations/CreateIndexOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/CreateIndexOperation.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for creating a new index. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("CREATE INDEX {Name} ON {Table}")] public class CreateIndexOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/CreateSequenceOperation.cs b/src/EFCore.Relational/Migrations/Operations/CreateSequenceOperation.cs index d57f4dee2f6..6f0b16f855f 100644 --- a/src/EFCore.Relational/Migrations/Operations/CreateSequenceOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/CreateSequenceOperation.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for creating a new sequence. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("CREATE SEQUENCE {Name}")] public class CreateSequenceOperation : SequenceOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/CreateTableOperation.cs b/src/EFCore.Relational/Migrations/Operations/CreateTableOperation.cs index da2f782c1b1..2927b0cad9c 100644 --- a/src/EFCore.Relational/Migrations/Operations/CreateTableOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/CreateTableOperation.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for creating a new table. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("CREATE TABLE {Name}")] public class CreateTableOperation : TableOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DatabaseOperation.cs b/src/EFCore.Relational/Migrations/Operations/DatabaseOperation.cs index 3d6dae8dac1..3a0fcca95bb 100644 --- a/src/EFCore.Relational/Migrations/Operations/DatabaseOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DatabaseOperation.cs @@ -7,6 +7,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// A for operations on databases. /// See also . /// + /// + /// See Database migrations for more information. + /// public abstract class DatabaseOperation : MigrationOperation { /// diff --git a/src/EFCore.Relational/Migrations/Operations/DeleteDataOperation.cs b/src/EFCore.Relational/Migrations/Operations/DeleteDataOperation.cs index e674fcb290e..cda89295866 100644 --- a/src/EFCore.Relational/Migrations/Operations/DeleteDataOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DeleteDataOperation.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for deleting seed data from an existing table. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("DELETE FROM {Table}")] public class DeleteDataOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DropCheckConstraintOperation.cs b/src/EFCore.Relational/Migrations/Operations/DropCheckConstraintOperation.cs index 91f8096baad..d503c9332ba 100644 --- a/src/EFCore.Relational/Migrations/Operations/DropCheckConstraintOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DropCheckConstraintOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for dropping an existing check constraint. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} DROP CONSTRAINT {Name}")] public class DropCheckConstraintOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DropColumnOperation.cs b/src/EFCore.Relational/Migrations/Operations/DropColumnOperation.cs index e1fb8f0da1b..72d84a66f34 100644 --- a/src/EFCore.Relational/Migrations/Operations/DropColumnOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DropColumnOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for dropping an existing column. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} DROP COLUMN {Name}")] public class DropColumnOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DropForeignKeyOperation.cs b/src/EFCore.Relational/Migrations/Operations/DropForeignKeyOperation.cs index cda926bcfe0..ec91d16c408 100644 --- a/src/EFCore.Relational/Migrations/Operations/DropForeignKeyOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DropForeignKeyOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for dropping an existing foreign key. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} DROP CONSTRAINT {Name}")] public class DropForeignKeyOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DropIndexOperation.cs b/src/EFCore.Relational/Migrations/Operations/DropIndexOperation.cs index 40c0d76648a..b90b07d4363 100644 --- a/src/EFCore.Relational/Migrations/Operations/DropIndexOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DropIndexOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for dropping an existing index. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("DROP INDEX {Name}")] public class DropIndexOperation : MigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DropPrimaryKeyOperation.cs b/src/EFCore.Relational/Migrations/Operations/DropPrimaryKeyOperation.cs index 3231ff6606b..1a45a4b02d8 100644 --- a/src/EFCore.Relational/Migrations/Operations/DropPrimaryKeyOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DropPrimaryKeyOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for dropping a primary key. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} DROP CONSTRAINT {Name}")] public class DropPrimaryKeyOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DropSchemaOperation.cs b/src/EFCore.Relational/Migrations/Operations/DropSchemaOperation.cs index 6822c03e7cf..18bee0308f2 100644 --- a/src/EFCore.Relational/Migrations/Operations/DropSchemaOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DropSchemaOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for dropping a schema. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("DROP SCHEMA {Name}")] public class DropSchemaOperation : MigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DropSequenceOperation.cs b/src/EFCore.Relational/Migrations/Operations/DropSequenceOperation.cs index eb278871c94..6984d6a86d1 100644 --- a/src/EFCore.Relational/Migrations/Operations/DropSequenceOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DropSequenceOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for dropping a sequence. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("DROP SEQUENCE {Name}")] public class DropSequenceOperation : MigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DropTableOperation.cs b/src/EFCore.Relational/Migrations/Operations/DropTableOperation.cs index 108b990c618..39cb9ffc593 100644 --- a/src/EFCore.Relational/Migrations/Operations/DropTableOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DropTableOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for dropping an existing table. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("DROP TABLE {Name}")] public class DropTableOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/DropUniqueConstraintOperation.cs b/src/EFCore.Relational/Migrations/Operations/DropUniqueConstraintOperation.cs index 902c33a0d0f..da142e3daf3 100644 --- a/src/EFCore.Relational/Migrations/Operations/DropUniqueConstraintOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/DropUniqueConstraintOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for dropping an existing unique constraint. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} DROP CONSTRAINT {Name}")] public class DropUniqueConstraintOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/EnsureSchemaOperation.cs b/src/EFCore.Relational/Migrations/Operations/EnsureSchemaOperation.cs index e9101e2ec03..6a2abcafc04 100644 --- a/src/EFCore.Relational/Migrations/Operations/EnsureSchemaOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/EnsureSchemaOperation.cs @@ -9,6 +9,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// A for ensuring that a schema exists. That is, the /// schema will be created if and only if it does not already exist. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("CREATE SCHEMA {Name}")] public class EnsureSchemaOperation : MigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/IAlterMigrationOperation.cs b/src/EFCore.Relational/Migrations/Operations/IAlterMigrationOperation.cs index efbadc709f2..7858e4c0967 100644 --- a/src/EFCore.Relational/Migrations/Operations/IAlterMigrationOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/IAlterMigrationOperation.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// annotations on that 'old' database object. /// /// + /// + /// See Database migrations for more information. + /// public interface IAlterMigrationOperation { /// diff --git a/src/EFCore.Relational/Migrations/Operations/ITableMigrationOperation.cs b/src/EFCore.Relational/Migrations/Operations/ITableMigrationOperation.cs index 4b0935f3870..8a04b201fda 100644 --- a/src/EFCore.Relational/Migrations/Operations/ITableMigrationOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/ITableMigrationOperation.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// Represents a migration operation on a table. /// + /// + /// See Database migrations for more information. + /// public interface ITableMigrationOperation { /// diff --git a/src/EFCore.Relational/Migrations/Operations/InsertDataOperation.cs b/src/EFCore.Relational/Migrations/Operations/InsertDataOperation.cs index 9079a2473e0..caabcaf720f 100644 --- a/src/EFCore.Relational/Migrations/Operations/InsertDataOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/InsertDataOperation.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for inserting seed data into a table. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("INSERT INTO {Table}")] public class InsertDataOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/MigrationOperation.cs b/src/EFCore.Relational/Migrations/Operations/MigrationOperation.cs index 26871276667..1f9c2e590cf 100644 --- a/src/EFCore.Relational/Migrations/Operations/MigrationOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/MigrationOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// Base class for all Migrations operations that can be performed against a database. /// + /// + /// See Database migrations for more information. + /// public abstract class MigrationOperation : Annotatable { /// diff --git a/src/EFCore.Relational/Migrations/Operations/RenameColumnOperation.cs b/src/EFCore.Relational/Migrations/Operations/RenameColumnOperation.cs index e335f17cc84..3ec9cce53ab 100644 --- a/src/EFCore.Relational/Migrations/Operations/RenameColumnOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/RenameColumnOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for renaming an existing column. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Table} RENAME COLUMN {Name} TO {NewName}")] public class RenameColumnOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/RenameIndexOperation.cs b/src/EFCore.Relational/Migrations/Operations/RenameIndexOperation.cs index 56fd1309323..1682f204d96 100644 --- a/src/EFCore.Relational/Migrations/Operations/RenameIndexOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/RenameIndexOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for renaming an existing index. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER INDEX {Name} RENAME TO {NewName}")] public class RenameIndexOperation : MigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/RenameSequenceOperation.cs b/src/EFCore.Relational/Migrations/Operations/RenameSequenceOperation.cs index 40fbc6da252..ea84871b421 100644 --- a/src/EFCore.Relational/Migrations/Operations/RenameSequenceOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/RenameSequenceOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for renaming an existing sequence. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER SEQUENCE {Name} RENAME TO {NewName}")] public class RenameSequenceOperation : MigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/RenameTableOperation.cs b/src/EFCore.Relational/Migrations/Operations/RenameTableOperation.cs index 12e74501336..b29fc07a265 100644 --- a/src/EFCore.Relational/Migrations/Operations/RenameTableOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/RenameTableOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for renaming an existing table. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER TABLE {Name} RENAME TO {NewName}")] public class RenameTableOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/RestartSequenceOperation.cs b/src/EFCore.Relational/Migrations/Operations/RestartSequenceOperation.cs index bf9d43c2647..e50c13c3db1 100644 --- a/src/EFCore.Relational/Migrations/Operations/RestartSequenceOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/RestartSequenceOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for re-starting an existing sequence. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("ALTER SEQUENCE {Name} RESTART")] public class RestartSequenceOperation : MigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/SequenceOperation.cs b/src/EFCore.Relational/Migrations/Operations/SequenceOperation.cs index 83e89128081..a9260e23380 100644 --- a/src/EFCore.Relational/Migrations/Operations/SequenceOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/SequenceOperation.cs @@ -7,6 +7,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// A for operations on sequences. /// See also and . /// + /// + /// See Database migrations for more information. + /// public abstract class SequenceOperation : MigrationOperation { /// diff --git a/src/EFCore.Relational/Migrations/Operations/SqlOperation.cs b/src/EFCore.Relational/Migrations/Operations/SqlOperation.cs index aa57831ae82..7d072c57aa8 100644 --- a/src/EFCore.Relational/Migrations/Operations/SqlOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/SqlOperation.cs @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for raw SQL commands. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("{Sql}")] public class SqlOperation : MigrationOperation { diff --git a/src/EFCore.Relational/Migrations/Operations/TableOperation.cs b/src/EFCore.Relational/Migrations/Operations/TableOperation.cs index 685cca05791..3afd7dc18da 100644 --- a/src/EFCore.Relational/Migrations/Operations/TableOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/TableOperation.cs @@ -7,6 +7,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// A for operations on tables. /// See also and . /// + /// + /// See Database migrations for more information. + /// public abstract class TableOperation : MigrationOperation, ITableMigrationOperation { /// diff --git a/src/EFCore.Relational/Migrations/Operations/UpdateDataOperation.cs b/src/EFCore.Relational/Migrations/Operations/UpdateDataOperation.cs index d4567d182a8..1b9a73ca42f 100644 --- a/src/EFCore.Relational/Migrations/Operations/UpdateDataOperation.cs +++ b/src/EFCore.Relational/Migrations/Operations/UpdateDataOperation.cs @@ -16,6 +16,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations.Operations /// /// A for updating seed data in an existing table. /// + /// + /// See Database migrations for more information. + /// [DebuggerDisplay("UPDATE {Table}")] public class UpdateDataOperation : MigrationOperation, ITableMigrationOperation { diff --git a/src/EFCore.Relational/Migrations/ReferentialAction.cs b/src/EFCore.Relational/Migrations/ReferentialAction.cs index cdac0146ef1..d008a4b312e 100644 --- a/src/EFCore.Relational/Migrations/ReferentialAction.cs +++ b/src/EFCore.Relational/Migrations/ReferentialAction.cs @@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Migrations /// Note that some database engines do not support or correctly honor every action. /// /// + /// + /// See Database migrations for more information. + /// public enum ReferentialAction { /// diff --git a/src/EFCore.Relational/QuerySplittingBehavior.cs b/src/EFCore.Relational/QuerySplittingBehavior.cs index 105d7fde478..44900144308 100644 --- a/src/EFCore.Relational/QuerySplittingBehavior.cs +++ b/src/EFCore.Relational/QuerySplittingBehavior.cs @@ -6,6 +6,9 @@ namespace Microsoft.EntityFrameworkCore /// /// Indicates how the related collections in a query should be loaded from database. /// + /// + /// See EF Core split queries for more information. + /// public enum QuerySplittingBehavior { /// diff --git a/src/EFCore.Relational/Scaffolding/DatabaseModelFactory.cs b/src/EFCore.Relational/Scaffolding/DatabaseModelFactory.cs index faf31f39f9e..3a1ff9682ea 100644 --- a/src/EFCore.Relational/Scaffolding/DatabaseModelFactory.cs +++ b/src/EFCore.Relational/Scaffolding/DatabaseModelFactory.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Base class used by database providers to reverse engineer a database into a . /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public abstract class DatabaseModelFactory : IDatabaseModelFactory { /// diff --git a/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs b/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs index 4973cfd9253..b8a900950f1 100644 --- a/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs +++ b/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Specifies which metadata to read from the database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabaseModelFactoryOptions { /// diff --git a/src/EFCore.Relational/Scaffolding/IDatabaseModelFactory.cs b/src/EFCore.Relational/Scaffolding/IDatabaseModelFactory.cs index 4af388c4b84..9c6c0e1ef02 100644 --- a/src/EFCore.Relational/Scaffolding/IDatabaseModelFactory.cs +++ b/src/EFCore.Relational/Scaffolding/IDatabaseModelFactory.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// A service typically implemented by database providers to reverse engineer a database into /// a . /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public interface IDatabaseModelFactory { /// diff --git a/src/EFCore.Relational/Scaffolding/IProviderCodeGeneratorPlugin.cs b/src/EFCore.Relational/Scaffolding/IProviderCodeGeneratorPlugin.cs index fbd62278db7..b409a7aa3d9 100644 --- a/src/EFCore.Relational/Scaffolding/IProviderCodeGeneratorPlugin.cs +++ b/src/EFCore.Relational/Scaffolding/IProviderCodeGeneratorPlugin.cs @@ -8,6 +8,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Implemented by plugins to generate code fragments for reverse engineering. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public interface IProviderCodeGeneratorPlugin { /// diff --git a/src/EFCore.Relational/Scaffolding/IProviderConfigurationCodeGenerator.cs b/src/EFCore.Relational/Scaffolding/IProviderConfigurationCodeGenerator.cs index 628f663f965..cc7cc61abcc 100644 --- a/src/EFCore.Relational/Scaffolding/IProviderConfigurationCodeGenerator.cs +++ b/src/EFCore.Relational/Scaffolding/IProviderConfigurationCodeGenerator.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// A service typically implemented by database providers to generate code fragments /// for reverse engineering. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public interface IProviderConfigurationCodeGenerator { /// diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseColumn.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseColumn.cs index a1c52abf150..da945e0fa77 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseColumn.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseColumn.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// /// A simple model for a database column used when reverse engineering an existing database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabaseColumn : Annotatable { /// diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseForeignKey.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseForeignKey.cs index 1a8e28557b3..af913fdef48 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseForeignKey.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseForeignKey.cs @@ -10,6 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// /// A simple model for a database foreign key constraint used when reverse engineering an existing database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabaseForeignKey : Annotatable { /// diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseIndex.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseIndex.cs index 4115f12ad9b..f23ead37205 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseIndex.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseIndex.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// /// A simple model for a database index used when reverse engineering an existing database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabaseIndex : Annotatable { /// diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseModel.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseModel.cs index c8347c9b51e..eea1f966bcd 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseModel.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseModel.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// /// A simple model for a database used when reverse engineering an existing database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabaseModel : Annotatable { /// diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabasePrimaryKey.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabasePrimaryKey.cs index 1ab0d1afc90..d5eb2a9c0b4 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabasePrimaryKey.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabasePrimaryKey.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// /// A simple model for a database primary key used when reverse engineering an existing database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabasePrimaryKey : Annotatable { /// diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseSequence.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseSequence.cs index 68731edc0f6..35d7b575783 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseSequence.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseSequence.cs @@ -8,6 +8,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// /// A simple model for a database sequence used when reverse engineering an existing database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabaseSequence : Annotatable { /// diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseTable.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseTable.cs index bc9ddaeccdf..4879e818bb5 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseTable.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseTable.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// /// A simple model for a database table used when reverse engineering an existing database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabaseTable : Annotatable { /// diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseUniqueConstraint.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseUniqueConstraint.cs index d71032c3fa6..a0853afacd9 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseUniqueConstraint.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseUniqueConstraint.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// /// A simple model for a database unique constraint used when reverse engineering an existing database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabaseUniqueConstraint : Annotatable { /// diff --git a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseView.cs b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseView.cs index 83cc0426fd8..b19d9b0f0bd 100644 --- a/src/EFCore.Relational/Scaffolding/Metadata/DatabaseView.cs +++ b/src/EFCore.Relational/Scaffolding/Metadata/DatabaseView.cs @@ -6,6 +6,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding.Metadata /// /// A simple model for a database view used when reverse engineering an existing database. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class DatabaseView : DatabaseTable { } diff --git a/src/EFCore.Relational/Scaffolding/ProviderCodeGenerator.cs b/src/EFCore.Relational/Scaffolding/ProviderCodeGenerator.cs index cc16ddf1e45..d1afb759580 100644 --- a/src/EFCore.Relational/Scaffolding/ProviderCodeGenerator.cs +++ b/src/EFCore.Relational/Scaffolding/ProviderCodeGenerator.cs @@ -9,6 +9,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Generates provider-specific code fragments. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public abstract class ProviderCodeGenerator : IProviderConfigurationCodeGenerator { /// diff --git a/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorPlugin.cs b/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorPlugin.cs index 9d198dfa445..99a29ad60b4 100644 --- a/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorPlugin.cs +++ b/src/EFCore.Relational/Scaffolding/ProviderCodeGeneratorPlugin.cs @@ -8,6 +8,10 @@ namespace Microsoft.EntityFrameworkCore.Scaffolding /// /// Base class used by plugins to generate code fragments for reverse engineering. /// + /// + /// See Reverse engineering (scaffolding) an existing database, and + /// EF Core design-time services for more information. + /// public class ProviderCodeGeneratorPlugin : IProviderCodeGeneratorPlugin { /// diff --git a/src/EFCore.Relational/Storage/BoolTypeMapping.cs b/src/EFCore.Relational/Storage/BoolTypeMapping.cs index ae043f976b1..291afbc5b2f 100644 --- a/src/EFCore.Relational/Storage/BoolTypeMapping.cs +++ b/src/EFCore.Relational/Storage/BoolTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class BoolTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/ByteArrayTypeMapping.cs b/src/EFCore.Relational/Storage/ByteArrayTypeMapping.cs index ac2dd0daae4..3361e26801a 100644 --- a/src/EFCore.Relational/Storage/ByteArrayTypeMapping.cs +++ b/src/EFCore.Relational/Storage/ByteArrayTypeMapping.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ByteArrayTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/ByteTypeMapping.cs b/src/EFCore.Relational/Storage/ByteTypeMapping.cs index 3e722476923..3feea676c29 100644 --- a/src/EFCore.Relational/Storage/ByteTypeMapping.cs +++ b/src/EFCore.Relational/Storage/ByteTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ByteTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/CharTypeMapping.cs b/src/EFCore.Relational/Storage/CharTypeMapping.cs index a990fe00b60..11a1ba1e119 100644 --- a/src/EFCore.Relational/Storage/CharTypeMapping.cs +++ b/src/EFCore.Relational/Storage/CharTypeMapping.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class CharTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/DateOnlyTypeMapping.cs b/src/EFCore.Relational/Storage/DateOnlyTypeMapping.cs index a684c6b4b89..1233b47c710 100644 --- a/src/EFCore.Relational/Storage/DateOnlyTypeMapping.cs +++ b/src/EFCore.Relational/Storage/DateOnlyTypeMapping.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class DateOnlyTypeMapping : RelationalTypeMapping { private const string DateOnlyFormatConst = @"{0:yyyy-MM-dd}"; diff --git a/src/EFCore.Relational/Storage/DateTimeOffsetTypeMapping.cs b/src/EFCore.Relational/Storage/DateTimeOffsetTypeMapping.cs index 9c64ef41dc0..f7db0d5dbd0 100644 --- a/src/EFCore.Relational/Storage/DateTimeOffsetTypeMapping.cs +++ b/src/EFCore.Relational/Storage/DateTimeOffsetTypeMapping.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class DateTimeOffsetTypeMapping : RelationalTypeMapping { private const string DateTimeOffsetFormatConst = @"{0:yyyy-MM-dd HH\:mm\:ss.fffffffzzz}"; diff --git a/src/EFCore.Relational/Storage/DateTimeTypeMapping.cs b/src/EFCore.Relational/Storage/DateTimeTypeMapping.cs index 4e607f40244..79b19e43e69 100644 --- a/src/EFCore.Relational/Storage/DateTimeTypeMapping.cs +++ b/src/EFCore.Relational/Storage/DateTimeTypeMapping.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class DateTimeTypeMapping : RelationalTypeMapping { private const string DateTimeFormatConst = @"{0:yyyy-MM-dd HH\:mm\:ss.fffffff}"; diff --git a/src/EFCore.Relational/Storage/DbContextTransactionExtensions.cs b/src/EFCore.Relational/Storage/DbContextTransactionExtensions.cs index 42c47ea05e1..09cb144f4aa 100644 --- a/src/EFCore.Relational/Storage/DbContextTransactionExtensions.cs +++ b/src/EFCore.Relational/Storage/DbContextTransactionExtensions.cs @@ -12,12 +12,18 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// Extension methods for . /// + /// + /// See Transactions in EF Core for more information. + /// public static class DbContextTransactionExtensions { /// /// Gets the underlying for the given transaction. Throws if the database being targeted /// is not a relational database that uses . /// + /// + /// See Transactions in EF Core for more information. + /// /// The transaction to get the from. /// The underlying . public static DbTransaction GetDbTransaction(this IDbContextTransaction dbContextTransaction) diff --git a/src/EFCore.Relational/Storage/DecimalTypeMapping.cs b/src/EFCore.Relational/Storage/DecimalTypeMapping.cs index 4be75e5573d..6a88c28e6da 100644 --- a/src/EFCore.Relational/Storage/DecimalTypeMapping.cs +++ b/src/EFCore.Relational/Storage/DecimalTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class DecimalTypeMapping : RelationalTypeMapping { private const string DecimalFormatConst = "{0:0.0###########################}"; diff --git a/src/EFCore.Relational/Storage/DoubleTypeMapping.cs b/src/EFCore.Relational/Storage/DoubleTypeMapping.cs index 808b8fe5cea..4cea4f9314a 100644 --- a/src/EFCore.Relational/Storage/DoubleTypeMapping.cs +++ b/src/EFCore.Relational/Storage/DoubleTypeMapping.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class DoubleTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/FloatTypeMapping.cs b/src/EFCore.Relational/Storage/FloatTypeMapping.cs index fcbd201b1ea..7e64931e9f4 100644 --- a/src/EFCore.Relational/Storage/FloatTypeMapping.cs +++ b/src/EFCore.Relational/Storage/FloatTypeMapping.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class FloatTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/GuidTypeMapping.cs b/src/EFCore.Relational/Storage/GuidTypeMapping.cs index fbccbb40fdb..1882ca37c90 100644 --- a/src/EFCore.Relational/Storage/GuidTypeMapping.cs +++ b/src/EFCore.Relational/Storage/GuidTypeMapping.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class GuidTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/IParameterNameGeneratorFactory.cs b/src/EFCore.Relational/Storage/IParameterNameGeneratorFactory.cs index cc447a643eb..637d0a961f2 100644 --- a/src/EFCore.Relational/Storage/IParameterNameGeneratorFactory.cs +++ b/src/EFCore.Relational/Storage/IParameterNameGeneratorFactory.cs @@ -19,6 +19,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IParameterNameGeneratorFactory { /// diff --git a/src/EFCore.Relational/Storage/IRawSqlCommandBuilder.cs b/src/EFCore.Relational/Storage/IRawSqlCommandBuilder.cs index 51d9b7bd359..5a47031981d 100644 --- a/src/EFCore.Relational/Storage/IRawSqlCommandBuilder.cs +++ b/src/EFCore.Relational/Storage/IRawSqlCommandBuilder.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRawSqlCommandBuilder { /// diff --git a/src/EFCore.Relational/Storage/IRelationalCommand.cs b/src/EFCore.Relational/Storage/IRelationalCommand.cs index 7c34c0d26d0..827572013de 100644 --- a/src/EFCore.Relational/Storage/IRelationalCommand.cs +++ b/src/EFCore.Relational/Storage/IRelationalCommand.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalCommand : IRelationalCommandTemplate { /// diff --git a/src/EFCore.Relational/Storage/IRelationalCommandBuilder.cs b/src/EFCore.Relational/Storage/IRelationalCommandBuilder.cs index 6e334c31951..367ae49a2f6 100644 --- a/src/EFCore.Relational/Storage/IRelationalCommandBuilder.cs +++ b/src/EFCore.Relational/Storage/IRelationalCommandBuilder.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalCommandBuilder { /// diff --git a/src/EFCore.Relational/Storage/IRelationalCommandBuilderFactory.cs b/src/EFCore.Relational/Storage/IRelationalCommandBuilderFactory.cs index c023a35d145..f9f120a9b6a 100644 --- a/src/EFCore.Relational/Storage/IRelationalCommandBuilderFactory.cs +++ b/src/EFCore.Relational/Storage/IRelationalCommandBuilderFactory.cs @@ -19,6 +19,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalCommandBuilderFactory { /// diff --git a/src/EFCore.Relational/Storage/IRelationalCommandTemplate.cs b/src/EFCore.Relational/Storage/IRelationalCommandTemplate.cs index 6ab2920ecc0..d313ebabe5c 100644 --- a/src/EFCore.Relational/Storage/IRelationalCommandTemplate.cs +++ b/src/EFCore.Relational/Storage/IRelationalCommandTemplate.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalCommandTemplate { /// diff --git a/src/EFCore.Relational/Storage/IRelationalConnection.cs b/src/EFCore.Relational/Storage/IRelationalConnection.cs index 75da00a6788..a5ec1ef32ed 100644 --- a/src/EFCore.Relational/Storage/IRelationalConnection.cs +++ b/src/EFCore.Relational/Storage/IRelationalConnection.cs @@ -25,6 +25,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalConnection : IRelationalTransactionManager, IDisposable, IAsyncDisposable { /// diff --git a/src/EFCore.Relational/Storage/IRelationalDatabaseCreator.cs b/src/EFCore.Relational/Storage/IRelationalDatabaseCreator.cs index e0a1f9e57b2..ddf2570876c 100644 --- a/src/EFCore.Relational/Storage/IRelationalDatabaseCreator.cs +++ b/src/EFCore.Relational/Storage/IRelationalDatabaseCreator.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalDatabaseCreator : IDatabaseCreator { /// diff --git a/src/EFCore.Relational/Storage/IRelationalDatabaseFacadeDependencies.cs b/src/EFCore.Relational/Storage/IRelationalDatabaseFacadeDependencies.cs index bb36187e9d7..81c79d5f1b8 100644 --- a/src/EFCore.Relational/Storage/IRelationalDatabaseFacadeDependencies.cs +++ b/src/EFCore.Relational/Storage/IRelationalDatabaseFacadeDependencies.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalDatabaseFacadeDependencies : IDatabaseFacadeDependencies { /// diff --git a/src/EFCore.Relational/Storage/IRelationalParameter.cs b/src/EFCore.Relational/Storage/IRelationalParameter.cs index b517de04d46..2de5a71de02 100644 --- a/src/EFCore.Relational/Storage/IRelationalParameter.cs +++ b/src/EFCore.Relational/Storage/IRelationalParameter.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalParameter { /// diff --git a/src/EFCore.Relational/Storage/IRelationalTransactionFactory.cs b/src/EFCore.Relational/Storage/IRelationalTransactionFactory.cs index 5709fac240e..4d1084b2d7e 100644 --- a/src/EFCore.Relational/Storage/IRelationalTransactionFactory.cs +++ b/src/EFCore.Relational/Storage/IRelationalTransactionFactory.cs @@ -21,6 +21,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalTransactionFactory { /// diff --git a/src/EFCore.Relational/Storage/IRelationalTransactionManager.cs b/src/EFCore.Relational/Storage/IRelationalTransactionManager.cs index 4db5d1e11fb..897916e0366 100644 --- a/src/EFCore.Relational/Storage/IRelationalTransactionManager.cs +++ b/src/EFCore.Relational/Storage/IRelationalTransactionManager.cs @@ -25,6 +25,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalTransactionManager : IDbContextTransactionManager { /// diff --git a/src/EFCore.Relational/Storage/IRelationalTypeMappingSource.cs b/src/EFCore.Relational/Storage/IRelationalTypeMappingSource.cs index d4c63a9855e..8817aa01784 100644 --- a/src/EFCore.Relational/Storage/IRelationalTypeMappingSource.cs +++ b/src/EFCore.Relational/Storage/IRelationalTypeMappingSource.cs @@ -26,6 +26,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalTypeMappingSource : ITypeMappingSource { /// diff --git a/src/EFCore.Relational/Storage/IRelationalTypeMappingSourcePlugin.cs b/src/EFCore.Relational/Storage/IRelationalTypeMappingSourcePlugin.cs index 3f0a54a2d7a..3a901db3d50 100644 --- a/src/EFCore.Relational/Storage/IRelationalTypeMappingSourcePlugin.cs +++ b/src/EFCore.Relational/Storage/IRelationalTypeMappingSourcePlugin.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalTypeMappingSourcePlugin { /// diff --git a/src/EFCore.Relational/Storage/IRelationalValueBufferFactory.cs b/src/EFCore.Relational/Storage/IRelationalValueBufferFactory.cs index 613f701e390..69c8ffd2de8 100644 --- a/src/EFCore.Relational/Storage/IRelationalValueBufferFactory.cs +++ b/src/EFCore.Relational/Storage/IRelationalValueBufferFactory.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalValueBufferFactory { /// diff --git a/src/EFCore.Relational/Storage/IRelationalValueBufferFactoryFactory.cs b/src/EFCore.Relational/Storage/IRelationalValueBufferFactoryFactory.cs index 6136669dca7..0801d6f1f28 100644 --- a/src/EFCore.Relational/Storage/IRelationalValueBufferFactoryFactory.cs +++ b/src/EFCore.Relational/Storage/IRelationalValueBufferFactoryFactory.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IRelationalValueBufferFactoryFactory { /// diff --git a/src/EFCore.Relational/Storage/ISqlGenerationHelper.cs b/src/EFCore.Relational/Storage/ISqlGenerationHelper.cs index 742303dd12e..cd0b253b1c5 100644 --- a/src/EFCore.Relational/Storage/ISqlGenerationHelper.cs +++ b/src/EFCore.Relational/Storage/ISqlGenerationHelper.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface ISqlGenerationHelper { /// diff --git a/src/EFCore.Relational/Storage/IntTypeMapping.cs b/src/EFCore.Relational/Storage/IntTypeMapping.cs index 7405465fc1b..1d004ba6269 100644 --- a/src/EFCore.Relational/Storage/IntTypeMapping.cs +++ b/src/EFCore.Relational/Storage/IntTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class IntTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/LongTypeMapping.cs b/src/EFCore.Relational/Storage/LongTypeMapping.cs index 739fa74aa98..418f22a94d5 100644 --- a/src/EFCore.Relational/Storage/LongTypeMapping.cs +++ b/src/EFCore.Relational/Storage/LongTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class LongTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/ParameterNameGenerator.cs b/src/EFCore.Relational/Storage/ParameterNameGenerator.cs index a8d3a00ef90..b689a6b5443 100644 --- a/src/EFCore.Relational/Storage/ParameterNameGenerator.cs +++ b/src/EFCore.Relational/Storage/ParameterNameGenerator.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ParameterNameGenerator { private int _count; diff --git a/src/EFCore.Relational/Storage/ParameterNameGeneratorFactory.cs b/src/EFCore.Relational/Storage/ParameterNameGeneratorFactory.cs index ad9a2f7cb80..5824c908706 100644 --- a/src/EFCore.Relational/Storage/ParameterNameGeneratorFactory.cs +++ b/src/EFCore.Relational/Storage/ParameterNameGeneratorFactory.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ParameterNameGeneratorFactory : IParameterNameGeneratorFactory { /// diff --git a/src/EFCore.Relational/Storage/RawSqlCommand.cs b/src/EFCore.Relational/Storage/RawSqlCommand.cs index a3606a675db..60797a85337 100644 --- a/src/EFCore.Relational/Storage/RawSqlCommand.cs +++ b/src/EFCore.Relational/Storage/RawSqlCommand.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RawSqlCommand { /// diff --git a/src/EFCore.Relational/Storage/ReaderColumn.cs b/src/EFCore.Relational/Storage/ReaderColumn.cs index e739b1fad35..94ed6f42d46 100644 --- a/src/EFCore.Relational/Storage/ReaderColumn.cs +++ b/src/EFCore.Relational/Storage/ReaderColumn.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class ReaderColumn { private static readonly ConcurrentDictionary _constructors = new(); diff --git a/src/EFCore.Relational/Storage/ReaderColumn`.cs b/src/EFCore.Relational/Storage/ReaderColumn`.cs index ac7b5647086..253768c9e76 100644 --- a/src/EFCore.Relational/Storage/ReaderColumn`.cs +++ b/src/EFCore.Relational/Storage/ReaderColumn`.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ReaderColumn : ReaderColumn { /// diff --git a/src/EFCore.Relational/Storage/RelationalCommand.cs b/src/EFCore.Relational/Storage/RelationalCommand.cs index e2596b0dd77..8e7671c7bc0 100644 --- a/src/EFCore.Relational/Storage/RelationalCommand.cs +++ b/src/EFCore.Relational/Storage/RelationalCommand.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalCommand : IRelationalCommand { private RelationalDataReader? _relationalReader; diff --git a/src/EFCore.Relational/Storage/RelationalCommandBuilder.cs b/src/EFCore.Relational/Storage/RelationalCommandBuilder.cs index a400a14ea40..2797dc2be95 100644 --- a/src/EFCore.Relational/Storage/RelationalCommandBuilder.cs +++ b/src/EFCore.Relational/Storage/RelationalCommandBuilder.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalCommandBuilder : IRelationalCommandBuilder { private readonly List _parameters = new(); diff --git a/src/EFCore.Relational/Storage/RelationalCommandBuilderExtensions.cs b/src/EFCore.Relational/Storage/RelationalCommandBuilderExtensions.cs index d90411ccad0..9647402fdb1 100644 --- a/src/EFCore.Relational/Storage/RelationalCommandBuilderExtensions.cs +++ b/src/EFCore.Relational/Storage/RelationalCommandBuilderExtensions.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// Extension methods for the class. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public static class RelationalCommandBuilderExtensions { /// diff --git a/src/EFCore.Relational/Storage/RelationalCommandBuilderFactory.cs b/src/EFCore.Relational/Storage/RelationalCommandBuilderFactory.cs index b42d96297a5..1b3e628c345 100644 --- a/src/EFCore.Relational/Storage/RelationalCommandBuilderFactory.cs +++ b/src/EFCore.Relational/Storage/RelationalCommandBuilderFactory.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalCommandBuilderFactory : IRelationalCommandBuilderFactory { /// diff --git a/src/EFCore.Relational/Storage/RelationalCommandParameterObject.cs b/src/EFCore.Relational/Storage/RelationalCommandParameterObject.cs index d7ef85e81f6..651bd2c8aa2 100644 --- a/src/EFCore.Relational/Storage/RelationalCommandParameterObject.cs +++ b/src/EFCore.Relational/Storage/RelationalCommandParameterObject.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public readonly struct RelationalCommandParameterObject { /// diff --git a/src/EFCore.Relational/Storage/RelationalConnection.cs b/src/EFCore.Relational/Storage/RelationalConnection.cs index e3f742816a1..90ed38a1fd9 100644 --- a/src/EFCore.Relational/Storage/RelationalConnection.cs +++ b/src/EFCore.Relational/Storage/RelationalConnection.cs @@ -34,6 +34,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class RelationalConnection : IRelationalConnection, ITransactionEnlistmentManager { private string? _connectionString; diff --git a/src/EFCore.Relational/Storage/RelationalDataReader.cs b/src/EFCore.Relational/Storage/RelationalDataReader.cs index 09946cfff53..5774f7adbaf 100644 --- a/src/EFCore.Relational/Storage/RelationalDataReader.cs +++ b/src/EFCore.Relational/Storage/RelationalDataReader.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalDataReader : IDisposable, IAsyncDisposable { private IRelationalConnection _relationalConnection = default!; diff --git a/src/EFCore.Relational/Storage/RelationalDatabase.cs b/src/EFCore.Relational/Storage/RelationalDatabase.cs index d6a24104cd2..3270444119b 100644 --- a/src/EFCore.Relational/Storage/RelationalDatabase.cs +++ b/src/EFCore.Relational/Storage/RelationalDatabase.cs @@ -26,6 +26,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalDatabase : Database { /// diff --git a/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs b/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs index ac82c5bd39b..4623823751d 100644 --- a/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs +++ b/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs @@ -30,6 +30,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class RelationalDatabaseCreator : IRelationalDatabaseCreator { /// diff --git a/src/EFCore.Relational/Storage/RelationalExecutionStrategyExtensions.cs b/src/EFCore.Relational/Storage/RelationalExecutionStrategyExtensions.cs index a05124c2885..1413da4ddee 100644 --- a/src/EFCore.Relational/Storage/RelationalExecutionStrategyExtensions.cs +++ b/src/EFCore.Relational/Storage/RelationalExecutionStrategyExtensions.cs @@ -13,12 +13,20 @@ namespace Microsoft.EntityFrameworkCore.Storage /// Extension methods for that can only be used with a /// relational database provider. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// public static class RelationalExecutionStrategyExtensions { /// /// Executes the specified operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The isolation level to use for the transaction. /// @@ -42,6 +50,10 @@ public static void ExecuteInTransaction( /// Executes the specified asynchronous operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The isolation level to use for the transaction. /// @@ -70,6 +82,10 @@ public static Task ExecuteInTransactionAsync( /// Executes the specified asynchronous operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The isolation level to use for the transaction. /// @@ -105,6 +121,10 @@ public static Task ExecuteInTransactionAsync( /// Executes the specified operation in a transaction and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The isolation level to use for the transaction. /// @@ -130,6 +150,10 @@ public static TResult ExecuteInTransaction( /// Executes the specified asynchronous operation in a transaction and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The isolation level to use for the transaction. /// @@ -166,6 +190,10 @@ public static Task ExecuteInTransactionAsync( /// Executes the specified operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -198,6 +226,10 @@ public static void ExecuteInTransaction( /// Executes the specified asynchronous operation in a transaction. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -241,6 +273,10 @@ public static Task ExecuteInTransactionAsync( /// Executes the specified operation in a transaction and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// @@ -270,6 +306,10 @@ public static TResult ExecuteInTransaction( /// Executes the specified asynchronous operation and returns the result. Allows to check whether /// the transaction has been rolled back if an error occurs during commit. /// + /// + /// See Connection resiliency and database retries + /// for more information. + /// /// The strategy that will be used for the execution. /// The state that will be passed to the operation. /// diff --git a/src/EFCore.Relational/Storage/RelationalExecutionStrategyFactory.cs b/src/EFCore.Relational/Storage/RelationalExecutionStrategyFactory.cs index 5b3577809ac..1b1647ab8ad 100644 --- a/src/EFCore.Relational/Storage/RelationalExecutionStrategyFactory.cs +++ b/src/EFCore.Relational/Storage/RelationalExecutionStrategyFactory.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalExecutionStrategyFactory : IExecutionStrategyFactory { private readonly Func _createExecutionStrategy; diff --git a/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs b/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs index 88e5273e746..970e8676c75 100644 --- a/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs +++ b/src/EFCore.Relational/Storage/RelationalGeometryTypeMapping.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// Base class for relation type mappings to NTS Geometry and derived types. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// /// The geometry type. /// The native type of the database provider. public abstract class RelationalGeometryTypeMapping : RelationalTypeMapping diff --git a/src/EFCore.Relational/Storage/RelationalSqlGenerationHelper.cs b/src/EFCore.Relational/Storage/RelationalSqlGenerationHelper.cs index 767517fb6ff..26d99998fae 100644 --- a/src/EFCore.Relational/Storage/RelationalSqlGenerationHelper.cs +++ b/src/EFCore.Relational/Storage/RelationalSqlGenerationHelper.cs @@ -23,6 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalSqlGenerationHelper : ISqlGenerationHelper { /// diff --git a/src/EFCore.Relational/Storage/RelationalTransaction.cs b/src/EFCore.Relational/Storage/RelationalTransaction.cs index eb977f2adc7..404a0b1bdd3 100644 --- a/src/EFCore.Relational/Storage/RelationalTransaction.cs +++ b/src/EFCore.Relational/Storage/RelationalTransaction.cs @@ -21,6 +21,9 @@ namespace Microsoft.EntityFrameworkCore.Storage /// to be directly constructed in your application code. /// /// + /// + /// See Transactions in EF Core for more information. + /// public class RelationalTransaction : IDbContextTransaction, IInfrastructure { private readonly DbTransaction _dbTransaction; diff --git a/src/EFCore.Relational/Storage/RelationalTransactionFactory.cs b/src/EFCore.Relational/Storage/RelationalTransactionFactory.cs index b0c942dabb8..8a54225e21a 100644 --- a/src/EFCore.Relational/Storage/RelationalTransactionFactory.cs +++ b/src/EFCore.Relational/Storage/RelationalTransactionFactory.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalTransactionFactory : IRelationalTransactionFactory { /// diff --git a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs index 595ec3a0c1b..c344542578e 100644 --- a/src/EFCore.Relational/Storage/RelationalTypeMapping.cs +++ b/src/EFCore.Relational/Storage/RelationalTypeMapping.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class RelationalTypeMapping : CoreTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs b/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs index d08ff196c5d..8d1189cbd23 100644 --- a/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs +++ b/src/EFCore.Relational/Storage/RelationalTypeMappingInfo.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// Describes metadata needed to decide on a relational type mapping for /// a property, type, or provider-specific relational type name. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public readonly record struct RelationalTypeMappingInfo : IEquatable { private readonly TypeMappingInfo _coreTypeMappingInfo; diff --git a/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs b/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs index 39c7cce081e..458948a0d65 100644 --- a/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs +++ b/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs @@ -31,6 +31,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class RelationalTypeMappingSource : TypeMappingSourceBase, IRelationalTypeMappingSource { private readonly ConcurrentDictionary<(RelationalTypeMappingInfo, Type?, ValueConverter?), RelationalTypeMapping?> _explicitMappings diff --git a/src/EFCore.Relational/Storage/RelationalTypeMappingSourceExtensions.cs b/src/EFCore.Relational/Storage/RelationalTypeMappingSourceExtensions.cs index 4f3a4f887c0..ee171aca7cc 100644 --- a/src/EFCore.Relational/Storage/RelationalTypeMappingSourceExtensions.cs +++ b/src/EFCore.Relational/Storage/RelationalTypeMappingSourceExtensions.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// Extension methods for the class. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public static class RelationalTypeMappingSourceExtensions { /// diff --git a/src/EFCore.Relational/Storage/SByteTypeMapping.cs b/src/EFCore.Relational/Storage/SByteTypeMapping.cs index 5d159922039..7dbea4229fd 100644 --- a/src/EFCore.Relational/Storage/SByteTypeMapping.cs +++ b/src/EFCore.Relational/Storage/SByteTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class SByteTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/ShortTypeMapping.cs b/src/EFCore.Relational/Storage/ShortTypeMapping.cs index b782b1acf23..8de7b193cd0 100644 --- a/src/EFCore.Relational/Storage/ShortTypeMapping.cs +++ b/src/EFCore.Relational/Storage/ShortTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ShortTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/StoreTypePostfix.cs b/src/EFCore.Relational/Storage/StoreTypePostfix.cs index b117528d35f..ad9a6445fa9 100644 --- a/src/EFCore.Relational/Storage/StoreTypePostfix.cs +++ b/src/EFCore.Relational/Storage/StoreTypePostfix.cs @@ -6,6 +6,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// /// Indicates which values should be appended to the store type name. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public enum StoreTypePostfix { /// diff --git a/src/EFCore.Relational/Storage/StringTypeMapping.cs b/src/EFCore.Relational/Storage/StringTypeMapping.cs index 195db6ff456..cad720892c8 100644 --- a/src/EFCore.Relational/Storage/StringTypeMapping.cs +++ b/src/EFCore.Relational/Storage/StringTypeMapping.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class StringTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/TimeOnlyTypeMapping.cs b/src/EFCore.Relational/Storage/TimeOnlyTypeMapping.cs index 410cae1cd93..3c31119d0e6 100644 --- a/src/EFCore.Relational/Storage/TimeOnlyTypeMapping.cs +++ b/src/EFCore.Relational/Storage/TimeOnlyTypeMapping.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class TimeOnlyTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/TimeSpanTypeMapping.cs b/src/EFCore.Relational/Storage/TimeSpanTypeMapping.cs index 906ffd80eab..5cf4c01c7b2 100644 --- a/src/EFCore.Relational/Storage/TimeSpanTypeMapping.cs +++ b/src/EFCore.Relational/Storage/TimeSpanTypeMapping.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class TimeSpanTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/TypeMaterializationInfo.cs b/src/EFCore.Relational/Storage/TypeMaterializationInfo.cs index 34ea5e2484c..f914e2a055c 100644 --- a/src/EFCore.Relational/Storage/TypeMaterializationInfo.cs +++ b/src/EFCore.Relational/Storage/TypeMaterializationInfo.cs @@ -11,6 +11,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// Associates a with an optional /// and an index into the data reader for use when reading and converting values from the database. /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class TypeMaterializationInfo { /// diff --git a/src/EFCore.Relational/Storage/TypedRelationalValueBufferFactoryFactory.cs b/src/EFCore.Relational/Storage/TypedRelationalValueBufferFactoryFactory.cs index ab19a60b9bf..eb0f130216f 100644 --- a/src/EFCore.Relational/Storage/TypedRelationalValueBufferFactoryFactory.cs +++ b/src/EFCore.Relational/Storage/TypedRelationalValueBufferFactoryFactory.cs @@ -38,6 +38,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class TypedRelationalValueBufferFactoryFactory : IRelationalValueBufferFactoryFactory { /// diff --git a/src/EFCore.Relational/Storage/UIntTypeMapping.cs b/src/EFCore.Relational/Storage/UIntTypeMapping.cs index 5b5d1d0506a..be3a5f51f95 100644 --- a/src/EFCore.Relational/Storage/UIntTypeMapping.cs +++ b/src/EFCore.Relational/Storage/UIntTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class UIntTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/ULongTypeMapping.cs b/src/EFCore.Relational/Storage/ULongTypeMapping.cs index e47195d98ed..1503d3a00c1 100644 --- a/src/EFCore.Relational/Storage/ULongTypeMapping.cs +++ b/src/EFCore.Relational/Storage/ULongTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ULongTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/UShortTypeMapping.cs b/src/EFCore.Relational/Storage/UShortTypeMapping.cs index ccaa715059a..bc58fbe206e 100644 --- a/src/EFCore.Relational/Storage/UShortTypeMapping.cs +++ b/src/EFCore.Relational/Storage/UShortTypeMapping.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Storage /// not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class UShortTypeMapping : RelationalTypeMapping { /// diff --git a/src/EFCore.Relational/Storage/ValueConversion/RelationalConverterMappingHints.cs b/src/EFCore.Relational/Storage/ValueConversion/RelationalConverterMappingHints.cs index 53c637e80bb..4e4319c137d 100644 --- a/src/EFCore.Relational/Storage/ValueConversion/RelationalConverterMappingHints.cs +++ b/src/EFCore.Relational/Storage/ValueConversion/RelationalConverterMappingHints.cs @@ -10,6 +10,9 @@ namespace Microsoft.EntityFrameworkCore.Storage.ValueConversion /// /// Specifies hints used by the type mapper when mapping using a . /// + /// + /// See EF Core value converters for more information. + /// public class RelationalConverterMappingHints : ConverterMappingHints { /// diff --git a/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs b/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs index d994e8ad542..49feb40a729 100644 --- a/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs +++ b/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs @@ -21,6 +21,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class AffectedCountModificationCommandBatch : ReaderModificationCommandBatch { /// diff --git a/src/EFCore.Relational/Update/ColumnModification.cs b/src/EFCore.Relational/Update/ColumnModification.cs index 349590f3eca..024cb3b38cc 100644 --- a/src/EFCore.Relational/Update/ColumnModification.cs +++ b/src/EFCore.Relational/Update/ColumnModification.cs @@ -25,6 +25,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ColumnModification : IColumnModification { private string? _parameterName; diff --git a/src/EFCore.Relational/Update/ColumnModificationParameters.cs b/src/EFCore.Relational/Update/ColumnModificationParameters.cs index 32bd7c78394..8fa014a6d7b 100644 --- a/src/EFCore.Relational/Update/ColumnModificationParameters.cs +++ b/src/EFCore.Relational/Update/ColumnModificationParameters.cs @@ -16,6 +16,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public readonly record struct ColumnModificationParameters { /// diff --git a/src/EFCore.Relational/Update/IBatchExecutor.cs b/src/EFCore.Relational/Update/IBatchExecutor.cs index 946776f2189..73ce19c24d0 100644 --- a/src/EFCore.Relational/Update/IBatchExecutor.cs +++ b/src/EFCore.Relational/Update/IBatchExecutor.cs @@ -24,6 +24,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IBatchExecutor { /// diff --git a/src/EFCore.Relational/Update/IColumnModification.cs b/src/EFCore.Relational/Update/IColumnModification.cs index 22aa9bf4415..95d038669b8 100644 --- a/src/EFCore.Relational/Update/IColumnModification.cs +++ b/src/EFCore.Relational/Update/IColumnModification.cs @@ -17,6 +17,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IColumnModification { /// diff --git a/src/EFCore.Relational/Update/ICommandBatchPreparer.cs b/src/EFCore.Relational/Update/ICommandBatchPreparer.cs index e6cdaf085c5..7daa0e8329a 100644 --- a/src/EFCore.Relational/Update/ICommandBatchPreparer.cs +++ b/src/EFCore.Relational/Update/ICommandBatchPreparer.cs @@ -21,6 +21,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface ICommandBatchPreparer { /// diff --git a/src/EFCore.Relational/Update/IModificationCommand.cs b/src/EFCore.Relational/Update/IModificationCommand.cs index 0eb9f0931e1..ace3ba1606e 100644 --- a/src/EFCore.Relational/Update/IModificationCommand.cs +++ b/src/EFCore.Relational/Update/IModificationCommand.cs @@ -11,6 +11,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IModificationCommand : IReadOnlyModificationCommand { /// diff --git a/src/EFCore.Relational/Update/IModificationCommandBatchFactory.cs b/src/EFCore.Relational/Update/IModificationCommandBatchFactory.cs index eae4fc51ad3..f7f3eb514af 100644 --- a/src/EFCore.Relational/Update/IModificationCommandBatchFactory.cs +++ b/src/EFCore.Relational/Update/IModificationCommandBatchFactory.cs @@ -19,6 +19,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IModificationCommandBatchFactory { /// diff --git a/src/EFCore.Relational/Update/IModificationCommandFactory.cs b/src/EFCore.Relational/Update/IModificationCommandFactory.cs index f90b4cf9262..5406d90fde7 100644 --- a/src/EFCore.Relational/Update/IModificationCommandFactory.cs +++ b/src/EFCore.Relational/Update/IModificationCommandFactory.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IModificationCommandFactory { /// diff --git a/src/EFCore.Relational/Update/IReadOnlyModificationCommand.cs b/src/EFCore.Relational/Update/IReadOnlyModificationCommand.cs index 63806e87ac3..6879a0c568d 100644 --- a/src/EFCore.Relational/Update/IReadOnlyModificationCommand.cs +++ b/src/EFCore.Relational/Update/IReadOnlyModificationCommand.cs @@ -14,6 +14,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IReadOnlyModificationCommand { /// diff --git a/src/EFCore.Relational/Update/IUpdateSqlGenerator.cs b/src/EFCore.Relational/Update/IUpdateSqlGenerator.cs index 7d71b9405ff..1dbf2aa2745 100644 --- a/src/EFCore.Relational/Update/IUpdateSqlGenerator.cs +++ b/src/EFCore.Relational/Update/IUpdateSqlGenerator.cs @@ -20,6 +20,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public interface IUpdateSqlGenerator { /// diff --git a/src/EFCore.Relational/Update/ModificationCommand.cs b/src/EFCore.Relational/Update/ModificationCommand.cs index 1998a8da357..35cd9b97e19 100644 --- a/src/EFCore.Relational/Update/ModificationCommand.cs +++ b/src/EFCore.Relational/Update/ModificationCommand.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class ModificationCommand : IModificationCommand { private readonly Func? _generateParameterName; diff --git a/src/EFCore.Relational/Update/ModificationCommandBatch.cs b/src/EFCore.Relational/Update/ModificationCommandBatch.cs index cf9eb0649db..2003916627c 100644 --- a/src/EFCore.Relational/Update/ModificationCommandBatch.cs +++ b/src/EFCore.Relational/Update/ModificationCommandBatch.cs @@ -18,6 +18,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class ModificationCommandBatch { /// diff --git a/src/EFCore.Relational/Update/ModificationCommandParameters.cs b/src/EFCore.Relational/Update/ModificationCommandParameters.cs index d0d8502c083..7a884eb93db 100644 --- a/src/EFCore.Relational/Update/ModificationCommandParameters.cs +++ b/src/EFCore.Relational/Update/ModificationCommandParameters.cs @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public readonly record struct ModificationCommandParameters { /// diff --git a/src/EFCore.Relational/Update/ReaderModificationCommandBatch.cs b/src/EFCore.Relational/Update/ReaderModificationCommandBatch.cs index ec416518130..c8244b4c05d 100644 --- a/src/EFCore.Relational/Update/ReaderModificationCommandBatch.cs +++ b/src/EFCore.Relational/Update/ReaderModificationCommandBatch.cs @@ -22,6 +22,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class ReaderModificationCommandBatch : ModificationCommandBatch { private readonly List _modificationCommands = new(); diff --git a/src/EFCore.Relational/Update/ResultSetMapping.cs b/src/EFCore.Relational/Update/ResultSetMapping.cs index d8d129a160d..186cf7662b1 100644 --- a/src/EFCore.Relational/Update/ResultSetMapping.cs +++ b/src/EFCore.Relational/Update/ResultSetMapping.cs @@ -11,6 +11,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public enum ResultSetMapping { /// diff --git a/src/EFCore.Relational/Update/SingularModificationCommandBatch.cs b/src/EFCore.Relational/Update/SingularModificationCommandBatch.cs index 07d04fdfd3f..9c5c283c994 100644 --- a/src/EFCore.Relational/Update/SingularModificationCommandBatch.cs +++ b/src/EFCore.Relational/Update/SingularModificationCommandBatch.cs @@ -12,6 +12,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This type is typically used by database providers; it is generally not used in application code. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class SingularModificationCommandBatch : AffectedCountModificationCommandBatch { /// diff --git a/src/EFCore.Relational/Update/UpdateSqlGenerator.cs b/src/EFCore.Relational/Update/UpdateSqlGenerator.cs index ba53a3af12a..f4fd599ab07 100644 --- a/src/EFCore.Relational/Update/UpdateSqlGenerator.cs +++ b/src/EFCore.Relational/Update/UpdateSqlGenerator.cs @@ -27,6 +27,10 @@ namespace Microsoft.EntityFrameworkCore.Update /// This service cannot depend on services registered as . /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public abstract class UpdateSqlGenerator : IUpdateSqlGenerator { /// diff --git a/src/EFCore.Relational/ValueGeneration/RelationalValueGeneratorSelector.cs b/src/EFCore.Relational/ValueGeneration/RelationalValueGeneratorSelector.cs index dd611b8f91c..0bdf9565450 100644 --- a/src/EFCore.Relational/ValueGeneration/RelationalValueGeneratorSelector.cs +++ b/src/EFCore.Relational/ValueGeneration/RelationalValueGeneratorSelector.cs @@ -24,6 +24,10 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration /// The implementation does not need to be thread-safe. /// /// + /// + /// See Implementation of database providers and extensions + /// for more information. + /// public class RelationalValueGeneratorSelector : ValueGeneratorSelector { private readonly TemporaryNumberValueGeneratorFactory _numberFactory diff --git a/src/EFCore/DbContext.cs b/src/EFCore/DbContext.cs index f41e03f3fd2..c4f45e3df03 100644 --- a/src/EFCore/DbContext.cs +++ b/src/EFCore/DbContext.cs @@ -57,7 +57,7 @@ namespace Microsoft.EntityFrameworkCore /// See DbContext lifetime, configuration, and initialization, /// Querying data with EF Core, /// Changing tracking, and - /// Saving data with EF Core for more information. + /// Saving data with EF Core for more information. /// /// public class DbContext : diff --git a/src/EFCore/DbUpdateException.cs b/src/EFCore/DbUpdateException.cs index acbb717d9a5..8edb4f53585 100644 --- a/src/EFCore/DbUpdateException.cs +++ b/src/EFCore/DbUpdateException.cs @@ -15,7 +15,7 @@ namespace Microsoft.EntityFrameworkCore /// An exception that is thrown when an error is encountered while saving to the database. /// /// - /// See Saving data with EF Core for more information. + /// See Saving data with EF Core for more information. /// [Serializable] public class DbUpdateException : Exception From c0dcce7b07c950c9f33015fa4aa6e39aff1f6a33 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Tue, 14 Sep 2021 08:58:42 +0100 Subject: [PATCH 101/346] Better exception message when switching from owned to non-owned configuration (#25984) Fixes #25863 --- src/EFCore/Properties/CoreStrings.Designer.cs | 24 +++++++++---------- src/EFCore/Properties/CoreStrings.resx | 24 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index a13989e5284..60f2e493f43 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -91,7 +91,7 @@ public static string AmbiguousOneToOneRelationship(object? dependentToPrincipalN dependentToPrincipalNavigationSpecification, principalToDependentNavigationSpecification); /// - /// Unable to determine the owner for the relationship between '{entityTypeNavigationSpecification}' and '{otherEntityType}' as both types have been marked as owned. Either manually configure the ownership, or ignore the corresponding navigations using the [NotMapped] attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'. + /// Unable to determine the owner for the relationship between '{entityTypeNavigationSpecification}' and '{otherEntityType}' as both types have been marked as owned. Either manually configure the ownership, or ignore the corresponding navigations using the [NotMapped] attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'. See https://aka.ms/efcore-docs-owned for more information. /// public static string AmbiguousOwnedNavigation(object? entityTypeNavigationSpecification, object? otherEntityType) => string.Format( @@ -171,7 +171,7 @@ public static string BadFilterExpression(object? filter, object? entityType, obj filter, entityType, clrType); /// - /// The filter expression '{filter}' cannot be specified for owned entity type '{entityType}'. A filter may only be applied to an entity type that is not owned. + /// The filter expression '{filter}' cannot be specified for owned entity type '{entityType}'. A filter may only be applied to an entity type that is not owned. See https://aka.ms/efcore-docs-owned for more information. /// public static string BadFilterOwnedType(object? filter, object? entityType) => string.Format( @@ -336,7 +336,7 @@ public static string ClashingMismatchedSharedType(object? entityType, object? ot entityType, otherClrType); /// - /// An entity type named '{ownedTypeName}' has already been added to the model. Use a different name when configuring the ownership '{ownerEntityType}.{navigation}' in 'OnModelCreating'. + /// An entity type named '{ownedTypeName}' has already been added to the model. Use a different name when configuring the ownership '{ownerEntityType}.{navigation}' in 'OnModelCreating'. See https://aka.ms/efcore-docs-owned for more information. /// public static string ClashingNamedOwnedType(object? ownedTypeName, object? ownerEntityType, object? navigation) => string.Format( @@ -344,7 +344,7 @@ public static string ClashingNamedOwnedType(object? ownedTypeName, object? owner ownedTypeName, ownerEntityType, navigation); /// - /// The entity type '{entityType}' cannot be marked as owned because the derived entity type '{derivedType}' has been configured as non-owned. Either don't configure '{derivedType}' as non-owned, or call 'HasBaseType(null)' for it in 'OnModelCreating'. + /// The entity type '{entityType}' cannot be marked as owned because the derived entity type '{derivedType}' has been configured as non-owned. Either don't configure '{derivedType}' as non-owned, or call 'HasBaseType(null)' for it in 'OnModelCreating'. See https://aka.ms/efcore-docs-owned for more information. /// public static string ClashingNonOwnedDerivedEntityType(object? entityType, object? derivedType) => string.Format( @@ -352,7 +352,7 @@ public static string ClashingNonOwnedDerivedEntityType(object? entityType, objec entityType, derivedType); /// - /// The entity type '{entityType}' cannot be configured as owned because it has already been configured as a non-owned. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. + /// The entity type '{entityType}' cannot be configured as owned because it has already been configured as a non-owned. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. See https://aka.ms/efcore-docs-owned for more information. /// public static string ClashingNonOwnedEntityType(object? entityType) => string.Format( @@ -377,7 +377,7 @@ public static string ClashingNonWeakEntityType(object? entityType) entityType); /// - /// The entity type '{entityType}' cannot be marked as non-owned because the derived entity type '{derivedType}' has been configured as owned. Either don't configure '{derivedType}' as owned, or call 'HasBaseType(null)' for it in 'OnModelCreating'. + /// The entity type '{entityType}' cannot be marked as non-owned because the derived entity type '{derivedType}' has been configured as owned. Either don't configure '{derivedType}' as owned, or call 'HasBaseType(null)' for it in 'OnModelCreating'. See https://aka.ms/efcore-docs-owned for more information. /// public static string ClashingOwnedDerivedEntityType(object? entityType, object? derivedType) => string.Format( @@ -385,7 +385,7 @@ public static string ClashingOwnedDerivedEntityType(object? entityType, object? entityType, derivedType); /// - /// The entity type '{entityType}' cannot be configured as non-owned because it has already been configured as a owned. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. + /// The entity type '{entityType}' cannot be configured as non-owned because it has already been configured as a owned. Use the nested builder in `OwnsOne` or `OwnsMany` on the owner entity type builder to further configure this type. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. See https://aka.ms/efcore-docs-owned for more information. /// public static string ClashingOwnedEntityType(object? entityType) => string.Format( @@ -634,7 +634,7 @@ public static string DerivedEntityCannotHaveKeys(object? entityType) entityType); /// - /// Unable to set '{baseEntityType}' as the base type for entity type '{derivedEntityType}' because '{ownedEntityType}' is configured as owned, while '{nonOwnedEntityType}' is non-owned. All entity types in a hierarchy need to have the same ownership status. + /// Unable to set '{baseEntityType}' as the base type for entity type '{derivedEntityType}' because '{ownedEntityType}' is configured as owned, while '{nonOwnedEntityType}' is non-owned. All entity types in a hierarchy need to have the same ownership status. See https://aka.ms/efcore-docs-owned for more information. /// public static string DerivedEntityOwnershipMismatch(object? baseEntityType, object? derivedEntityType, object? ownedEntityType, object? nonOwnedEntityType) => string.Format( @@ -1371,7 +1371,7 @@ public static string InvalidSetType(object? typeName) typeName); /// - /// Cannot create a DbSet for '{typeName}' because it is configured as an owned entity type and must be accessed through its owning entity type '{ownerType}'. + /// Cannot create a DbSet for '{typeName}' because it is configured as an owned entity type and must be accessed through its owning entity type '{ownerType}'. See https://aka.ms/efcore-docs-owned for more information. /// public static string InvalidSetTypeOwned(object? typeName, object? ownerType) => string.Format( @@ -1436,7 +1436,7 @@ public static string InversePropertyMismatch(object? navigation, object? entityT navigation, entityType, referencedNavigation, referencedEntityType); /// - /// The navigation '{principalEntityType}.{navigation}' is not supported because it is pointing to an owned entity type '{ownedType}'. Only the ownership navigation from the entity type '{ownerType}' can point to the owned entity type. + /// The navigation '{principalEntityType}.{navigation}' is not supported because it is pointing to an owned entity type '{ownedType}'. Only the ownership navigation from the entity type '{ownerType}' can point to the owned entity type. See https://aka.ms/efcore-docs-owned for more information. /// public static string InverseToOwnedType(object? principalEntityType, object? navigation, object? ownedType, object? ownerType) => string.Format( @@ -1703,7 +1703,7 @@ public static string NavigationIsProperty(object? property, object? entityType, property, entityType, referenceMethod, collectionMethod, propertyMethod); /// - /// The relationship between '{principalEntityType}' and '{dependentEntityType}' cannot be configured as an ownership as there is no associated navigation to the owned type. An ownership must always have an associated navigation. + /// The relationship between '{principalEntityType}' and '{dependentEntityType}' cannot be configured as an ownership as there is no associated navigation to the owned type. An ownership must always have an associated navigation. See https://aka.ms/efcore-docs-owned for more information. /// public static string NavigationlessOwnership(object? principalEntityType, object? dependentEntityType) => string.Format( @@ -2059,7 +2059,7 @@ public static string OriginalValueNotTracked(object? property, object? entityTyp property, entityType); /// - /// The owned entity type '{entityType}' cannot have a base type. + /// The owned entity type '{entityType}' cannot have a base type. See https://aka.ms/efcore-docs-owned for more information. /// public static string OwnedDerivedType(object? entityType) => string.Format( diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index da665f56181..100b4b9b66b 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -142,7 +142,7 @@ The dependent side could not be determined for the one-to-one relationship between '{dependentToPrincipalNavigationSpecification}' and '{principalToDependentNavigationSpecification}'. To identify the dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship, configure them independently via separate method chains in 'OnModelCreating'. See http://go.microsoft.com/fwlink/?LinkId=724062 for more details. - Unable to determine the owner for the relationship between '{entityTypeNavigationSpecification}' and '{otherEntityType}' as both types have been marked as owned. Either manually configure the ownership, or ignore the corresponding navigations using the [NotMapped] attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'. + Unable to determine the owner for the relationship between '{entityTypeNavigationSpecification}' and '{otherEntityType}' as both types have been marked as owned. Either manually configure the ownership, or ignore the corresponding navigations using the [NotMapped] attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'. See https://aka.ms/efcore-docs-owned for more information. The shared type entity type '{entityType}' cannot be added to the model because its name is the same as the CLR type name. This usually indicates an error, either add it as a non-shared entity type or choose a different name. @@ -172,7 +172,7 @@ The filter expression '{filter}' specified for entity type '{entityType}' is invalid. The expression must accept a single parameter of type '{clrType}' and return bool. - The filter expression '{filter}' cannot be specified for owned entity type '{entityType}'. A filter may only be applied to an entity type that is not owned. + The filter expression '{filter}' cannot be specified for owned entity type '{entityType}'. A filter may only be applied to an entity type that is not owned. See https://aka.ms/efcore-docs-owned for more information. The type '{givenType}' cannot be used as a value comparer because it does not inherit from '{expectedType}'. Make sure to inherit value comparers from '{expectedType}'. @@ -236,13 +236,13 @@ The shared-type entity type '{entityType}' cannot be added because the model already contains an entity type with the same name, but with a different CLR type '{otherClrType}'. Ensure all entity type names are unique. - An entity type named '{ownedTypeName}' has already been added to the model. Use a different name when configuring the ownership '{ownerEntityType}.{navigation}' in 'OnModelCreating'. + An entity type named '{ownedTypeName}' has already been added to the model. Use a different name when configuring the ownership '{ownerEntityType}.{navigation}' in 'OnModelCreating'. See https://aka.ms/efcore-docs-owned for more information. - The entity type '{entityType}' cannot be marked as owned because the derived entity type '{derivedType}' has been configured as non-owned. Either don't configure '{derivedType}' as non-owned, or call 'HasBaseType(null)' for it in 'OnModelCreating'. + The entity type '{entityType}' cannot be marked as owned because the derived entity type '{derivedType}' has been configured as non-owned. Either don't configure '{derivedType}' as non-owned, or call 'HasBaseType(null)' for it in 'OnModelCreating'. See https://aka.ms/efcore-docs-owned for more information. - The entity type '{entityType}' cannot be configured as owned because it has already been configured as a non-owned. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. + The entity type '{entityType}' cannot be configured as owned because it has already been configured as a non-owned. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. See https://aka.ms/efcore-docs-owned for more information. The shared-type entity type '{entityType}' with CLR type '{type}' cannot be added to the model because a non-shared entity type with the same CLR type already exists. @@ -252,10 +252,10 @@ Obsolete - The entity type '{entityType}' cannot be marked as non-owned because the derived entity type '{derivedType}' has been configured as owned. Either don't configure '{derivedType}' as owned, or call 'HasBaseType(null)' for it in 'OnModelCreating'. + The entity type '{entityType}' cannot be marked as non-owned because the derived entity type '{derivedType}' has been configured as owned. Either don't configure '{derivedType}' as owned, or call 'HasBaseType(null)' for it in 'OnModelCreating'. See https://aka.ms/efcore-docs-owned for more information. - The entity type '{entityType}' cannot be configured as non-owned because it has already been configured as a owned. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. + The entity type '{entityType}' cannot be configured as non-owned because it has already been configured as a owned. Use the nested builder in `OwnsOne` or `OwnsMany` on the owner entity type builder to further configure this type. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. See https://aka.ms/efcore-docs-owned for more information. The entity type '{entityType}' cannot be added to the model because its CLR type has been configured as a shared type. @@ -354,7 +354,7 @@ Unable to set a base type for entity type '{entityType}' because it has one or more keys defined. Only root types can have keys. - Unable to set '{baseEntityType}' as the base type for entity type '{derivedEntityType}' because '{ownedEntityType}' is configured as owned, while '{nonOwnedEntityType}' is non-owned. All entity types in a hierarchy need to have the same ownership status. + Unable to set '{baseEntityType}' as the base type for entity type '{derivedEntityType}' because '{ownedEntityType}' is configured as owned, while '{nonOwnedEntityType}' is non-owned. All entity types in a hierarchy need to have the same ownership status. See https://aka.ms/efcore-docs-owned for more information. '{derivedType}' cannot be configured as keyless because it is a derived type; the root type '{rootType}' must be configured as keyless instead. If you did not intend for '{rootType}' to be included in the model, ensure that it is not referenced by a DbSet property on your context, referenced in a configuration call to ModelBuilder in 'OnModelCreating', or referenced from a navigation on a type that is included in the model. @@ -640,7 +640,7 @@ Cannot create a DbSet for '{typeName}' because this type is not included in the model for the context. - Cannot create a DbSet for '{typeName}' because it is configured as an owned entity type and must be accessed through its owning entity type '{ownerType}'. + Cannot create a DbSet for '{typeName}' because it is configured as an owned entity type and must be accessed through its owning entity type '{ownerType}'. See https://aka.ms/efcore-docs-owned for more information. Cannot create a DbSet for '{typeName}' because it is mapped to multiple entity types with defining navigations and should be accessed through the owning entities. @@ -665,7 +665,7 @@ [InverseProperty] attributes on navigation '{1_entityType}.{0_navigation}' and on navigation '{3_referencedEntityType}.{2_referencedNavigation}' are not pointing to each other. Change the attributes to use the corresponding names or remove one of them. - The navigation '{principalEntityType}.{navigation}' is not supported because it is pointing to an owned entity type '{ownedType}'. Only the ownership navigation from the entity type '{ownerType}' can point to the owned entity type. + The navigation '{principalEntityType}.{navigation}' is not supported because it is pointing to an owned entity type '{ownedType}'. Only the ownership navigation from the entity type '{ownerType}' can point to the owned entity type. See https://aka.ms/efcore-docs-owned for more information. The source 'IQueryable' doesn't implement 'IAsyncEnumerable<{genericParameter}>'. Only sources that implement 'IAsyncEnumerable' can be used for Entity Framework asynchronous operations. @@ -1080,7 +1080,7 @@ The property '{1_entityType}.{0_property}' is being accessed using the '{referenceMethod}' or '{collectionMethod}' method, but is defined in the model as a non-navigation. Use the '{propertyMethod}' method to access non-navigation properties. - The relationship between '{principalEntityType}' and '{dependentEntityType}' cannot be configured as an ownership as there is no associated navigation to the owned type. An ownership must always have an associated navigation. + The relationship between '{principalEntityType}' and '{dependentEntityType}' cannot be configured as an ownership as there is no associated navigation to the owned type. An ownership must always have an associated navigation. See https://aka.ms/efcore-docs-owned for more information. The navigation '{1_entityType}.{0_navigation}' does not have a setter and no writable backing field was found or specified. Read-only collection navigations must be initialized before use. @@ -1221,7 +1221,7 @@ The original value for property '{1_entityType}.{0_property}' cannot be accessed because it is not being tracked. Original values are not recorded for most properties of entities when the 'ChangingAndChangedNotifications' strategy is used. To access all original values, use a different change tracking strategy such as 'ChangingAndChangedNotificationsWithOriginalValues'. - The owned entity type '{entityType}' cannot have a base type. + The owned entity type '{entityType}' cannot have a base type. See https://aka.ms/efcore-docs-owned for more information. A tracking query is attempting to project an owned entity without a corresponding owner in its result, but owned entities cannot be tracked without their owner. Either include the owner entity in the result or make the query non-tracking using 'AsNoTracking'. From 729dc99100a141faefb4bb9669fa1ab75d611c42 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Tue, 14 Sep 2021 09:02:02 +0100 Subject: [PATCH 102/346] Clear all connection pools before attempting to delete SQLite file (#25985) Fixes #25797 --- .../Storage/Internal/SqliteDatabaseCreator.cs | 2 +- .../SqliteDatabaseCreatorTest.cs | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteDatabaseCreator.cs b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteDatabaseCreator.cs index 51307d76681..e17de7bada2 100644 --- a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteDatabaseCreator.cs +++ b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteDatabaseCreator.cs @@ -147,7 +147,7 @@ public override void Delete() if (!string.IsNullOrEmpty(path)) { - SqliteConnection.ClearPool(new SqliteConnection(Dependencies.Connection.ConnectionString)); + SqliteConnection.ClearAllPools(); File.Delete(path); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/SqliteDatabaseCreatorTest.cs b/test/EFCore.Sqlite.FunctionalTests/SqliteDatabaseCreatorTest.cs index 60ca8856867..730bd3fa2af 100644 --- a/test/EFCore.Sqlite.FunctionalTests/SqliteDatabaseCreatorTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/SqliteDatabaseCreatorTest.cs @@ -102,6 +102,55 @@ public async Task Create_sets_journal_mode_to_wal(bool async) Assert.Equal("wal", journalMode); } + [ConditionalTheory] + [InlineData(false)] + [InlineData(true)] + public async Task Delete_works_even_when_different_connection_exists_to_same_file(bool async) + { + using (var context = new BathtubContext("DataSource=bathtub.db")) + { + if (async) + { + await context.Database.EnsureDeletedAsync(); + await context.Database.EnsureCreatedAsync(); + } + else + { + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + } + } + + using (var context = new BathtubContext("Command Timeout=60;DataSource=bathtub.db")) + { + var creator = context.GetService(); + + if (async) + { + await context.Database.EnsureDeletedAsync(); + Assert.False(await creator.ExistsAsync()); + } + else + { + context.Database.EnsureDeleted(); + Assert.False(creator.Exists()); + } + } + } + + private class BathtubContext : DbContext + { + private readonly string _connectionString; + + public BathtubContext(string connectionString) + { + _connectionString = connectionString; + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.UseSqlite(_connectionString); + } + [ConditionalTheory] [InlineData("Data Source=:memory:")] [InlineData("Data Source=exists-memory;Mode=Memory;Cache=Shared")] From b47ddd10e5bceaf28a3fa882314b6aecfc20b7d7 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Tue, 14 Sep 2021 09:03:40 +0100 Subject: [PATCH 103/346] Don't hard-code value generation to Never for FKs (#25992) Fixes #23974 --- .../RelationalConventionSetBuilder.cs | 2 + .../Conventions/ValueGenerationConvention.cs | 4 +- .../GraphUpdates/GraphUpdatesInMemoryTest.cs | 4 ++ .../GraphUpdates/GraphUpdatesTestBase.cs | 43 +++++++++++++++++++ .../GraphUpdatesTestBaseMiscellaneous.cs | 27 ++++++++++++ .../GraphUpdatesSqlServerOwnedTest.cs | 14 ++++++ .../GraphUpdatesSqlServerTestBase.cs | 19 ++++++++ .../SqlServerEndToEndTest.cs | 1 - .../GraphUpdatesSqliteTestBase.cs | 19 ++++++++ 9 files changed, 130 insertions(+), 3 deletions(-) diff --git a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs index 488c041fa01..59764963ed2 100644 --- a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs +++ b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs @@ -76,6 +76,8 @@ public override ConventionSet CreateConventionSet() ValueGenerationConvention valueGenerationConvention = new RelationalValueGenerationConvention(Dependencies, RelationalDependencies); ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGenerationConvention); + ReplaceConvention(conventionSet.ForeignKeyPropertiesChangedConventions, valueGenerationConvention); + ReplaceConvention(conventionSet.ForeignKeyOwnershipChangedConventions, valueGenerationConvention); conventionSet.EntityTypeBaseTypeChangedConventions.Add(tableNameFromDbSetConvention); conventionSet.EntityTypeBaseTypeChangedConventions.Add(new CheckConstraintConvention(Dependencies, RelationalDependencies)); diff --git a/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs b/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs index 8f524743d3b..090d7355382 100644 --- a/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs +++ b/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs @@ -52,7 +52,7 @@ public virtual void ProcessForeignKeyAdded( { foreach (var property in foreignKey.Properties) { - property.Builder.ValueGenerated(ValueGenerated.Never); + property.Builder.ValueGenerated(GetValueGenerated(property)); } } } @@ -94,7 +94,7 @@ public virtual void ProcessForeignKeyPropertiesChanged( { foreach (var property in foreignKey.Properties) { - property.Builder.ValueGenerated(ValueGenerated.Never); + property.Builder.ValueGenerated(GetValueGenerated(property)); } } } diff --git a/test/EFCore.InMemory.FunctionalTests/GraphUpdates/GraphUpdatesInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/GraphUpdates/GraphUpdatesInMemoryTest.cs index 6520be3daae..9f5c80eb282 100644 --- a/test/EFCore.InMemory.FunctionalTests/GraphUpdates/GraphUpdatesInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/GraphUpdates/GraphUpdatesInMemoryTest.cs @@ -16,6 +16,10 @@ public GraphUpdatesInMemoryTest(InMemoryFixture fixture) { } + // In-memory database does not have database default values + public override Task Can_insert_when_FK_has_default_value(bool async) + => Task.CompletedTask; + public override void Required_many_to_one_dependents_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) diff --git a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs index b37894d068c..c99021eceae 100644 --- a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs +++ b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBase.cs @@ -3451,6 +3451,49 @@ public int CityId } } + protected class Cruiser : NotifyingEntity + { + private int _cruiserId; + private int _idUserState; + private AccessState _userState; + + public int CruiserId + { + get => _cruiserId; + set => SetWithNotify(value, ref _cruiserId); + } + + public int IdUserState + { + get => _idUserState; + set => SetWithNotify(value, ref _idUserState); + } + + public virtual AccessState UserState + { + get => _userState; + set => SetWithNotify(value, ref _userState); + } + } + + protected class AccessState : NotifyingEntity + { + private int _accessStateId; + private ICollection _users = new ObservableHashSet(); + + public int AccessStateId + { + get => _accessStateId; + set => SetWithNotify(value, ref _accessStateId); + } + + public virtual ICollection Users + { + get => _users; + set => SetWithNotify(value, ref _users); + } + } + protected class NotifyingEntity : INotifyPropertyChanging, INotifyPropertyChanged { protected void SetWithNotify(T value, ref T field, [CallerMemberName] string propertyName = "") diff --git a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs index 63971570e01..7e54281ab14 100644 --- a/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs +++ b/test/EFCore.Specification.Tests/GraphUpdates/GraphUpdatesTestBaseMiscellaneous.cs @@ -18,6 +18,33 @@ namespace Microsoft.EntityFrameworkCore public abstract partial class GraphUpdatesTestBase where TFixture : GraphUpdatesTestBase.GraphUpdatesFixtureBase, new() { + [ConditionalTheory] // Issue #23974 + [InlineData(false)] + [InlineData(true)] + public virtual async Task Can_insert_when_FK_has_default_value(bool async) + { + await ExecuteWithStrategyInTransactionAsync( + async context => + { + if (async) + { + await context.AddAsync(new Cruiser()); + await context.SaveChangesAsync(); + } + else + { + context.Add(new Cruiser()); + context.SaveChanges(); + } + }, + async context => + { + var queryable = context.Set().Include(e => e.UserState); + var cruiser = async ? (await queryable.SingleAsync()) : queryable.Single(); + Assert.Equal(cruiser.IdUserState, cruiser.UserState.AccessStateId); + }); + } + [ConditionalTheory] // Issue #23043 [InlineData(false)] [InlineData(true)] diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerOwnedTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerOwnedTest.cs index 22a1bf23271..c64c766613f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerOwnedTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerOwnedTest.cs @@ -499,6 +499,20 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con }); modelBuilder.Entity(); + + modelBuilder.Entity( + b => + { + b.Property(e => e.AccessStateId).ValueGeneratedNever(); + b.HasData(new AccessState {AccessStateId = 1}); + }); + + modelBuilder.Entity( + b => + { + b.Property(e => e.IdUserState).HasDefaultValue(1); + b.HasOne(e => e.UserState).WithMany(e => e.Users).HasForeignKey(e => e.IdUserState); + }); } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTestBase.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTestBase.cs index f3c4ecbed18..c4062c37d2f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTestBase.cs +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdates/GraphUpdatesSqlServerTestBase.cs @@ -29,6 +29,25 @@ public TestSqlLoggerFactory TestSqlLoggerFactory protected override ITestStoreFactory TestStoreFactory => SqlServerTestStoreFactory.Instance; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity( + b => + { + b.Property(e => e.AccessStateId).ValueGeneratedNever(); + b.HasData(new AccessState {AccessStateId = 1}); + }); + + modelBuilder.Entity( + b => + { + b.Property(e => e.IdUserState).HasDefaultValue(1); + b.HasOne(e => e.UserState).WithMany(e => e.Users).HasForeignKey(e => e.IdUserState); + }); + } } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs b/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs index 8425d7228bb..eb59f231491 100644 --- a/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Runtime.CompilerServices; diff --git a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTestBase.cs b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTestBase.cs index ce1ce3c220e..aeaabb770c4 100644 --- a/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTestBase.cs +++ b/test/EFCore.Sqlite.FunctionalTests/GraphUpdates/GraphUpdatesSqliteTestBase.cs @@ -66,6 +66,25 @@ public override PoolableDbContext CreateContext() return context; } + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity( + b => + { + b.Property(e => e.AccessStateId).ValueGeneratedNever(); + b.HasData(new AccessState {AccessStateId = 1}); + }); + + modelBuilder.Entity( + b => + { + b.Property(e => e.IdUserState).HasDefaultValue(1); + b.HasOne(e => e.UserState).WithMany(e => e.Users).HasForeignKey(e => e.IdUserState); + }); + } } } } From d07f279775f28725ff316253e493fa0bcfd7a75d Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Tue, 14 Sep 2021 15:25:54 +0100 Subject: [PATCH 104/346] Throw better exception for many-to-many with same navigation on both ends (#25990) Co-authored-by: Andriy Svyryd --- .../Builders/CollectionCollectionBuilder.cs | 7 +++++++ src/EFCore/Properties/CoreStrings.Designer.cs | 8 ++++++++ src/EFCore/Properties/CoreStrings.resx | 3 +++ .../ModelBuilding/ManyToManyTestBase.cs | 13 +++++++------ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/EFCore/Metadata/Builders/CollectionCollectionBuilder.cs b/src/EFCore/Metadata/Builders/CollectionCollectionBuilder.cs index 1b17265d879..e77447031e2 100644 --- a/src/EFCore/Metadata/Builders/CollectionCollectionBuilder.cs +++ b/src/EFCore/Metadata/Builders/CollectionCollectionBuilder.cs @@ -3,6 +3,7 @@ using System; using System.ComponentModel; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Utilities; @@ -41,6 +42,12 @@ public CollectionCollectionBuilder( Check.DebugAssert(((IConventionSkipNavigation)leftNavigation).IsInModel, "Not in model"); Check.DebugAssert(((IConventionSkipNavigation)rightNavigation).IsInModel, "Not in model"); + if (leftNavigation == rightNavigation) + { + throw new InvalidOperationException( + CoreStrings.ManyToManyOneNav(leftEntityType.DisplayName(), leftNavigation.Name)); + } + LeftEntityType = leftEntityType; RightEntityType = rightEntityType; LeftNavigation = leftNavigation; diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index 60f2e493f43..c7234d5386f 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -1545,6 +1545,14 @@ public static string LiteralGenerationNotSupported(object? type) GetString("LiteralGenerationNotSupported", nameof(type)), type); + /// + /// The navigation '{entityType}.{navigation}' cannot be used for both sides of a many-to-many relationship. Many-to-many relationships must use different navigation properties for either end of the relationship. + /// + public static string ManyToManyOneNav(object? entityType, object? navigation) + => string.Format( + GetString("ManyToManyOneNav", "entityType", "navigation"), + entityType, navigation); + /// /// The specified field '{field}' could not be found for property '{2_entityType}.{1_property}'. /// diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index 100b4b9b66b..d5573b70723 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -1018,6 +1018,9 @@ '{contextType}' generated value '{keyValue}' for the property '{3_entityType}.{2_property}'. Debug CoreEventId.ValueGenerated string object? string string + + The navigation '{entityType}.{navigation}' cannot be used for both sides of a many-to-many relationship. Many-to-many relationships must use two distinct navigation properties. + The specified field '{field}' could not be found for property '{2_entityType}.{1_property}'. diff --git a/test/EFCore.Tests/ModelBuilding/ManyToManyTestBase.cs b/test/EFCore.Tests/ModelBuilding/ManyToManyTestBase.cs index 13025a272ea..b1597475458 100644 --- a/test/EFCore.Tests/ModelBuilding/ManyToManyTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/ManyToManyTestBase.cs @@ -472,12 +472,13 @@ public virtual void Throws_for_self_ref_with_same_navigation() { var modelBuilder = CreateModelBuilder(); - modelBuilder.Entity().Ignore(s => s.SelfRef1); - modelBuilder.Entity().HasMany(t => t.SelfRef2) - .WithMany(t => t.SelfRef2); - - Assert.Equal(CoreStrings.EntityRequiresKey("SelfRefManyToOneSelfRefManyToOne (Dictionary)"), - Assert.Throws(() => modelBuilder.FinalizeModel()).Message); + Assert.Equal( + CoreStrings.ManyToManyOneNav(nameof(SelfRefManyToOne), nameof(SelfRefManyToOne.SelfRef2)), + Assert.Throws( + () => modelBuilder + .Entity() + .HasMany(e => e.SelfRef2) + .WithMany(e => e.SelfRef2)).Message); } [ConditionalFact] From 9e3b86989ddf90bf231efad64066c10a85081ef2 Mon Sep 17 00:00:00 2001 From: maumar Date: Fri, 10 Sep 2021 17:05:23 -0700 Subject: [PATCH 105/346] Fixing bugs around hidden period columns Fixes #25841 - Create period columns as hidden Fixes #25774 - EFCore.SqlServer - v6.00-preview - SqlServerDatabaseModelFactory doesn't read information about hidden temoral tables' columns Fixes #25773 - EFCore.SqlServer - v6.00-preview - failed on creating model for WideWorldImporters sample database temporal tables Multiple problems were causing the issues in the scaffolding code path: We used to skip over hidden columns when constructing database model. This made sense when temporal tables were not supported, but now we need that column information. However, if we add period columns to database model, they will in turn produce EF model with period properties, and then code generator will produce property code for them on the entity, rendering them non-shadow. All period properties must be in shadow state (otherwise validation fails) and there is currently no way to mark a property as shadow state in the code generator. Instead, we continue to not add period columns to the table in the database model, so the properties won't be part of the EF model passed to the code generator and therefore code for them is not generated and they de facto stay in shadow state. To compensate, in SqlServerDatabaseModelFactory we store the period information on the table in form of period start/end property name. Code generator uses annotations to produce the temporal table configuration fluen API, so this information is sufficient. Also adjusted code in SqlServerAnnotationProvider which was always expecting period properties to always be defined on the model. It is still the case for a normal code path, but for scaffolding properties are missing (due to shadow state code gen issue), and we no longer throw NRE because of that. Small drawback is that we don't scaffold indexes based on period columns. We would need to add the period columns to the database model in SqlServerDatabaseModelFactory. It's possible to define such index in the model and migrations will create DML for it, but reverse engineer is unable to pick up existing indexes. --- .../SqlServerAnnotationCodeGenerator.cs | 29 +- .../Internal/SqlServerAnnotationProvider.cs | 44 ++- .../SqlServerMigrationsSqlGenerator.cs | 26 ++ .../Internal/SqlServerDatabaseModelFactory.cs | 13 +- .../Internal/CSharpDbContextGeneratorTest.cs | 78 ++++ .../Migrations/MigrationsSqlServerTest.cs | 332 ++++++++++-------- .../SqlServerDatabaseModelFactoryTest.cs | 39 +- 7 files changed, 386 insertions(+), 175 deletions(-) diff --git a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs index f6055dbc3d3..395e8ca94ea 100644 --- a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs +++ b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs @@ -197,10 +197,23 @@ public override IReadOnlyList GenerateFluentApiCalls( ? annotations[SqlServerAnnotationNames.TemporalHistoryTableSchema].Value as string : null; - var periodStartProperty = entityType.GetProperty(entityType.GetPeriodStartPropertyName()!); - var periodEndProperty = entityType.GetProperty(entityType.GetPeriodEndPropertyName()!); - var periodStartColumnName = periodStartProperty[RelationalAnnotationNames.ColumnName] as string; - var periodEndColumnName = periodEndProperty[RelationalAnnotationNames.ColumnName] as string; + // for the RevEng path, we avoid adding period properties to the entity + // because we don't want code for them to be generated - they need to be in shadow state + // so if we don't find property on the entity, we know it's this scenario + // and in that case period column name is actually the same as the period property name annotation + // since in RevEng scenario there can't be custom column mapping + // see #26007 + var periodStartPropertyName = entityType.GetPeriodStartPropertyName(); + var periodStartProperty = entityType.FindProperty(periodStartPropertyName!); + var periodStartColumnName = periodStartProperty != null + ? periodStartProperty[RelationalAnnotationNames.ColumnName] as string + : periodStartPropertyName; + + var periodEndPropertyName = entityType.GetPeriodEndPropertyName(); + var periodEndProperty = entityType.FindProperty(periodEndPropertyName!); + var periodEndColumnName = periodEndProperty != null + ? periodEndProperty[RelationalAnnotationNames.ColumnName] as string + : periodEndPropertyName; // ttb => ttb.UseHistoryTable("HistoryTable", "schema") var temporalTableBuilderCalls = new List(); @@ -215,16 +228,16 @@ public override IReadOnlyList GenerateFluentApiCalls( // ttb => ttb.HasPeriodStart("Start").HasColumnName("ColumnStart") temporalTableBuilderCalls.Add( periodStartColumnName != null - ? new MethodCallCodeFragment(_temporalTableHasPeriodStartMethodInfo, periodStartProperty.Name) + ? new MethodCallCodeFragment(_temporalTableHasPeriodStartMethodInfo, periodStartPropertyName) .Chain(new MethodCallCodeFragment(_temporalPropertyHasColumnNameMethodInfo, periodStartColumnName)) - : new MethodCallCodeFragment(_temporalTableHasPeriodStartMethodInfo, periodStartProperty.Name)); + : new MethodCallCodeFragment(_temporalTableHasPeriodStartMethodInfo, periodStartPropertyName)); // ttb => ttb.HasPeriodEnd("End").HasColumnName("ColumnEnd") temporalTableBuilderCalls.Add( periodEndColumnName != null - ? new MethodCallCodeFragment(_temporalTableHasPeriodEndMethodInfo, periodEndProperty.Name) + ? new MethodCallCodeFragment(_temporalTableHasPeriodEndMethodInfo, periodEndPropertyName) .Chain(new MethodCallCodeFragment(_temporalPropertyHasColumnNameMethodInfo, periodEndColumnName)) - : new MethodCallCodeFragment(_temporalTableHasPeriodEndMethodInfo, periodEndProperty.Name)); + : new MethodCallCodeFragment(_temporalTableHasPeriodEndMethodInfo, periodEndPropertyName)); // ToTable(tb => tb.IsTemporal(ttb => { ... })) var toTemporalTableCall = new MethodCallCodeFragment( diff --git a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs index 56784b5eb79..a91f26f5ba5 100644 --- a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs +++ b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs @@ -116,19 +116,33 @@ public override IEnumerable For(ITable table, bool designTime) yield return new Annotation(SqlServerAnnotationNames.TemporalHistoryTableName, entityType.GetHistoryTableName()); yield return new Annotation(SqlServerAnnotationNames.TemporalHistoryTableSchema, entityType.GetHistoryTableSchema()); + // for the RevEng path, we avoid adding period properties to the entity + // because we don't want code for them to be generated - they need to be in shadow state + // so if we don't find property on the entity, we know it's this scenario + // and in that case period column name is actually the same as the period property name annotation + // since in RevEng scenario there can't be custom column mapping + // see #26007 var storeObjectIdentifier = StoreObjectIdentifier.Table(table.Name, table.Schema); var periodStartPropertyName = entityType.GetPeriodStartPropertyName(); if (periodStartPropertyName != null) { - var periodStartProperty = entityType.GetProperty(periodStartPropertyName); - yield return new Annotation(SqlServerAnnotationNames.TemporalPeriodStartColumnName, periodStartProperty.GetColumnName(storeObjectIdentifier)); + var periodStartProperty = entityType.FindProperty(periodStartPropertyName); + var periodStartColumnName = periodStartProperty != null + ? periodStartProperty.GetColumnName(storeObjectIdentifier) + : periodStartPropertyName; + + yield return new Annotation(SqlServerAnnotationNames.TemporalPeriodStartColumnName, periodStartColumnName); } var periodEndPropertyName = entityType.GetPeriodEndPropertyName(); if (periodEndPropertyName != null) { - var periodEndProperty = entityType.GetProperty(entityType.GetPeriodEndPropertyName()!); - yield return new Annotation(SqlServerAnnotationNames.TemporalPeriodEndColumnName, periodEndProperty.GetColumnName(storeObjectIdentifier)); + var periodEndProperty = entityType.FindProperty(periodEndPropertyName); + var periodEndColumnName = periodEndProperty != null + ? periodEndProperty.GetColumnName(storeObjectIdentifier) + : periodEndPropertyName; + + yield return new Annotation(SqlServerAnnotationNames.TemporalPeriodEndColumnName, periodEndColumnName); } } } @@ -244,13 +258,23 @@ public override IEnumerable For(IColumn column, bool designTime) { var periodStartPropertyName = entityType.GetPeriodStartPropertyName(); var periodEndPropertyName = entityType.GetPeriodEndPropertyName(); - - var periodStartProperty = entityType.GetProperty(periodStartPropertyName!); - var periodEndProperty = entityType.GetProperty(periodEndPropertyName!); - var storeObjectIdentifier = StoreObjectIdentifier.Table(table.Name, table.Schema); - var periodStartColumnName = periodStartProperty.GetColumnName(storeObjectIdentifier); - var periodEndColumnName = periodEndProperty.GetColumnName(storeObjectIdentifier); + + // for the RevEng path, we avoid adding period properties to the entity + // because we don't want code for them to be generated - they need to be in shadow state + // so if we don't find property on the entity, we know it's this scenario + // and in that case period column name is actually the same as the period property name annotation + // since in RevEng scenario there can't be custom column mapping + // see #26007 + var periodStartProperty = entityType.FindProperty(periodStartPropertyName!); + var periodStartColumnName = periodStartProperty != null + ? periodStartProperty.GetColumnName(storeObjectIdentifier) + : periodStartPropertyName; + + var periodEndProperty = entityType.FindProperty(periodEndPropertyName!); + var periodEndColumnName = periodEndProperty != null + ? periodEndProperty.GetColumnName(storeObjectIdentifier) + : periodEndPropertyName; if (column.Name == periodStartColumnName || column.Name == periodEndColumnName) diff --git a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs index 19289767eba..8d6b0cf6be9 100644 --- a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs +++ b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs @@ -1608,6 +1608,8 @@ protected override void ColumnDefinition( { builder.Append("END"); } + + builder.Append(" HIDDEN"); } builder.Append(operation.IsNullable ? " NULL" : " NOT NULL"); @@ -2682,6 +2684,30 @@ void EnablePeriod(string table, string? schema, string periodStartColumnName, st .Append(")") .ToString() }); + + operations.Add( + new SqlOperation + { + Sql = new StringBuilder() + .Append("ALTER TABLE ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(table, schema)) + .Append(" ALTER COLUMN ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(periodStartColumnName)) + .Append(" ADD HIDDEN") + .ToString() + }); + + operations.Add( + new SqlOperation + { + Sql = new StringBuilder() + .Append("ALTER TABLE ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(table, schema)) + .Append(" ALTER COLUMN ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(periodEndColumnName)) + .Append(" ADD HIDDEN") + .ToString() + }); } static bool CanSkipAlterColumnOperation(ColumnOperation first, ColumnOperation second) diff --git a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs index dcac5e48bec..76a4f5d6441 100644 --- a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs +++ b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs @@ -639,10 +639,10 @@ FROM [sys].[views] AS [v] table[SqlServerAnnotationNames.TemporalHistoryTableSchema] = historyTableSchema; var periodStartColumnName = reader.GetValueOrDefault("period_start_column"); - table[SqlServerAnnotationNames.TemporalPeriodStartColumnName] = periodStartColumnName; + table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName] = periodStartColumnName; var periodEndColumnName = reader.GetValueOrDefault("period_end_column"); - table[SqlServerAnnotationNames.TemporalPeriodEndColumnName] = periodEndColumnName; + table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName] = periodEndColumnName; } } @@ -690,12 +690,6 @@ private void GetColumns( [c].[collation_name], [c].[is_sparse]"; - if (SupportsTemporalTable()) - { - commandText += @", - [c].[generated_always_type]"; - } - commandText += @"FROM ( SELECT[v].[name], [v].[object_id], [v].[schema_id] @@ -720,7 +714,7 @@ UNION ALL if (SupportsTemporalTable()) { - commandText += " WHERE [c].[is_hidden] = 0"; + commandText += " WHERE [c].[generated_always_type] <> 1 AND [c].[generated_always_type] <> 2"; } commandText += @" @@ -758,7 +752,6 @@ UNION ALL var comment = dataRecord.GetValueOrDefault("comment"); var collation = dataRecord.GetValueOrDefault("collation_name"); var isSparse = dataRecord.GetValueOrDefault("is_sparse"); - var generatedAlwaysType = SupportsTemporalTable() ? dataRecord.GetValueOrDefault("generated_always_type") : 0; if (dataTypeName is null) { diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs index 78780767d07..bc41773e18f 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpDbContextGeneratorTest.cs @@ -1075,6 +1075,84 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) skipBuild: true); } + [ConditionalFact(Skip = "issue #26007")] + public void Temporal_table_works() + { + Test( + modelBuilder => modelBuilder.Entity( + "Customer", e => + { + e.Property("Id"); + e.Property("Name"); + e.HasKey("Id"); + e.ToTable(tb => tb.IsTemporal()); + }), + new ModelCodeGenerationOptions { UseDataAnnotations = false }, + code => + { + AssertFileContents( + @"using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata; + +namespace TestNamespace +{ + public partial class TestDbContext : DbContext + { + public TestDbContext() + { + } + + public TestDbContext(DbContextOptions options) + : base(options) + { + } + + public virtual DbSet Customer { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { +#warning " + DesignStrings.SensitiveInformationWarning + @" + optionsBuilder.UseSqlServer(""Initial Catalog=TestDatabase""); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.ToTable(tb => tb.IsTemporal(ttb => + { + ttb + .HasPeriodStart(""PeriodStart"") + .HasColumnName(""PeriodStart""); + ttb + .HasPeriodEnd(""PeriodEnd"") + .HasColumnName(""PeriodEnd""); + } +)); + + entity.Property(e => e.Id).UseIdentityColumn(); + }); + + OnModelCreatingPartial(modelBuilder); + } + + partial void OnModelCreatingPartial(ModelBuilder modelBuilder); + } +} +", + code.ContextFile); + }, + model => + { + // TODO + }); + } + protected override void AddModelServices(IServiceCollection services) { services.Replace(ServiceDescriptor.Singleton()); diff --git a/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs index 5527bbe1980..2a108deba81 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs @@ -1914,15 +1914,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("CustomerHistory", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("SystemTimeEnd", c.Name), - c => Assert.Equal("SystemTimeStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -1933,8 +1931,8 @@ await Test( EXEC(N'CREATE TABLE [Customer] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customer] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + N'].[CustomerHistory]))');"); @@ -1966,15 +1964,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("CustomerHistory", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -1985,8 +1981,8 @@ await Test( EXEC(N'CREATE TABLE [Customer] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [End] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [Start] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [End] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [Start] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customer] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([Start], [End]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + N'].[CustomerHistory]))');"); @@ -2018,16 +2014,14 @@ await Test( var table = Assert.Single(model.Tables); Assert.Equal("Customer", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); - Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("SystemTimeEnd", c.Name), - c => Assert.Equal("SystemTimeStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2038,8 +2032,8 @@ await Test( EXEC(N'CREATE TABLE [Customer] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customer] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + N'].[HistoryTable]))');"); @@ -2072,15 +2066,13 @@ await Test( Assert.Equal("mySchema", table.Schema); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("CustomerHistory", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("SystemTimeEnd", c.Name), - c => Assert.Equal("SystemTimeStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2092,8 +2084,8 @@ await Test( @"CREATE TABLE [mySchema].[Customers] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customers] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [mySchema].[CustomerHistory]));"); @@ -2130,15 +2122,13 @@ await Test( Assert.Equal("myDefaultSchema", table.Schema); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("CustomerHistory", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("SystemTimeEnd", c.Name), - c => Assert.Equal("SystemTimeStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2150,8 +2140,8 @@ await Test( @"CREATE TABLE [myDefaultSchema].[Customers] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customers] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [myDefaultSchema].[CustomerHistory]));"); @@ -2188,15 +2178,13 @@ await Test( Assert.Equal("mySchema", table.Schema); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("CustomerHistory", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("SystemTimeEnd", c.Name), - c => Assert.Equal("SystemTimeStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2208,8 +2196,8 @@ await Test( @"CREATE TABLE [mySchema].[Customers] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customers] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [mySchema].[CustomerHistory]));"); @@ -2246,15 +2234,13 @@ await Test( Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Equal("historySchema", table[SqlServerAnnotationNames.TemporalHistoryTableSchema]); - Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("SystemTimeEnd", c.Name), - c => Assert.Equal("SystemTimeStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2266,8 +2252,8 @@ await Test( @"CREATE TABLE [Customers] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customers] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [historySchema].[HistoryTable]));"); @@ -2409,16 +2395,14 @@ await Test( var table = Assert.Single(model.Tables); Assert.Equal("RenamedCustomers", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2473,16 +2457,14 @@ await Test( var table = Assert.Single(model.Tables); Assert.Equal("RenamedCustomers", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2538,16 +2520,14 @@ await Test( var table = Assert.Single(model.Tables); Assert.Equal("Customers", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Equal("RenamedHistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2595,17 +2575,15 @@ await Test( var table = Assert.Single(model.Tables); Assert.Equal("Customers", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Equal("modifiedHistorySchema", table[SqlServerAnnotationNames.TemporalHistoryTableSchema]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2660,17 +2638,15 @@ await Test( Assert.Equal("RenamedCustomers", table.Name); Assert.Equal("newSchema", table.Schema); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Equal("RenamedHistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Equal("newHistorySchema", table[SqlServerAnnotationNames.TemporalHistoryTableSchema]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2729,15 +2705,13 @@ await Test( var table = Assert.Single(model.Tables); Assert.Equal("Customers", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Collection( table.Columns, - c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Id", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -2813,15 +2787,13 @@ await Test( var table = Assert.Single(model.Tables); Assert.Equal("Customers", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Start", c.Name), c => Assert.Equal("Name", c.Name), c => Assert.Equal("Number", c.Name)); Assert.Same( @@ -3056,9 +3028,7 @@ await Test( Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("PeriodEnd", c.Name), - c => Assert.Equal("PeriodStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3071,6 +3041,10 @@ await Test( // @"ALTER TABLE [Customer] ADD PERIOD FOR SYSTEM_TIME ([PeriodStart], [PeriodEnd])", // + @"ALTER TABLE [Customer] ALTER COLUMN [PeriodStart] ADD HIDDEN", + // + @"ALTER TABLE [Customer] ALTER COLUMN [PeriodEnd] ADD HIDDEN", + // @"DECLARE @historyTableSchema sysname = SCHEMA_NAME() EXEC(N'ALTER TABLE [Customer] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + '].[CustomerHistory]))')"); } @@ -3113,9 +3087,7 @@ await Test( Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3124,6 +3096,10 @@ await Test( AssertSql( @"ALTER TABLE [Customer] ADD PERIOD FOR SYSTEM_TIME ([Start], [End])", // + @"ALTER TABLE [Customer] ALTER COLUMN [Start] ADD HIDDEN", + // + @"ALTER TABLE [Customer] ALTER COLUMN [End] ADD HIDDEN", + // @"DECLARE @historyTableSchema sysname = SCHEMA_NAME() EXEC(N'ALTER TABLE [Customer] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + '].[CustomerHistory]))')"); } @@ -3163,15 +3139,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3180,6 +3154,10 @@ await Test( AssertSql( @"ALTER TABLE [Customer] ADD PERIOD FOR SYSTEM_TIME ([Start], [End])", // + @"ALTER TABLE [Customer] ALTER COLUMN [Start] ADD HIDDEN", + // + @"ALTER TABLE [Customer] ALTER COLUMN [End] ADD HIDDEN", + // @"DECLARE @historyTableSchema sysname = SCHEMA_NAME() EXEC(N'ALTER TABLE [Customer] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + '].[HistoryTable]))')"); } @@ -3216,15 +3194,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.NotNull(table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3237,6 +3213,10 @@ await Test( // @"ALTER TABLE [Customer] ADD PERIOD FOR SYSTEM_TIME ([Start], [End])", // + @"ALTER TABLE [Customer] ALTER COLUMN [Start] ADD HIDDEN", + // + @"ALTER TABLE [Customer] ALTER COLUMN [End] ADD HIDDEN", + // @"DECLARE @historyTableSchema sysname = SCHEMA_NAME() EXEC(N'ALTER TABLE [Customer] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + '].[CustomerHistory]))')"); } @@ -3274,15 +3254,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3295,6 +3273,10 @@ await Test( // @"ALTER TABLE [Customer] ADD PERIOD FOR SYSTEM_TIME ([Start], [End])", // + @"ALTER TABLE [Customer] ALTER COLUMN [Start] ADD HIDDEN", + // + @"ALTER TABLE [Customer] ALTER COLUMN [End] ADD HIDDEN", + // @"DECLARE @historyTableSchema sysname = SCHEMA_NAME() EXEC(N'ALTER TABLE [Customer] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + '].[HistoryTable]))')"); } @@ -3341,15 +3323,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.NotNull(table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("ModifiedStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("ModifiedEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("ModifiedStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("ModifiedEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("ModifiedEnd", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("ModifiedStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3400,15 +3380,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.NotNull(table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("ModifiedStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("ModifiedEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("ModifiedStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("ModifiedEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("ModifiedEnd", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("ModifiedStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3447,15 +3425,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.NotNull(table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("SystemTimeEnd", c.Name), - c => Assert.Equal("SystemTimeStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3466,8 +3442,8 @@ await Test( EXEC(N'CREATE TABLE [Customer] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customer] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + N'].[CustomerHistory]))'); @@ -3514,15 +3490,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("End", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3550,6 +3524,10 @@ FROM [sys].[default_constraints] [d] // @"ALTER TABLE [Customer] ADD PERIOD FOR SYSTEM_TIME ([Start], [End])", // + @"ALTER TABLE [Customer] ALTER COLUMN [Start] ADD HIDDEN", + // + @"ALTER TABLE [Customer] ALTER COLUMN [End] ADD HIDDEN", + // @"DECLARE @historyTableSchema sysname = SCHEMA_NAME() EXEC(N'ALTER TABLE [Customer] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [' + @historyTableSchema + '].[HistoryTable]))')"); } @@ -3591,15 +3569,13 @@ await Test( Assert.Equal("Customer", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); Assert.NotNull(table[SqlServerAnnotationNames.TemporalHistoryTableName]); - Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("SystemTimeStart", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("SystemTimeEnd", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("Name", c.Name), - c => Assert.Equal("SystemTimeEnd", c.Name), - c => Assert.Equal("SystemTimeStart", c.Name)); + c => Assert.Equal("Name", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3655,18 +3631,16 @@ await Test( var table = Assert.Single(model.Tables); Assert.Equal("Customers", table.Name); Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); - Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartColumnName]); - Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndColumnName]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); Assert.Equal(2, table.Indexes.Count); Assert.Collection( table.Columns, c => Assert.Equal("Id", c.Name), - c => Assert.Equal("End", c.Name), c => Assert.Equal("Name", c.Name), - c => Assert.Equal("Number", c.Name), - c => Assert.Equal("Start", c.Name)); + c => Assert.Equal("Number", c.Name)); Assert.Same( table.Columns.Single(c => c.Name == "Id"), Assert.Single(table.PrimaryKey!.Columns)); @@ -3686,6 +3660,72 @@ FROM [sys].[default_constraints] [d] @"CREATE UNIQUE INDEX [IX_Customers_Number] ON [Customers] ([Number]);"); } + + [ConditionalFact] + public virtual async Task Add_index_on_period_column_to_temporal_table() + { + await Test( + builder => builder.Entity( + "Customer", e => + { + e.Property("Id").ValueGeneratedOnAdd(); + e.Property("Name"); + e.Property("Number"); + e.Property("Start").ValueGeneratedOnAddOrUpdate(); + e.Property("End").ValueGeneratedOnAddOrUpdate(); + e.HasKey("Id"); + + e.ToTable("Customers", tb => tb.IsTemporal(ttb => + { + ttb.UseHistoryTable("HistoryTable"); + ttb.HasPeriodStart("Start"); + ttb.HasPeriodEnd("End"); + })); + }), + + builder => { }, + builder => builder.Entity( + "Customer", e => + { + e.HasIndex("Start"); + e.HasIndex("End", "Name"); + }), + model => + { + var table = Assert.Single(model.Tables); + Assert.Equal("Customers", table.Name); + Assert.Equal(true, table[SqlServerAnnotationNames.IsTemporal]); + Assert.Equal("Start", table[SqlServerAnnotationNames.TemporalPeriodStartPropertyName]); + Assert.Equal("End", table[SqlServerAnnotationNames.TemporalPeriodEndPropertyName]); + Assert.Equal("HistoryTable", table[SqlServerAnnotationNames.TemporalHistoryTableName]); + + // TODO: issue #26008 - we don't reverse engineer indexes on period columns since the columns are not added to the database model + //Assert.Equal(2, table.Indexes.Count); + + Assert.Collection( + table.Columns, + c => Assert.Equal("Id", c.Name), + c => Assert.Equal("Name", c.Name), + c => Assert.Equal("Number", c.Name)); + Assert.Same( + table.Columns.Single(c => c.Name == "Id"), + Assert.Single(table.PrimaryKey!.Columns)); + }); + + AssertSql( + @"DECLARE @var0 sysname; +SELECT @var0 = [d].[name] +FROM [sys].[default_constraints] [d] +INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id] +WHERE ([d].[parent_object_id] = OBJECT_ID(N'[Customers]') AND [c].[name] = N'Name'); +IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [Customers] DROP CONSTRAINT [' + @var0 + '];'); +ALTER TABLE [Customers] ALTER COLUMN [Name] nvarchar(450) NULL;", + // + @"CREATE INDEX [IX_Customers_End_Name] ON [Customers] ([End], [Name]);", + // + @"CREATE INDEX [IX_Customers_Start] ON [Customers] ([Start]);"); + } + [ConditionalFact] public virtual async Task History_table_schema_created_when_necessary() { @@ -3725,8 +3765,8 @@ await Test( @"CREATE TABLE [mySchema].[Customers] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customers] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [mySchema2].[MyHistoryTable]));"); @@ -3784,8 +3824,8 @@ await Test( @"CREATE TABLE [mySchema].[Customers] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customers] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [mySchema].[CustomerHistory]));", @@ -3793,8 +3833,8 @@ PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) @"CREATE TABLE [mySchema].[Orders] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Orders] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [mySchema].[OrderHistory]));"); @@ -3856,8 +3896,8 @@ await Test( @"CREATE TABLE [mySchema].[Customers] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Customers] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [mySchema2].[CustomersHistoryTable]));", @@ -3865,8 +3905,8 @@ PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) @"CREATE TABLE [mySchema].[Orders] ( [Id] int NOT NULL, [Name] nvarchar(max) NULL, - [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END NOT NULL, - [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + [SystemTimeEnd] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL, + [SystemTimeStart] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL, CONSTRAINT [PK_Orders] PRIMARY KEY ([Id]), PERIOD FOR SYSTEM_TIME([SystemTimeStart], [SystemTimeEnd]) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [mySchema2].[OrdersHistoryTable]));"); diff --git a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs index b621213b02f..7a2a348999d 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/SqlServerDatabaseModelFactoryTest.cs @@ -1657,7 +1657,7 @@ NonSparse nvarchar(max) NULL [ConditionalFact] [SqlServerCondition(SqlServerCondition.SupportsHiddenColumns)] - public void Hidden_columns_are_not_created() + public void Hidden_period_columns_are_not_created() { Test( @" @@ -1692,6 +1692,43 @@ PERIOD FOR SYSTEM_TIME(SysStartTime, SysEndTime) "); } + [ConditionalFact] + [SqlServerCondition(SqlServerCondition.SupportsHiddenColumns)] + public void Period_columns_are_not_created() + { + Test( + @" +CREATE TABLE dbo.HiddenColumnsTable +( + Id int NOT NULL PRIMARY KEY CLUSTERED, + Name varchar(50) NOT NULL, + SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL, + SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL, + PERIOD FOR SYSTEM_TIME(SysStartTime, SysEndTime) +) +WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.HiddenColumnsTableHistory)); +CREATE INDEX IX_HiddenColumnsTable_1 ON dbo.HiddenColumnsTable ( Name, SysStartTime); +CREATE INDEX IX_HiddenColumnsTable_2 ON dbo.HiddenColumnsTable ( SysStartTime); +CREATE INDEX IX_HiddenColumnsTable_3 ON dbo.HiddenColumnsTable ( Name ); +", + Enumerable.Empty(), + Enumerable.Empty(), + dbModel => + { + var columns = dbModel.Tables.Single().Columns; + + Assert.Equal(2, columns.Count); + Assert.DoesNotContain(columns, c => c.Name == "SysStartTime"); + Assert.DoesNotContain(columns, c => c.Name == "SysEndTime"); + Assert.Equal("IX_HiddenColumnsTable_3", dbModel.Tables.Single().Indexes.Single().Name); + }, + @" +ALTER TABLE dbo.HiddenColumnsTable SET (SYSTEM_VERSIONING = OFF); +DROP TABLE dbo.HiddenColumnsTableHistory; +DROP TABLE dbo.HiddenColumnsTable; +"); + } + #endregion #region PrimaryKeyFacets From c7c94694a53de990d9090c0a744e7b0e1d046f2f Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Tue, 14 Sep 2021 09:14:58 -0700 Subject: [PATCH 106/346] Query: Add regression test for #19726 (#26002) Resolves #19726 --- .../Query/NorthwindSelectQueryCosmosTest.cs | 6 +++++ .../Query/NorthwindSelectQueryTestBase.cs | 25 +++++++++++++++++++ .../NorthwindSelectQuerySqlServerTest.cs | 12 +++++++++ 3 files changed, 43 insertions(+) diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindSelectQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindSelectQueryCosmosTest.cs index 44b895e4bb3..53caf32a5c4 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindSelectQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindSelectQueryCosmosTest.cs @@ -1320,6 +1320,12 @@ public override Task Projecting_count_of_navigation_which_is_generic_collection_ return base.Projecting_count_of_navigation_which_is_generic_collection_using_convert(async); } + [ConditionalTheory(Skip = "Cross collection join Issue#17246")] + public override Task MemberInit_in_projection_without_arguments(bool async) + { + return base.MemberInit_in_projection_without_arguments(async); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Specification.Tests/Query/NorthwindSelectQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindSelectQueryTestBase.cs index a2ed150b078..f5fd0c70f10 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindSelectQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindSelectQueryTestBase.cs @@ -2421,5 +2421,30 @@ public virtual Task Client_projection_with_string_initialization_with_scalar_sub AssertCollection(e.Collection, a.Collection, ordered: true); }); } + + private class OrderDto + { + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task MemberInit_in_projection_without_arguments(bool async) + { + return AssertQuery( + async, + ss => ss.Set() + .Where(c => c.CustomerID.StartsWith("F")) + .Select(c => new + { + c.CustomerID, + Orders = c.Orders.Select(o => new OrderDto()) + }), + elementSorter: e => e.CustomerID, + elementAsserter: (e, a) => + { + AssertEqual(e.CustomerID, a.CustomerID); + AssertEqual(e.Orders.Count(), a.Orders.Count()); + }); + } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs index b92fe8faec3..c8bd7504324 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs @@ -1866,6 +1866,18 @@ FROM [Customers] AS [c] WHERE [c].[CustomerID] LIKE N'F%'"); } + public override async Task MemberInit_in_projection_without_arguments(bool async) + { + await base.MemberInit_in_projection_without_arguments(async); + + AssertSql( + @"SELECT [c].[CustomerID], [o].[OrderID] +FROM [Customers] AS [c] +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +WHERE [c].[CustomerID] LIKE N'F%' +ORDER BY [c].[CustomerID]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); From 98c1052c840c350da10a01d2d664c39d53b0a196 Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Mon, 13 Sep 2021 14:21:02 -0700 Subject: [PATCH 107/346] Bundles: Copy NuGet.Config and global.json files Fixes #25622, fixes #25483 --- src/ef/Commands/MigrationsBundleCommand.cs | 52 ++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/src/ef/Commands/MigrationsBundleCommand.cs b/src/ef/Commands/MigrationsBundleCommand.cs index a8943cf1b17..4813e5876e8 100644 --- a/src/ef/Commands/MigrationsBundleCommand.cs +++ b/src/ef/Commands/MigrationsBundleCommand.cs @@ -78,10 +78,56 @@ protected override int Execute(string[] args) programGenerator.Initialize(); // TODO: We may not always have access to TEMP - var directory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - Directory.CreateDirectory(directory); + var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(tempDirectory); try { + var directory = tempDirectory; + + var globalJson = default(string); + var nugetConfigs = new Stack(); + + var searchPath = WorkingDir!.Value(); + do + { + foreach (var file in Directory.EnumerateFiles(searchPath)) + { + var fileName = Path.GetFileName(file); + if (fileName.Equals("NuGet.Config", StringComparison.OrdinalIgnoreCase)) + { + nugetConfigs.Push(file); + } + else if (globalJson == null + && fileName.Equals("global.json", StringComparison.OrdinalIgnoreCase)) + { + globalJson = file; + } + } + + searchPath = Path.GetDirectoryName(searchPath); + } + while (searchPath != null); + + while (nugetConfigs.Count > 1) + { + var nugetConfig = nugetConfigs.Pop(); + File.Copy(nugetConfig, Path.Combine(directory, Path.GetFileName(nugetConfig))); + + directory = Path.Combine(directory, Path.GetRandomFileName()); + Directory.CreateDirectory(directory); + } + + if (globalJson != null) + { + File.Copy(globalJson, Path.Combine(directory, Path.GetFileName(globalJson))); + } + + if (nugetConfigs.Count > 0) + { + var nugetConfig = nugetConfigs.Pop(); + File.Copy(nugetConfig, Path.Combine(directory, Path.GetFileName(nugetConfig))); + } + var publishArgs = new List { "publish" }; var runtime = _runtime!.HasValue() @@ -156,7 +202,7 @@ protected override int Execute(string[] args) } finally { - Directory.Delete(directory, recursive: true); + Directory.Delete(tempDirectory, recursive: true); } return base.Execute(args); From 65e3cbae57471c6115e343689ad08ce37b21a3e5 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Tue, 14 Sep 2021 09:31:26 -0700 Subject: [PATCH 108/346] Query: Avoid incorrect cast when simplifying null check (#26004) Resolves #19425 --- .../NullCheckRemovingExpressionVisitor.cs | 17 ++++++++++++- .../Extensions/TypeExtensions.cs | 2 -- .../Query/SimpleQueryTestBase.cs | 24 +++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs b/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs index 0e05e49e9ab..bd8912a4c93 100644 --- a/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.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; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; @@ -65,6 +66,20 @@ protected override Expression VisitConditional(ConditionalExpression conditional ? conditionalExpression.IfFalse : conditionalExpression.IfTrue; + if (accessOperation is UnaryExpression outerUnary + && (outerUnary.NodeType == ExpressionType.Convert + || outerUnary.NodeType == ExpressionType.ConvertChecked) + && accessOperation.Type.IsNullableType() + && accessOperation.Type.UnwrapNullableType() == outerUnary.Operand.Type + && outerUnary.Operand is UnaryExpression innerUnary + && (innerUnary.NodeType == ExpressionType.Convert + || innerUnary.NodeType == ExpressionType.ConvertChecked)) + { + // If expression is of type Convert(Convert(a, type), type?) + // then we convert it to Convert(a, type?) since a can be nullable after removing check + accessOperation = outerUnary.Update(innerUnary.Operand); + } + if (_nullSafeAccessVerifyingExpressionVisitor.Verify(caller, accessOperation)) { return accessOperation; @@ -153,7 +168,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) var operand = Visit(unaryExpression.Operand); if ((unaryExpression.NodeType == ExpressionType.Convert - || unaryExpression.NodeType == ExpressionType.ConvertChecked) + || unaryExpression.NodeType == ExpressionType.ConvertChecked) && _nullSafeAccesses.Contains(operand)) { _nullSafeAccesses.Add(unaryExpression); diff --git a/src/Microsoft.Data.Sqlite.Core/Extensions/TypeExtensions.cs b/src/Microsoft.Data.Sqlite.Core/Extensions/TypeExtensions.cs index a2985d37a4e..68fc5149bd7 100644 --- a/src/Microsoft.Data.Sqlite.Core/Extensions/TypeExtensions.cs +++ b/src/Microsoft.Data.Sqlite.Core/Extensions/TypeExtensions.cs @@ -1,8 +1,6 @@ // 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 System { diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs index b896faf9c18..90db5cc757e 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs @@ -174,6 +174,24 @@ public virtual async Task Comparing_byte_column_to_enum_in_vb_creating_double_ca : query.ToList(); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Null_check_removal_in_ternary_maintain_appropriate_cast(bool async) + { + var contextFactory = await InitializeAsync(); + using var context = contextFactory.CreateContext(); + + var query = from f in context.Food + select new + { + Bar = f.Taste != null ? (Taste)f.Taste : (Taste?)null + }; + + var bitterFood = async + ? await query.ToListAsync() + : query.ToList(); + } + protected class Context21770 : DbContext { public Context21770(DbContextOptions options) @@ -194,6 +212,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) new IceCream { IceCreamId = 2, Name = "Chocolate", Taste = (byte)Taste.Sweet }, new IceCream { IceCreamId = 3, Name = "Match", Taste = (byte)Taste.Bitter }); }); + + modelBuilder.Entity( + entity => + { + entity.HasData(new Food { Id = 1, Taste = null }); + }); } } From 576ab5235bc779d42f009b7845eeefb3dfdfeeaa Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Tue, 14 Sep 2021 09:31:33 -0700 Subject: [PATCH 109/346] Query: Add regression test for #21665 (#26009) Resolves #21665 --- ...plexNavigationsCollectionsQueryTestBase.cs | 48 ++++++++++++++++ ...tionsCollectionsSharedTypeQueryTestBase.cs | 2 + ...avigationsCollectionsQuerySqlServerTest.cs | 51 +++++++++++++++++ ...tionsCollectionsSplitQuerySqlServerTest.cs | 57 +++++++++++++++++++ ...exNavigationsCollectionsQuerySqliteTest.cs | 6 ++ ...igationsCollectionsSplitQuerySqliteTest.cs | 6 ++ 6 files changed, 170 insertions(+) diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs index dec01800930..1300d69f959 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsQueryTestBase.cs @@ -2536,5 +2536,53 @@ from l2 in ss.Set().Where(x => x.Level1_Required_Id == l1.Id * 2 || x.Na AssertCollection(e.Collection, a.Collection); }); } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Complex_query_issue_21665(bool async) + { + return AssertFirstOrDefault( + async, + ss => ss.Set() + .OrderBy(l1 => l1.Name) + .Select(l1 => new + { + Level1 = l1, + Level2Name = l1.OneToOne_Optional_FK1.Name, + ChildCount = l1.OneToMany_Optional_Self1.Count, + Level2Count = l1.OneToMany_Optional1.Count(), + IsLevel2There = l1.OneToMany_Optional1.Any(l2 => l2.Id == 2), + Children = l1.OneToMany_Optional_Self1 + .OrderBy(e => e.Name) + .Skip(1) + .Take(5) + .Select(lc1 => new + { + Level1 = lc1, + ChildCount = lc1.OneToMany_Optional_Self1.Count, + Level2Name = lc1.OneToOne_Optional_FK1.Name, + Level2Count = lc1.OneToMany_Optional1.Count(), + IsLevel2There = lc1.OneToMany_Optional1.Any(l2 => l2.Id == 2) + }) + }), + e => e.Level1.Id == 2, + asserter: (e, a) => + { + AssertEqual(e.Level1, a.Level1); + AssertEqual(e.Level2Name, a.Level2Name); + AssertEqual(e.ChildCount, a.ChildCount); + AssertEqual(e.Level2Count, a.Level2Count); + AssertEqual(e.IsLevel2There, a.IsLevel2There); + AssertCollection(e.Children, a.Children, ordered: true, + elementAsserter: (ee, aa) => + { + AssertEqual(ee.Level1, aa.Level1); + AssertEqual(ee.Level2Name, aa.Level2Name); + AssertEqual(ee.ChildCount, aa.ChildCount); + AssertEqual(ee.Level2Count, aa.Level2Count); + AssertEqual(ee.IsLevel2There, aa.IsLevel2There); + }); + }); + } } } diff --git a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryTestBase.cs index 673d140a1ed..9472c67b4e8 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryTestBase.cs @@ -62,5 +62,7 @@ public override Task Required_navigation_with_Include_ThenInclude(bool async) // Navigations used are not mapped in shared type. public override Task SelectMany_DefaultIfEmpty_multiple_times_with_joins_projecting_a_collection(bool async) => Task.CompletedTask; + + public override Task Complex_query_issue_21665(bool async) => Task.CompletedTask; } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs index 8f74e6adbde..85e4874710e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs @@ -2191,6 +2191,57 @@ FROM [LevelTwo] AS [l0] ORDER BY [l].[Id], [t].[Id]"); } + public override async Task Complex_query_issue_21665(bool async) + { + await base.Complex_query_issue_21665(async); + + AssertSql( + @"SELECT [t].[Id], [t].[Date], [t].[Name], [t].[OneToMany_Optional_Self_Inverse1Id], [t].[OneToMany_Required_Self_Inverse1Id], [t].[OneToOne_Optional_Self1Id], [t].[Name0], [t].[c], [t].[c0], [t].[c1], [t].[Id0], [t0].[Id], [t0].[Date], [t0].[Name], [t0].[OneToMany_Optional_Self_Inverse1Id], [t0].[OneToMany_Required_Self_Inverse1Id], [t0].[OneToOne_Optional_Self1Id], [t0].[ChildCount], [t0].[Level2Name], [t0].[Level2Count], [t0].[IsLevel2There], [t0].[Id0] +FROM ( + SELECT TOP(1) [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [l0].[Name] AS [Name0], ( + SELECT COUNT(*) + FROM [LevelOne] AS [l1] + WHERE [l].[Id] = [l1].[OneToMany_Optional_Self_Inverse1Id]) AS [c], ( + SELECT COUNT(*) + FROM [LevelTwo] AS [l2] + WHERE [l].[Id] = [l2].[OneToMany_Optional_Inverse2Id]) AS [c0], CASE + WHEN EXISTS ( + SELECT 1 + FROM [LevelTwo] AS [l3] + WHERE ([l].[Id] = [l3].[OneToMany_Optional_Inverse2Id]) AND ([l3].[Id] = 2)) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [c1], [l0].[Id] AS [Id0] + FROM [LevelOne] AS [l] + LEFT JOIN [LevelTwo] AS [l0] ON [l].[Id] = [l0].[Level1_Optional_Id] + WHERE [l].[Id] = 2 + ORDER BY [l].[Name] +) AS [t] +OUTER APPLY ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[OneToMany_Optional_Self_Inverse1Id], [t1].[OneToMany_Required_Self_Inverse1Id], [t1].[OneToOne_Optional_Self1Id], ( + SELECT COUNT(*) + FROM [LevelOne] AS [l5] + WHERE [t1].[Id] = [l5].[OneToMany_Optional_Self_Inverse1Id]) AS [ChildCount], [l4].[Name] AS [Level2Name], ( + SELECT COUNT(*) + FROM [LevelTwo] AS [l6] + WHERE [t1].[Id] = [l6].[OneToMany_Optional_Inverse2Id]) AS [Level2Count], CASE + WHEN EXISTS ( + SELECT 1 + FROM [LevelTwo] AS [l7] + WHERE ([t1].[Id] = [l7].[OneToMany_Optional_Inverse2Id]) AND ([l7].[Id] = 2)) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsLevel2There], [l4].[Id] AS [Id0] + FROM ( + SELECT [l8].[Id], [l8].[Date], [l8].[Name], [l8].[OneToMany_Optional_Self_Inverse1Id], [l8].[OneToMany_Required_Self_Inverse1Id], [l8].[OneToOne_Optional_Self1Id] + FROM [LevelOne] AS [l8] + WHERE [t].[Id] = [l8].[OneToMany_Optional_Self_Inverse1Id] + ORDER BY [l8].[Name] + OFFSET 1 ROWS FETCH NEXT 5 ROWS ONLY + ) AS [t1] + LEFT JOIN [LevelTwo] AS [l4] ON [t1].[Id] = [l4].[Level1_Optional_Id] +) AS [t0] +ORDER BY [t].[Name], [t].[Id], [t].[Id0], [t0].[Name], [t0].[Id]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs index 5b732bac485..58a87f74eec 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs @@ -3311,6 +3311,63 @@ FROM [LevelTwo] AS [l0] ORDER BY [l].[Id], [t].[Id]"); } + public override async Task Complex_query_issue_21665(bool async) + { + await base.Complex_query_issue_21665(async); + + AssertSql( + @"SELECT TOP(1) [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [l0].[Name], ( + SELECT COUNT(*) + FROM [LevelOne] AS [l1] + WHERE [l].[Id] = [l1].[OneToMany_Optional_Self_Inverse1Id]), ( + SELECT COUNT(*) + FROM [LevelTwo] AS [l2] + WHERE [l].[Id] = [l2].[OneToMany_Optional_Inverse2Id]), CASE + WHEN EXISTS ( + SELECT 1 + FROM [LevelTwo] AS [l3] + WHERE ([l].[Id] = [l3].[OneToMany_Optional_Inverse2Id]) AND ([l3].[Id] = 2)) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END, [l0].[Id] +FROM [LevelOne] AS [l] +LEFT JOIN [LevelTwo] AS [l0] ON [l].[Id] = [l0].[Level1_Optional_Id] +WHERE [l].[Id] = 2 +ORDER BY [l].[Name], [l].[Id], [l0].[Id]", + // + @"SELECT [t0].[Id], [t0].[Date], [t0].[Name], [t0].[OneToMany_Optional_Self_Inverse1Id], [t0].[OneToMany_Required_Self_Inverse1Id], [t0].[OneToOne_Optional_Self1Id], [t0].[ChildCount], [t0].[Level2Name], [t0].[Level2Count], [t0].[IsLevel2There], [t].[Id], [t].[Id0] +FROM ( + SELECT TOP(1) [l].[Id], [l0].[Id] AS [Id0], [l].[Name] + FROM [LevelOne] AS [l] + LEFT JOIN [LevelTwo] AS [l0] ON [l].[Id] = [l0].[Level1_Optional_Id] + WHERE [l].[Id] = 2 + ORDER BY [l].[Name] +) AS [t] +CROSS APPLY ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[OneToMany_Optional_Self_Inverse1Id], [t1].[OneToMany_Required_Self_Inverse1Id], [t1].[OneToOne_Optional_Self1Id], ( + SELECT COUNT(*) + FROM [LevelOne] AS [l2] + WHERE [t1].[Id] = [l2].[OneToMany_Optional_Self_Inverse1Id]) AS [ChildCount], [l1].[Name] AS [Level2Name], ( + SELECT COUNT(*) + FROM [LevelTwo] AS [l3] + WHERE [t1].[Id] = [l3].[OneToMany_Optional_Inverse2Id]) AS [Level2Count], CASE + WHEN EXISTS ( + SELECT 1 + FROM [LevelTwo] AS [l4] + WHERE ([t1].[Id] = [l4].[OneToMany_Optional_Inverse2Id]) AND ([l4].[Id] = 2)) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsLevel2There] + FROM ( + SELECT [l5].[Id], [l5].[Date], [l5].[Name], [l5].[OneToMany_Optional_Self_Inverse1Id], [l5].[OneToMany_Required_Self_Inverse1Id], [l5].[OneToOne_Optional_Self1Id] + FROM [LevelOne] AS [l5] + WHERE [t].[Id] = [l5].[OneToMany_Optional_Self_Inverse1Id] + ORDER BY [l5].[Name] + OFFSET 1 ROWS FETCH NEXT 5 ROWS ONLY + ) AS [t1] + LEFT JOIN [LevelTwo] AS [l1] ON [t1].[Id] = [l1].[Level1_Optional_Id] +) AS [t0] +ORDER BY [t].[Name], [t].[Id], [t].[Id0], [t0].[Name]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs index 89d2ec29f86..d27f1632862 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqliteTest.cs @@ -135,5 +135,11 @@ public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecti SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async))).Message); + + public override async Task Complex_query_issue_21665(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Complex_query_issue_21665(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs index 4ab44875707..275c2621a3b 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqliteTest.cs @@ -111,5 +111,11 @@ public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecti SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async))).Message); + + public override async Task Complex_query_issue_21665(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Complex_query_issue_21665(async))).Message); } } From 2482ecf6803a758c9d3f37717fe27d99748afba0 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Tue, 14 Sep 2021 09:31:41 -0700 Subject: [PATCH 110/346] Query: Translate object.Equals correctly when object argument passed with constant (#26010) Resolves #22981 --- src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs | 4 ++-- src/EFCore.Relational/Query/Internal/EqualsTranslator.cs | 4 ++-- .../Query/GearsOfWarQueryTestBase.cs | 9 +++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs b/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs index c4fe7042eb9..695d9a3ce95 100644 --- a/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/EqualsTranslator.cs @@ -68,8 +68,8 @@ public EqualsTranslator(ISqlExpressionFactory sqlExpressionFactory) && right != null) { return left.Type.UnwrapNullableType() == right.Type.UnwrapNullableType() - || (right.Type == typeof(object) && right is SqlParameterExpression) - || (left.Type == typeof(object) && left is SqlParameterExpression) + || (right.Type == typeof(object) && (right is SqlParameterExpression || right is SqlConstantExpression)) + || (left.Type == typeof(object) && (left is SqlParameterExpression || left is SqlConstantExpression)) ? _sqlExpressionFactory.Equal(left, right) : (SqlExpression)_sqlExpressionFactory.Constant(false); } diff --git a/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs index e42aa07009d..7f532d7cc66 100644 --- a/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/EqualsTranslator.cs @@ -68,8 +68,8 @@ public EqualsTranslator(ISqlExpressionFactory sqlExpressionFactory) && right != null) { if (left.Type == right.Type - || (right.Type == typeof(object) && right is SqlParameterExpression) - || (left.Type == typeof(object) && left is SqlParameterExpression)) + || (right.Type == typeof(object) && (right is SqlParameterExpression || right is SqlConstantExpression)) + || (left.Type == typeof(object) && (left is SqlParameterExpression || left is SqlConstantExpression))) { return _sqlExpressionFactory.Equal(left, right); } diff --git a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs index 7463273c50b..5a02d94205d 100644 --- a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs @@ -9118,6 +9118,15 @@ public virtual Task Project_navigation_defined_on_derived_from_entity_with_inher }); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Where_equals_method_on_nullable_with_object_overload(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(m => m.Rating.Equals(null))); + } + protected GearsOfWarContext CreateContext() => Fixture.CreateContext(); From a6b7d5987aa8017ccf5f45e39947dd5fcda8ddc3 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Tue, 14 Sep 2021 09:31:46 -0700 Subject: [PATCH 111/346] Query: Extract join predicate from Having for group by aggregate queries (#26011) Resolves #24474 --- .../Query/SqlExpressions/SelectExpression.cs | 98 ++++++++++--------- .../Query/NorthwindGroupByQueryTestBase.cs | 35 ++++++- .../NorthwindGroupByQuerySqlServerTest.cs | 30 ++++++ 3 files changed, 117 insertions(+), 46 deletions(-) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 3254d901ac7..676ef9ce4fb 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -2132,57 +2132,67 @@ static void GetPartitions(SelectExpression selectExpression, SqlExpression sqlEx static SqlExpression? TryExtractJoinKey(SelectExpression outer, SelectExpression inner, bool allowNonEquality) { - if (inner.Limit == null - && inner.Offset == null - && inner.Predicate != null) - { - var outerColumnExpressions = new List(); - var joinPredicate = TryExtractJoinKey( - outer, - inner, - inner.Predicate, - outerColumnExpressions, - allowNonEquality, - out var predicate); + if (inner.Limit != null + || inner.Offset != null) + { + return null; + } - if (joinPredicate != null) - { - joinPredicate = RemoveRedundantNullChecks(joinPredicate, outerColumnExpressions); - } - // TODO: verify the case for GroupBy. See issue#24474 - // We extract join predicate from Predicate part but GroupBy would have last Having. Changing predicate can change groupings + var predicate = inner.GroupBy.Count > 0 ? inner.Having : inner.Predicate; + if (predicate == null) + { + return null; + } - // we can't convert apply to join in case of distinct and groupby, if the projection doesn't already contain the join keys - // since we can't add the missing keys to the projection - only convert to join if all the keys are already there - if (joinPredicate != null - && (inner.IsDistinct - || inner.GroupBy.Count > 0)) - { - var innerKeyColumns = new List(); - InnerKeyColumns(inner.Tables, joinPredicate, innerKeyColumns); + var outerColumnExpressions = new List(); + var joinPredicate = TryExtractJoinKey( + outer, + inner, + predicate, + outerColumnExpressions, + allowNonEquality, + out var updatedPredicate); + + if (joinPredicate != null) + { + joinPredicate = RemoveRedundantNullChecks(joinPredicate, outerColumnExpressions); + } - // if projection has already been applied we can use it directly - // otherwise we extract future projection columns from projection mapping - // and based on that we determine whether we can convert from APPLY to JOIN - var projectionColumns = inner.Projection.Count > 0 - ? inner.Projection.Select(p => p.Expression) - : ExtractColumnsFromProjectionMapping(inner._projectionMapping); + // we can't convert apply to join in case of distinct and groupby, if the projection doesn't already contain the join keys + // since we can't add the missing keys to the projection - only convert to join if all the keys are already there + if (joinPredicate != null + && (inner.IsDistinct + || inner.GroupBy.Count > 0)) + { + var innerKeyColumns = new List(); + PopulateInnerKeyColumns(inner.Tables, joinPredicate, innerKeyColumns); + + // if projection has already been applied we can use it directly + // otherwise we extract future projection columns from projection mapping + // and based on that we determine whether we can convert from APPLY to JOIN + var projectionColumns = inner.Projection.Count > 0 + ? inner.Projection.Select(p => p.Expression) + : ExtractColumnsFromProjectionMapping(inner._projectionMapping); - foreach (var innerColumn in innerKeyColumns) + foreach (var innerColumn in innerKeyColumns) + { + if (!projectionColumns.Contains(innerColumn)) { - if (!projectionColumns.Contains(innerColumn)) - { - return null; - } + return null; } } + } - inner.Predicate = predicate; - - return joinPredicate; + if (inner.GroupBy.Count > 0) + { + inner.Having = updatedPredicate; + } + else + { + inner.Predicate = updatedPredicate; } - return null; + return joinPredicate; static SqlExpression? TryExtractJoinKey( SelectExpression outer, @@ -2310,12 +2320,12 @@ static bool IsContainedColumn(SelectExpression selectExpression, SqlExpression s } } - static void InnerKeyColumns(IEnumerable tables, SqlExpression joinPredicate, List resultColumns) + static void PopulateInnerKeyColumns(IEnumerable tables, SqlExpression joinPredicate, List resultColumns) { if (joinPredicate is SqlBinaryExpression sqlBinaryExpression) { - InnerKeyColumns(tables, sqlBinaryExpression.Left, resultColumns); - InnerKeyColumns(tables, sqlBinaryExpression.Right, resultColumns); + PopulateInnerKeyColumns(tables, sqlBinaryExpression.Left, resultColumns); + PopulateInnerKeyColumns(tables, sqlBinaryExpression.Right, resultColumns); } else if (joinPredicate is ColumnExpression columnExpression && tables.Contains(columnExpression.Table)) diff --git a/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs index 3fe9700ec58..f11d23ba64b 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs @@ -1898,6 +1898,37 @@ join o in ss.Set() on a.LastOrderID equals o.OrderID entryCount: 126); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_Aggregate_Join_converted_from_SelectMany(bool async) + { + return AssertQuery( + async, + ss => from c in ss.Set() + from o in ss.Set().GroupBy(o => o.CustomerID) + .Where(g => g.Count() > 5) + .Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(o => o.OrderID) }) + .Where(c1 => c.CustomerID == c1.CustomerID) + select c, + entryCount: 63); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_Aggregate_LeftJoin_converted_from_SelectMany(bool async) + { + return AssertQuery( + async, + ss => from c in ss.Set() + from o in ss.Set().GroupBy(o => o.CustomerID) + .Where(g => g.Count() > 5) + .Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(o => o.OrderID) }) + .Where(c1 => c.CustomerID == c1.CustomerID) + .DefaultIfEmpty() + select c, + entryCount: 91); + } + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Join_GroupBy_Aggregate_multijoins(bool async) @@ -2486,8 +2517,8 @@ public virtual Task GroupBy_aggregate_without_selectMany_selecting_first(bool as async, ss => from id in (from o in ss.Set() - group o by o.CustomerID into g - select g.Min(x => x.OrderID)) + group o by o.CustomerID into g + select g.Min(x => x.OrderID)) from o in ss.Set() where o.OrderID == id select o, diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs index e1fac97d2ad..1a474be074f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs @@ -1420,6 +1420,36 @@ HAVING COUNT(*) > 5 INNER JOIN [Orders] AS [o0] ON [t].[LastOrderID] = [o0].[OrderID]"); } + public override async Task GroupBy_Aggregate_Join_converted_from_SelectMany(bool async) + { + await base.GroupBy_Aggregate_Join_converted_from_SelectMany(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +INNER JOIN ( + SELECT [o].[CustomerID] + FROM [Orders] AS [o] + GROUP BY [o].[CustomerID] + HAVING COUNT(*) > 5 +) AS [t] ON [c].[CustomerID] = [t].[CustomerID]"); + } + + public override async Task GroupBy_Aggregate_LeftJoin_converted_from_SelectMany(bool async) + { + await base.GroupBy_Aggregate_LeftJoin_converted_from_SelectMany(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +LEFT JOIN ( + SELECT [o].[CustomerID], MAX([o].[OrderID]) AS [LastOrderID] + FROM [Orders] AS [o] + GROUP BY [o].[CustomerID] + HAVING COUNT(*) > 5 +) AS [t] ON [c].[CustomerID] = [t].[CustomerID]"); + } + public override async Task Join_GroupBy_Aggregate_multijoins(bool async) { await base.Join_GroupBy_Aggregate_multijoins(async); From 557255776b993bd296681b312e739de85f94ae36 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 09:54:38 -0700 Subject: [PATCH 112/346] Update dependencies from https://github.com/dotnet/arcade build 20210910.7 (#26012) Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk From Version 6.0.0-beta.21427.6 -> To Version 6.0.0-beta.21460.7 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 8 ++++---- eng/common/cross/toolchain.cmake | 4 ++-- eng/common/tools.ps1 | 11 +++++++++++ eng/common/tools.sh | 9 +++++++++ global.json | 8 ++++---- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 8d37bb0a99b..8dd64dd47bd 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -47,13 +47,13 @@ - + https://github.com/dotnet/arcade - 474307e526160c813c9fd58060eb8356ccca6099 + 7324320f814152b72295946847ca72413507705a - + https://github.com/dotnet/arcade - 474307e526160c813c9fd58060eb8356ccca6099 + 7324320f814152b72295946847ca72413507705a diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake index fc11001aa76..ec8971eb019 100644 --- a/eng/common/cross/toolchain.cmake +++ b/eng/common/cross/toolchain.cmake @@ -138,8 +138,8 @@ function(add_toolchain_linker_flag Flag) if (NOT Config STREQUAL "") set(CONFIG_SUFFIX "_${Config}") endif() - set("CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}" "${CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}} ${Flag}" PARENT_SCOPE) - set("CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}" "${CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}} ${Flag}" PARENT_SCOPE) + set("CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}_INIT" "${CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}_INIT} ${Flag}" PARENT_SCOPE) + set("CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}_INIT" "${CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}_INIT} ${Flag}" PARENT_SCOPE) endfunction() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 56ee4a577ac..02347914f5d 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -709,6 +709,15 @@ function MSBuild() { Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' } + if ($ci) { + $env:NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY = 'true' + $env:NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT = 6 + $env:NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS = 1000 + Write-PipelineSetVariable -Name 'NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY' -Value 'true' + Write-PipelineSetVariable -Name 'NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT' -Value '6' + Write-PipelineSetVariable -Name 'NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS' -Value '1000' + } + $toolsetBuildProject = InitializeToolset $basePath = Split-Path -parent $toolsetBuildProject $possiblePaths = @( @@ -717,6 +726,8 @@ function MSBuild() { (Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.Arcade.Sdk.dll')), (Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.ArcadeLogging.dll')), (Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.Arcade.Sdk.dll')) + (Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.ArcadeLogging.dll')), + (Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.Arcade.Sdk.dll')) ) $selectedPath = $null foreach ($path in $possiblePaths) { diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 41e323104df..6a4871ef72b 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -417,6 +417,13 @@ function MSBuild { export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" + + export NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY=true + export NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT=6 + export NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS=1000 + Write-PipelineSetVariable -name "NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY" -value "true" + Write-PipelineSetVariable -name "NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT" -value "6" + Write-PipelineSetVariable -name "NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS" -value "1000" fi local toolset_dir="${_InitializeToolset%/*}" @@ -427,6 +434,8 @@ function MSBuild { possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.Arcade.Sdk.dll" ) possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.ArcadeLogging.dll" ) possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.Arcade.Sdk.dll" ) + possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.ArcadeLogging.dll" ) + possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.Arcade.Sdk.dll" ) for path in "${possiblePaths[@]}"; do if [[ -f $path ]]; then selectedPath=$path diff --git a/global.json b/global.json index aa183d0c637..f9e7652b9e9 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "tools": { - "dotnet": "6.0.100-rc.1.21379.2", + "dotnet": "6.0.100-rc.1.21430.12", "runtimes": { "dotnet": [ "3.1.16", @@ -13,12 +13,12 @@ } }, "sdk": { - "version": "6.0.100-rc.1.21379.2", + "version": "6.0.100-rc.1.21430.12", "allowPrerelease": true, "rollForward": "latestMajor" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21427.6", - "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21427.6" + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21460.7", + "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21460.7" } } From 40f84af6856fe9453700b5df2a8859686c7bd4e5 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Tue, 14 Sep 2021 10:57:48 -0700 Subject: [PATCH 113/346] Remove OSX from helix build (#26020) Blocked by https://github.com/dotnet/core-eng/issues/14346 --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 29ff118beb0..d961fcc4395 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -197,12 +197,12 @@ stages: value: $(_BuildConfig) - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: HelixTargetQueues - value: Windows.10.Amd64.Open;Ubuntu.1804.Amd64.Open;OSX.1014.Amd64.Open;Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-sqlserver-amd64-20201109180804-3069967 + value: Windows.10.Amd64.Open;Ubuntu.1804.Amd64.Open;Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-sqlserver-amd64-20201109180804-3069967 - name: _HelixAccessToken value: '' # Needed for public queues - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: HelixTargetQueues - value: Windows.10.Amd64;Ubuntu.1804.Amd64;OSX.1014.Amd64;Ubuntu.1604.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-sqlserver-amd64-20201109180804-3069967 + value: Windows.10.Amd64;Ubuntu.1804.Amd64;Ubuntu.1604.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-sqlserver-amd64-20201109180804-3069967 - name: _HelixAccessToken value: $(HelixApiAccessToken) # Needed for internal queues steps: From fc00579c3c1933ae8ae31381e2ebfe412534db76 Mon Sep 17 00:00:00 2001 From: maumar Date: Wed, 8 Sep 2021 15:17:15 -0700 Subject: [PATCH 114/346] Fix to #19883 - Query: null semantics should keep track of columns that are guaranteed to be null and remove redundant IS NULL/ IS NOT NULL checks Adding a list of columns guaranteed to be null in the given subtree. When processing right side of the || operator, we can convert those to non-nullable columns and therefore improve the generated sql. Fixes #19883 Fixes #19410 --- .../Query/SqlNullabilityProcessor.cs | 78 ++++++++-- .../NorthwindFunctionsQueryCosmosTest.cs | 16 +- .../Query/NullSemanticsQueryTestBase.cs | 98 ++++++++++++ .../Query/NorthwindFunctionsQueryTestBase.cs | 40 ++--- .../NorthwindFunctionsQuerySqlServerTest.cs | 20 ++- .../Query/NullSemanticsQuerySqlServerTest.cs | 143 ++++++++++++++++++ .../NorthwindFunctionsQuerySqliteTest.cs | 29 ++++ 7 files changed, 387 insertions(+), 37 deletions(-) diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs index 010f6f80e75..381a8e1b791 100644 --- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs +++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs @@ -27,6 +27,7 @@ namespace Microsoft.EntityFrameworkCore.Query public class SqlNullabilityProcessor { private readonly List _nonNullableColumns; + private readonly List _nullValueColumns; private readonly ISqlExpressionFactory _sqlExpressionFactory; private bool _canCache; @@ -46,6 +47,7 @@ public SqlNullabilityProcessor( _sqlExpressionFactory = dependencies.SqlExpressionFactory; UseRelationalNulls = useRelationalNulls; _nonNullableColumns = new List(); + _nullValueColumns = new List(); ParameterValues = null!; } @@ -81,6 +83,7 @@ public virtual SelectExpression Process( _canCache = true; _nonNullableColumns.Clear(); + _nullValueColumns.Clear(); ParameterValues = parameterValues; var result = Visit(selectExpression); @@ -342,13 +345,13 @@ protected virtual SelectExpression Visit(SelectExpression selectExpression) /// An optimized sql expression. [return: NotNullIfNotNull("sqlExpression")] protected virtual SqlExpression? Visit(SqlExpression? sqlExpression, bool allowOptimizedExpansion, out bool nullable) - => Visit(sqlExpression, allowOptimizedExpansion, preserveNonNullableColumns: false, out nullable); + => Visit(sqlExpression, allowOptimizedExpansion, preserveColumnNullabilityInformation: false, out nullable); [return: NotNullIfNotNull("sqlExpression")] private SqlExpression? Visit( SqlExpression? sqlExpression, bool allowOptimizedExpansion, - bool preserveNonNullableColumns, + bool preserveColumnNullabilityInformation, out bool nullable) { if (sqlExpression == null) @@ -358,6 +361,7 @@ protected virtual SelectExpression Visit(SelectExpression selectExpression) } var nonNullableColumnsCount = _nonNullableColumns.Count; + var nullValueColumnsCount = _nullValueColumns.Count; var result = sqlExpression switch { CaseExpression caseExpression @@ -393,9 +397,10 @@ SqlUnaryExpression sqlUnaryExpression _ => VisitCustomSqlExpression(sqlExpression, allowOptimizedExpansion, out nullable) }; - if (!preserveNonNullableColumns) + if (!preserveColumnNullabilityInformation) { RestoreNonNullableColumnsList(nonNullableColumnsCount); + RestoreNullValueColumnsList(nullValueColumnsCount); } return result; @@ -430,6 +435,7 @@ protected virtual SqlExpression VisitCase(CaseExpression caseExpression, bool al // otherwise the result is nullable if any of the WhenClause results OR ElseResult is nullable nullable = caseExpression.ElseResult == null; var currentNonNullableColumnsCount = _nonNullableColumns.Count; + var currentNullValueColumnsCount = _nullValueColumns.Count; var operand = Visit(caseExpression.Operand, out _); var whenClauses = new List(); @@ -438,8 +444,8 @@ protected virtual SqlExpression VisitCase(CaseExpression caseExpression, bool al var testEvaluatesToTrue = false; foreach (var whenClause in caseExpression.WhenClauses) { - // we can use non-nullable column information we got from visiting Test, in the Result - var test = Visit(whenClause.Test, allowOptimizedExpansion: testIsCondition, preserveNonNullableColumns: true, out _); + // we can use column nullability information we got from visiting Test, in the Result + var test = Visit(whenClause.Test, allowOptimizedExpansion: testIsCondition, preserveColumnNullabilityInformation: true, out _); if (TryGetBoolConstantValue(test) is bool testConstantBool) { @@ -451,6 +457,7 @@ protected virtual SqlExpression VisitCase(CaseExpression caseExpression, bool al { // if test evaluates to 'false' we can remove the WhenClause RestoreNonNullableColumnsList(currentNonNullableColumnsCount); + RestoreNullValueColumnsList(currentNullValueColumnsCount); continue; } @@ -461,6 +468,7 @@ protected virtual SqlExpression VisitCase(CaseExpression caseExpression, bool al nullable |= resultNullable; whenClauses.Add(new CaseWhenClause(test, newResult)); RestoreNonNullableColumnsList(currentNonNullableColumnsCount); + RestoreNullValueColumnsList(currentNonNullableColumnsCount); // if test evaluates to 'true' we can remove every condition that comes after, including ElseResult if (testEvaluatesToTrue) @@ -476,6 +484,9 @@ protected virtual SqlExpression VisitCase(CaseExpression caseExpression, bool al nullable |= elseResultNullable; } + RestoreNonNullableColumnsList(currentNonNullableColumnsCount); + RestoreNullValueColumnsList(currentNullValueColumnsCount); + // if there are no whenClauses left (e.g. their tests evaluated to false): // - if there is Else block, return it // - if there is no Else block, return null @@ -830,16 +841,30 @@ protected virtual SqlExpression VisitSqlBinary( || sqlBinaryExpression.OperatorType == ExpressionType.OrElse); var currentNonNullableColumnsCount = _nonNullableColumns.Count; + var currentNullValueColumnsCount = _nullValueColumns.Count; - var left = Visit(sqlBinaryExpression.Left, allowOptimizedExpansion, preserveNonNullableColumns: true, out var leftNullable); + var left = Visit(sqlBinaryExpression.Left, allowOptimizedExpansion, preserveColumnNullabilityInformation: true, out var leftNullable); var leftNonNullableColumns = _nonNullableColumns.Skip(currentNonNullableColumnsCount).ToList(); + var leftNullValueColumns = _nullValueColumns.Skip(currentNullValueColumnsCount).ToList(); if (sqlBinaryExpression.OperatorType != ExpressionType.AndAlso) { RestoreNonNullableColumnsList(currentNonNullableColumnsCount); } - var right = Visit(sqlBinaryExpression.Right, allowOptimizedExpansion, preserveNonNullableColumns: true, out var rightNullable); + if (sqlBinaryExpression.OperatorType == ExpressionType.OrElse) + { + // in case of OrElse, we can assume all null value columns on the left side can be treated as non-nullable on the right + // e.g. (a == null || b == null) || f(a, b) + // f(a, b) will only be executed if a != null and b != null + _nonNullableColumns.AddRange(_nullValueColumns.Skip(currentNullValueColumnsCount).ToList()); + } + else + { + RestoreNullValueColumnsList(currentNullValueColumnsCount); + } + + var right = Visit(sqlBinaryExpression.Right, allowOptimizedExpansion, preserveColumnNullabilityInformation: true, out var rightNullable); if (sqlBinaryExpression.OperatorType == ExpressionType.OrElse) { @@ -853,6 +878,17 @@ protected virtual SqlExpression VisitSqlBinary( RestoreNonNullableColumnsList(currentNonNullableColumnsCount); } + if (sqlBinaryExpression.OperatorType == ExpressionType.AndAlso) + { + var intersect = leftNullValueColumns.Intersect(_nullValueColumns.Skip(currentNullValueColumnsCount)).ToList(); + RestoreNullValueColumnsList(currentNullValueColumnsCount); + _nullValueColumns.AddRange(intersect); + } + else if (sqlBinaryExpression.OperatorType != ExpressionType.OrElse) + { + RestoreNullValueColumnsList(currentNullValueColumnsCount); + } + // nullableStringColumn + a -> COALESCE(nullableStringColumn, "") + a if (sqlBinaryExpression.OperatorType == ExpressionType.Add && sqlBinaryExpression.Type == typeof(string)) @@ -886,10 +922,16 @@ protected virtual SqlExpression VisitSqlBinary( out nullable); if (optimized is SqlUnaryExpression optimizedUnary - && optimizedUnary.OperatorType == ExpressionType.NotEqual && optimizedUnary.Operand is ColumnExpression optimizedUnaryColumnOperand) { - _nonNullableColumns.Add(optimizedUnaryColumnOperand); + if (optimizedUnary.OperatorType == ExpressionType.NotEqual) + { + _nonNullableColumns.Add(optimizedUnaryColumnOperand); + } + else if (optimizedUnary.OperatorType == ExpressionType.Equal) + { + _nullValueColumns.Add(optimizedUnaryColumnOperand); + } } // we assume that NullSemantics rewrite is only needed (on the current level) @@ -1069,10 +1111,16 @@ protected virtual SqlExpression VisitSqlUnary( nullable = false; if (result is SqlUnaryExpression resultUnary - && resultUnary.OperatorType == ExpressionType.NotEqual && resultUnary.Operand is ColumnExpression resultColumnOperand) { - _nonNullableColumns.Add(resultColumnOperand); + if (resultUnary.OperatorType == ExpressionType.NotEqual) + { + _nonNullableColumns.Add(resultColumnOperand); + } + else if (resultUnary.OperatorType == ExpressionType.Equal) + { + _nullValueColumns.Add(resultColumnOperand); + } } return result; @@ -1099,6 +1147,14 @@ private void RestoreNonNullableColumnsList(int counter) } } + private void RestoreNullValueColumnsList(int counter) + { + if (counter < _nullValueColumns.Count) + { + _nullValueColumns.RemoveRange(counter, _nullValueColumns.Count - counter); + } + } + private SqlExpression ProcessJoinPredicate(SqlExpression predicate) { if (predicate is SqlBinaryExpression sqlBinaryExpression) diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs index 60f6ba46599..8277b093d62 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs @@ -1087,15 +1087,23 @@ FROM root c WHERE (c[""Discriminator""] = ""Customer"")"); } + [ConditionalTheory(Skip = "Issue #17246")] + public override async Task IsNullOrEmpty_negated_in_predicate(bool async) + { + await base.IsNullOrEmpty_negated_in_predicate(async); + + AssertSql(@""); + } + [ConditionalTheory(Skip = "Issue #17246")] public override Task IsNullOrWhiteSpace_in_predicate_on_non_nullable_column(bool async) { return base.IsNullOrWhiteSpace_in_predicate_on_non_nullable_column(async); } - public override void IsNullOrEmpty_in_projection() + public override async Task IsNullOrEmpty_in_projection(bool async) { - base.IsNullOrEmpty_in_projection(); + await base.IsNullOrEmpty_in_projection(async); AssertSql( @"SELECT c[""CustomerID""], c[""Region""] @@ -1103,9 +1111,9 @@ FROM root c WHERE (c[""Discriminator""] = ""Customer"")"); } - public override void IsNullOrEmpty_negated_in_projection() + public override async Task IsNullOrEmpty_negated_in_projection(bool async) { - base.IsNullOrEmpty_negated_in_projection(); + await base.IsNullOrEmpty_negated_in_projection(async); AssertSql( @"SELECT c[""CustomerID""], c[""Region""] diff --git a/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs index 0d6e703259c..36f31baf7f3 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs @@ -1756,6 +1756,104 @@ public virtual async Task Negated_contains_with_comparison_without_null_get_comb Assert.Equal(expected.Count, result.Count); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_simple(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(x => !(x.NullableStringA == null || x.NullableStringA != "Foo"))); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_negative(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(x => !(x.NullableStringA == null && x.NullableStringA != "Foo"))); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_nested(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(x => x.NullableStringA == null + || x.NullableStringB == null + || x.NullableStringA != x.NullableStringB)); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_intersection(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(x => (x.NullableStringA == null + && (x.StringA == "Foo" || x.NullableStringA == null || x.NullableStringB == null)) + || x.NullableStringA != x.NullableStringB)); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(x => x.NullableStringA == null + ? x.NullableStringA != x.NullableStringB + : x.NullableStringA != x.NullableStringC)); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_multiple(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(x => x.NullableStringA == null || x.NullableStringB == null + ? x.NullableStringA == x.NullableStringB + : x.NullableStringA != x.NullableStringB)); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_negative(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(x => (x.NullableStringA == null || x.NullableStringB == null) && x.NullableBoolC == null + ? x.NullableStringA == x.NullableStringB + : x.NullableStringA != x.NullableStringB)); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_with_setup(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(x => x.NullableBoolA == null + || (x.NullableBoolB == null + ? x.NullableBoolB != x.NullableBoolA + : x.NullableBoolA != x.NullableBoolB))); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_nested(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(x => x.NullableBoolA == null + ? x.BoolA == x.BoolB + : (x.NullableBoolC == null + ? x.NullableBoolA != x.NullableBoolC + : x.NullableBoolC != x.NullableBoolA))); + } + private string NormalizeDelimitersInRawString(string sql) => Fixture.TestStore.NormalizeDelimitersInRawString(sql); diff --git a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs index 6268fb54f7f..3b52258933b 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindFunctionsQueryTestBase.cs @@ -1681,28 +1681,34 @@ public virtual Task IsNullOrEmpty_in_predicate(bool async) entryCount: 60); } - [ConditionalFact] - public virtual void IsNullOrEmpty_in_projection() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task IsNullOrEmpty_in_projection(bool async) { - using var context = CreateContext(); - var query = context.Set() - .Select( - c => new { Id = c.CustomerID, Value = string.IsNullOrEmpty(c.Region) }) - .ToList(); - - Assert.Equal(91, query.Count); + return AssertQuery( + async, + ss => ss.Set().Select(c => new { Id = c.CustomerID, Value = string.IsNullOrEmpty(c.Region) }), + elementSorter: e => e.Id); } - [ConditionalFact] - public virtual void IsNullOrEmpty_negated_in_projection() + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task IsNullOrEmpty_negated_in_predicate(bool async) { - using var context = CreateContext(); - var query = context.Set() - .Select( - c => new { Id = c.CustomerID, Value = !string.IsNullOrEmpty(c.Region) }) - .ToList(); + return AssertQuery( + async, + ss => ss.Set().Where(c => !string.IsNullOrEmpty(c.Region)), + entryCount: 31); + } - Assert.Equal(91, query.Count); + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task IsNullOrEmpty_negated_in_projection(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Select(c => new { Id = c.CustomerID, Value = !string.IsNullOrEmpty(c.Region) }), + elementSorter: e => e.Id); } [ConditionalTheory] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs index 47592328412..ab3fd6d779f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs @@ -1656,9 +1656,9 @@ FROM [Customers] AS [c] WHERE [c].[Region] IS NULL OR ([c].[Region] LIKE N'')"); } - public override void IsNullOrEmpty_in_projection() + public override async Task IsNullOrEmpty_in_projection(bool async) { - base.IsNullOrEmpty_in_projection(); + await base.IsNullOrEmpty_in_projection(async); AssertSql( @"SELECT [c].[CustomerID] AS [Id], CASE @@ -1668,13 +1668,23 @@ END AS [Value] FROM [Customers] AS [c]"); } - public override void IsNullOrEmpty_negated_in_projection() + public override async Task IsNullOrEmpty_negated_in_predicate(bool async) { - base.IsNullOrEmpty_negated_in_projection(); + await base.IsNullOrEmpty_negated_in_predicate(async); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +WHERE [c].[Region] IS NOT NULL AND NOT ([c].[Region] LIKE N'')"); + } + + public override async Task IsNullOrEmpty_negated_in_projection(bool async) + { + await base.IsNullOrEmpty_negated_in_projection(async); AssertSql( @"SELECT [c].[CustomerID] AS [Id], CASE - WHEN NOT ([c].[Region] IS NULL OR ([c].[Region] LIKE N'')) THEN CAST(1 AS bit) + WHEN [c].[Region] IS NOT NULL AND NOT ([c].[Region] LIKE N'') THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS [Value] FROM [Customers] AS [c]"); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs index f6e48ec4d1b..086621ff24e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs @@ -2120,6 +2120,149 @@ ELSE CAST(0 AS bit) END"); } + public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_simple(bool async) + { + await base.Is_null_on_column_followed_by_OrElse_optimizes_nullability_simple(async); + + AssertSql( + @"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] +FROM [Entities1] AS [e] +WHERE [e].[NullableStringA] IS NOT NULL AND ([e].[NullableStringA] = N'Foo')"); + } + + public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_negative(bool async) + { + await base.Is_null_on_column_followed_by_OrElse_optimizes_nullability_negative(async); + + AssertSql( + @"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] +FROM [Entities1] AS [e] +WHERE [e].[NullableStringA] IS NOT NULL OR (([e].[NullableStringA] = N'Foo') AND [e].[NullableStringA] IS NOT NULL)"); + } + + public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_nested(bool async) + { + await base.Is_null_on_column_followed_by_OrElse_optimizes_nullability_nested(async); + + AssertSql( + @"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] +FROM [Entities1] AS [e] +WHERE ([e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL) OR ([e].[NullableStringA] <> [e].[NullableStringB])"); + } + + public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_intersection(bool async) + { + await base.Is_null_on_column_followed_by_OrElse_optimizes_nullability_intersection(async); + + AssertSql( + @"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] +FROM [Entities1] AS [e] +WHERE ([e].[NullableStringA] IS NULL AND ((([e].[StringA] = N'Foo') OR [e].[NullableStringA] IS NULL) OR [e].[NullableStringB] IS NULL)) OR (([e].[NullableStringA] <> [e].[NullableStringB]) OR [e].[NullableStringB] IS NULL)"); + } + + public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional(bool async) + { + await base.Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional(async); + + // issue #25977 + AssertSql( + @"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] +FROM [Entities1] AS [e] +WHERE CASE + WHEN [e].[NullableStringA] IS NULL THEN CASE + WHEN (([e].[NullableStringA] <> [e].[NullableStringB]) OR ([e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL)) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableStringB] IS NOT NULL) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END + ELSE CASE + WHEN (([e].[NullableStringA] <> [e].[NullableStringC]) OR ([e].[NullableStringA] IS NULL OR [e].[NullableStringC] IS NULL)) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableStringC] IS NOT NULL) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END +END = CAST(1 AS bit)"); + } + + public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_multiple(bool async) + { + await base.Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_multiple(async); + + // issue #25977 + AssertSql( + @"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] +FROM [Entities1] AS [e] +WHERE CASE + WHEN [e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL THEN CASE + WHEN (([e].[NullableStringA] = [e].[NullableStringB]) AND ([e].[NullableStringA] IS NOT NULL AND [e].[NullableStringB] IS NOT NULL)) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END + ELSE CASE + WHEN (([e].[NullableStringA] <> [e].[NullableStringB]) OR ([e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL)) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableStringB] IS NOT NULL) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END +END = CAST(1 AS bit)"); + } + + public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_negative(bool async) + { + await base.Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_negative(async); + + AssertSql( + @"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] +FROM [Entities1] AS [e] +WHERE CASE + WHEN ([e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL) AND ([e].[NullableBoolC] IS NULL) THEN CASE + WHEN (([e].[NullableStringA] = [e].[NullableStringB]) AND ([e].[NullableStringA] IS NOT NULL AND [e].[NullableStringB] IS NOT NULL)) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END + ELSE CASE + WHEN (([e].[NullableStringA] <> [e].[NullableStringB]) OR ([e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL)) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableStringB] IS NOT NULL) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END +END = CAST(1 AS bit)"); + } + + public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_with_setup(bool async) + { + await base.Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_with_setup(async); + + // issue #25977 + AssertSql( + @"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] +FROM [Entities1] AS [e] +WHERE ([e].[NullableBoolA] IS NULL) OR (CASE + WHEN [e].[NullableBoolB] IS NULL THEN CASE + WHEN ([e].[NullableBoolB] <> [e].[NullableBoolA]) OR ([e].[NullableBoolB] IS NULL) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END + ELSE CASE + WHEN ([e].[NullableBoolA] <> [e].[NullableBoolB]) OR ([e].[NullableBoolB] IS NULL) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END +END = CAST(1 AS bit))"); + } + + public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_nested(bool async) + { + await base.Is_null_on_column_followed_by_OrElse_optimizes_nullability_conditional_nested(async); + + // issue #25977 + AssertSql( + @"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] +FROM [Entities1] AS [e] +WHERE CASE + WHEN [e].[NullableBoolA] IS NULL THEN CASE + WHEN [e].[BoolA] = [e].[BoolB] THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END + WHEN [e].[NullableBoolC] IS NULL THEN CASE + WHEN (([e].[NullableBoolA] <> [e].[NullableBoolC]) OR (([e].[NullableBoolA] IS NULL) OR ([e].[NullableBoolC] IS NULL))) AND (([e].[NullableBoolA] IS NOT NULL) OR ([e].[NullableBoolC] IS NOT NULL)) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END + ELSE CASE + WHEN (([e].[NullableBoolC] <> [e].[NullableBoolA]) OR (([e].[NullableBoolC] IS NULL) OR ([e].[NullableBoolA] IS NULL))) AND (([e].[NullableBoolC] IS NOT NULL) OR ([e].[NullableBoolA] IS NOT NULL)) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END +END = CAST(1 AS bit)"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindFunctionsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindFunctionsQuerySqliteTest.cs index c81ec422dd8..54579cafef4 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindFunctionsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindFunctionsQuerySqliteTest.cs @@ -617,6 +617,35 @@ public override async Task Regex_IsMatch_MethodCall_constant_input(bool async) WHERE regexp(""c"".""CustomerID"", 'ALFKI')"); } + public override async Task IsNullOrEmpty_in_predicate(bool async) + { + await base.IsNullOrEmpty_in_predicate(async); + + AssertSql( + @"SELECT ""c"".""CustomerID"", ""c"".""Address"", ""c"".""City"", ""c"".""CompanyName"", ""c"".""ContactName"", ""c"".""ContactTitle"", ""c"".""Country"", ""c"".""Fax"", ""c"".""Phone"", ""c"".""PostalCode"", ""c"".""Region"" +FROM ""Customers"" AS ""c"" +WHERE ""c"".""Region"" IS NULL OR (""c"".""Region"" = '')"); + } + + public override async Task IsNullOrEmpty_in_projection(bool async) + { + await base.IsNullOrEmpty_in_projection(async); + + AssertSql( + @"SELECT ""c"".""CustomerID"" AS ""Id"", ""c"".""Region"" IS NULL OR (""c"".""Region"" = '') AS ""Value"" +FROM ""Customers"" AS ""c"""); + } + + public override async Task IsNullOrEmpty_negated_in_predicate(bool async) + { + await base.IsNullOrEmpty_negated_in_predicate(async); + + AssertSql( + @"SELECT ""c"".""CustomerID"", ""c"".""Address"", ""c"".""City"", ""c"".""CompanyName"", ""c"".""ContactName"", ""c"".""ContactTitle"", ""c"".""Country"", ""c"".""Fax"", ""c"".""Phone"", ""c"".""PostalCode"", ""c"".""Region"" +FROM ""Customers"" AS ""c"" +WHERE ""c"".""Region"" IS NOT NULL AND (""c"".""Region"" <> '')"); + } + public override Task Datetime_subtraction_TotalDays(bool async) { return AssertTranslationFailed(() => base.Datetime_subtraction_TotalDays(async)); From 0458d0817b71c467ecf950147fd6b2301d06e6a9 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Tue, 14 Sep 2021 21:54:41 +0200 Subject: [PATCH 115/346] Fix adding value-converted rowversion column (#25998) Fixes #25997 Closes #22980 --- .../SqlServerMigrationsSqlGenerator.cs | 7 ++++++- .../Migrations/MigrationsSqlServerTest.cs | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs index 8d6b0cf6be9..acb4ab15272 100644 --- a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs +++ b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs @@ -1614,7 +1614,12 @@ protected override void ColumnDefinition( builder.Append(operation.IsNullable ? " NULL" : " NOT NULL"); - DefaultValue(operation.DefaultValue, operation.DefaultValueSql, columnType, builder); + if (!string.Equals(columnType, "rowversion", StringComparison.OrdinalIgnoreCase) + && !string.Equals(columnType, "timestamp", StringComparison.OrdinalIgnoreCase)) + { + // rowversion/timestamp columns cannot have default values, but also don't need them when adding a new column. + DefaultValue(operation.DefaultValue, operation.DefaultValueSql, columnType, builder); + } var identity = operation[SqlServerAnnotationNames.Identity] as string; if (identity != null diff --git a/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs index 2a108deba81..750dded8aa2 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs @@ -375,6 +375,27 @@ await Test( @"ALTER TABLE [People] ADD [RowVersion] rowversion NULL;"); } + [ConditionalFact] + public virtual async Task Add_column_with_rowversion_and_value_conversion() + { + await Test( + builder => builder.Entity("People").Property("Id"), + builder => { }, + builder => builder.Entity("People").Property("RowVersion") + .IsRowVersion() + .HasConversion(), + model => + { + var table = Assert.Single(model.Tables); + var column = Assert.Single(table.Columns, c => c.Name == "RowVersion"); + Assert.Equal("rowversion", column.StoreType); + Assert.True(column.IsRowVersion()); + }); + + AssertSql( + @"ALTER TABLE [People] ADD [RowVersion] rowversion NOT NULL;"); + } + public override async Task Add_column_with_defaultValueSql() { await base.Add_column_with_defaultValueSql(); From d31ba4b15595488127efec04a41732327f09ba64 Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Tue, 14 Sep 2021 11:54:37 -0700 Subject: [PATCH 116/346] Tools: Pass absolute project paths to ef.exe Fixes #25625 --- src/dotnet-ef/RootCommand.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dotnet-ef/RootCommand.cs b/src/dotnet-ef/RootCommand.cs index c6497d3d649..9c0ff014884 100644 --- a/src/dotnet-ef/RootCommand.cs +++ b/src/dotnet-ef/RootCommand.cs @@ -279,9 +279,14 @@ private static List ResolveProjects(string? path) { path = Directory.GetCurrentDirectory(); } - else if (!Directory.Exists(path)) // It's not a directory + else { - return new List { path }; + path = Path.GetFullPath(path); + + if (!Directory.Exists(path)) // It's not a directory + { + return new List { path }; + } } var projectFiles = Directory.EnumerateFiles(path, "*.*proj", SearchOption.TopDirectoryOnly) From 704f6893685dfdd109c990ab28975894f4035c11 Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Tue, 14 Sep 2021 12:02:32 -0700 Subject: [PATCH 117/346] :arrow_up: Update to .NET SDK 6.0 RC1 --- global.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/global.json b/global.json index f9e7652b9e9..a70a92f9ac8 100644 --- a/global.json +++ b/global.json @@ -1,19 +1,19 @@ { "tools": { - "dotnet": "6.0.100-rc.1.21430.12", + "dotnet": "6.0.100-rc.1.21458.32", "runtimes": { "dotnet": [ - "3.1.16", - "5.0.7" + "3.1.19", + "5.0.10" ], "aspnetcore": [ - "3.1.16", - "5.0.7" + "3.1.19", + "5.0.10" ] } }, "sdk": { - "version": "6.0.100-rc.1.21430.12", + "version": "6.0.100-rc.1.21458.32", "allowPrerelease": true, "rollForward": "latestMajor" }, From 919dd8fb761b42e2e3ed88b4053be4fbd99672d8 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Tue, 14 Sep 2021 16:40:46 -0700 Subject: [PATCH 118/346] List shared-identity entries for STETs Remove null-checking code for IProperty.GetValueComparer() Make DebugString terser for Indexes and keys on STETs Remove extra UsingEntity in ManyToManyQueryFixtureBase Fixes #23418 --- .../Internal/MigrationsModelDiffer.cs | 5 +- ...sitor.ShaperProcessingExpressionVisitor.cs | 17 +- .../Update/ColumnModification.cs | 4 +- .../Update/ModificationCommand.cs | 18 +- .../ChangeTracking/Internal/ChangeDetector.cs | 16 +- .../Internal/EntityGraphAttacher.cs | 2 +- .../Internal/EntityReferenceMap.cs | 36 ++- .../ChangeTracking/Internal/IStateManager.cs | 6 +- .../Internal/InternalEntityEntry.cs | 8 +- .../ChangeTracking/Internal/OriginalValues.cs | 6 +- .../ChangeTracking/Internal/SidecarValues.cs | 6 +- .../ChangeTracking/Internal/StateManager.cs | 16 +- .../Internal/StateManagerExtensions.cs | 9 +- .../Extensions/PropertyBaseExtensions.cs | 2 +- src/EFCore/Metadata/IReadOnlyIndex.cs | 2 +- src/EFCore/Metadata/IReadOnlyKey.cs | 2 +- src/EFCore/Metadata/IReadOnlyTypeBase.cs | 15 +- .../Migrations/ModelSnapshotSqlServerTest.cs | 2 +- .../ManyToManyTrackingTestBase.cs | 26 +- .../Query/ManyToManyQueryFixtureBase.cs | 32 +- .../ManyToManyModel/ManyToManyData.cs | 38 +-- .../ManyToManyNoTrackingQuerySqlServerTest.cs | 277 ++++++++--------- .../Query/ManyToManyQuerySqlServerTest.cs | 284 +++++++++--------- ...TManyToManyNoTrackingQuerySqlServerTest.cs | 274 ++++++++--------- .../Query/TPTManyToManyQuerySqlServerTest.cs | 283 ++++++++--------- .../ChangeTracking/ChangeTrackerTest.cs | 20 ++ .../ChangeTracking/Internal/OwnedFixupTest.cs | 40 +-- .../TestUtilities/FakeStateManager.cs | 6 +- 28 files changed, 714 insertions(+), 738 deletions(-) diff --git a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs index 8952357e1ce..0dd6e7d2b5a 100644 --- a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs +++ b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs @@ -2018,12 +2018,11 @@ protected virtual void TrackData( var sourceValue = sourceEntry.GetCurrentValue(sourceProperty); var targetValue = entry.GetCurrentValue(targetProperty); - var comparer = targetProperty.GetValueComparer() - ?? sourceProperty.GetValueComparer(); + var comparer = targetProperty.GetValueComparer(); var modelValuesChanged = sourceProperty.ClrType.UnwrapNullableType() == targetProperty.ClrType.UnwrapNullableType() - && comparer?.Equals(sourceValue, targetValue) == false; + && comparer.Equals(sourceValue, targetValue) == false; if (!modelValuesChanged) { diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index a67cdf1c8f2..e8f91528e16 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -1877,23 +1877,16 @@ private static async Task TaskAwaiter(Func[] taskFactories) private static bool CompareIdentifiers(IReadOnlyList valueComparers, object[] left, object[] right) { - if (valueComparers != null) + // Ignoring size check on all for perf as they should be same unless bug in code. + for (var i = 0; i < left.Length; i++) { - // Ignoring size check on all for perf as they should be same unless bug in code. - for (var i = 0; i < left.Length; i++) + if (!valueComparers[i].Equals(left[i], right[i])) { - if (valueComparers[i] != null - ? !valueComparers[i].Equals(left[i], right[i]) - : !Equals(left[i], right[i])) - { - return false; - } + return false; } - - return true; } - return StructuralComparisons.StructuralEqualityComparer.Equals(left, right); + return true; } private sealed class CollectionShaperFindingExpressionVisitor : ExpressionVisitor diff --git a/src/EFCore.Relational/Update/ColumnModification.cs b/src/EFCore.Relational/Update/ColumnModification.cs index 024cb3b38cc..94f4026d3b3 100644 --- a/src/EFCore.Relational/Update/ColumnModification.cs +++ b/src/EFCore.Relational/Update/ColumnModification.cs @@ -423,7 +423,7 @@ public virtual void AddSharedColumnModification(IColumnModification modification _sharedColumnModifications ??= new List(); if (UseCurrentValueParameter - && !StructuralComparisons.StructuralEqualityComparer.Equals(Value, modification.Value)) + && !modification.Property.GetValueComparer().Equals(Value, modification.Value)) { if (_sensitiveLoggingEnabled) { @@ -447,7 +447,7 @@ public virtual void AddSharedColumnModification(IColumnModification modification } if (UseOriginalValueParameter - && !StructuralComparisons.StructuralEqualityComparer.Equals(OriginalValue, modification.OriginalValue)) + && !modification.Property.GetValueComparer().Equals(OriginalValue, modification.OriginalValue)) { if (Entry.EntityState == EntityState.Modified && modification.Entry.EntityState == EntityState.Added diff --git a/src/EFCore.Relational/Update/ModificationCommand.cs b/src/EFCore.Relational/Update/ModificationCommand.cs index 35cd9b97e19..85de9f58d8a 100644 --- a/src/EFCore.Relational/Update/ModificationCommand.cs +++ b/src/EFCore.Relational/Update/ModificationCommand.cs @@ -270,7 +270,9 @@ private List GenerateColumnModifications() if (entry.SharedIdentityEntry != null) { - var sharedTableMapping = GetTableMapping(entry.SharedIdentityEntry.EntityType); + var sharedTableMapping = entry.EntityType != entry.SharedIdentityEntry.EntityType + ? GetTableMapping(entry.SharedIdentityEntry.EntityType) + : tableMapping; if (sharedTableMapping != null) { InitializeSharedColumns(entry.SharedIdentityEntry, sharedTableMapping, updating, sharedTableColumnMap); @@ -482,16 +484,7 @@ public void RecordValue(IProperty property, IUpdateEntry entry) break; case EntityState.Added: _currentValue = entry.GetCurrentValue(property); - - var comparer = property.GetValueComparer(); - if (comparer == null) - { - _write = !Equals(_originalValue, _currentValue); - } - else - { - _write = !comparer.Equals(_originalValue, _currentValue); - } + _write = !property.GetValueComparer().Equals(_originalValue, _currentValue); break; case EntityState.Deleted: @@ -512,7 +505,8 @@ public bool TryPropagate(IProperty property, IUpdateEntry entry) if (_write && (entry.EntityState == EntityState.Unchanged || (entry.EntityState == EntityState.Modified && !entry.IsModified(property)) - || (entry.EntityState == EntityState.Added && Equals(_originalValue, entry.GetCurrentValue(property))))) + || (entry.EntityState == EntityState.Added + && property.GetValueComparer().Equals(_originalValue, entry.GetCurrentValue(property))))) { entry.SetStoreGeneratedValue(property, _currentValue); diff --git a/src/EFCore/ChangeTracking/Internal/ChangeDetector.cs b/src/EFCore/ChangeTracking/Internal/ChangeDetector.cs index ed5e0721928..39baad40602 100644 --- a/src/EFCore/ChangeTracking/Internal/ChangeDetector.cs +++ b/src/EFCore/ChangeTracking/Internal/ChangeDetector.cs @@ -208,21 +208,7 @@ private void LocalDetectChanges(InternalEntityEntry entry) var current = entry[property]; var original = entry.GetOriginalValue(property); - var comparer = property.GetValueComparer(); - - if (comparer == null) - { - if (!Equals(current, original)) - { - SetPropertyModified(); - } - } - else if (!comparer.Equals(current, original)) - { - SetPropertyModified(); - } - - void SetPropertyModified() + if (!property.GetValueComparer().Equals(current, original)) { if (entry.EntityState == EntityState.Deleted) { diff --git a/src/EFCore/ChangeTracking/Internal/EntityGraphAttacher.cs b/src/EFCore/ChangeTracking/Internal/EntityGraphAttacher.cs index 174be047501..b52caacce51 100644 --- a/src/EFCore/ChangeTracking/Internal/EntityGraphAttacher.cs +++ b/src/EFCore/ChangeTracking/Internal/EntityGraphAttacher.cs @@ -124,7 +124,7 @@ private static bool PaintAction( ? (isGenerated ? storeGenTargetState : targetState) : EntityState.Added, // Key can only be not-set if it is store-generated acceptChanges: true, - forceStateWhenUnknownKey: force ? (EntityState?)targetState : null); + forceStateWhenUnknownKey: force ? targetState : null); return true; } diff --git a/src/EFCore/ChangeTracking/Internal/EntityReferenceMap.cs b/src/EFCore/ChangeTracking/Internal/EntityReferenceMap.cs index aad2c22566e..0e6e5dba116 100644 --- a/src/EFCore/ChangeTracking/Internal/EntityReferenceMap.cs +++ b/src/EFCore/ChangeTracking/Internal/EntityReferenceMap.cs @@ -178,10 +178,7 @@ public virtual bool TryGet( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual int GetCountForState( - bool added = false, - bool modified = false, - bool deleted = false, - bool unchanged = false) + bool added, bool modified, bool deleted, bool unchanged, bool countDeletedSharedIdentity) { var count = 0; @@ -200,7 +197,9 @@ public virtual int GetCountForState( if (deleted && _deletedReferenceMap != null) { - count += _deletedReferenceMap.Count; + count += countDeletedSharedIdentity + ? _deletedReferenceMap.Count + : _deletedReferenceMap.Count(p => p.Value.SharedIdentityEntry == null); } if (unchanged @@ -213,7 +212,7 @@ public virtual int GetCountForState( { foreach (var map in _sharedTypeReferenceMap) { - count += map.Value.GetCountForState(added, modified, deleted, unchanged); + count += map.Value.GetCountForState(added, modified, deleted, unchanged, countDeletedSharedIdentity); } } @@ -227,10 +226,7 @@ public virtual int GetCountForState( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual IEnumerable GetEntriesForState( - bool added = false, - bool modified = false, - bool deleted = false, - bool unchanged = false) + bool added, bool modified, bool deleted, bool unchanged, bool returnDeletedSharedIdentity) { // Perf sensitive @@ -298,7 +294,8 @@ var numberOfStates return GetEntriesForState( added, modified, deleted, unchanged, hasSharedTypes, - returnAdded, returnModified, returnDeleted, returnUnchanged); + returnAdded, returnModified, returnDeleted, returnUnchanged, + returnDeletedSharedIdentity); } private IEnumerable GetEntriesForState( @@ -310,7 +307,8 @@ private IEnumerable GetEntriesForState( bool returnAdded, bool returnModified, bool returnDeleted, - bool returnUnchanged) + bool returnUnchanged, + bool returnSharedIdentity) { if (returnAdded) { @@ -332,7 +330,11 @@ private IEnumerable GetEntriesForState( { foreach (var entry in _deletedReferenceMap!.Values) { - yield return entry; + if (entry.SharedIdentityEntry == null + || returnSharedIdentity) + { + yield return entry; + } } } @@ -348,13 +350,9 @@ private IEnumerable GetEntriesForState( { foreach (var subMap in _sharedTypeReferenceMap!.Values) { - foreach (var entry in subMap.GetEntriesForState(added, modified, deleted, unchanged)) + foreach (var entry in subMap.GetEntriesForState(added, modified, deleted, unchanged, returnSharedIdentity)) { - if ((entry.SharedIdentityEntry == null - || entry.EntityState != EntityState.Deleted)) - { - yield return entry; - } + yield return entry; } } } diff --git a/src/EFCore/ChangeTracking/Internal/IStateManager.cs b/src/EFCore/ChangeTracking/Internal/IStateManager.cs index 8a757981f46..4259fcd670f 100644 --- a/src/EFCore/ChangeTracking/Internal/IStateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/IStateManager.cs @@ -149,7 +149,8 @@ IEnumerable GetEntriesForState( bool added = false, bool modified = false, bool deleted = false, - bool unchanged = false); + bool unchanged = false, + bool returnSharedIdentity = false); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -161,7 +162,8 @@ int GetCountForState( bool added = false, bool modified = false, bool deleted = false, - bool unchanged = false); + bool unchanged = false, + bool returnSharedIdentity = false); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index 29896d0e998..c86407f1bfd 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -1391,13 +1391,7 @@ public void HandleNullForeignKey( } private static Func ValuesEqualFunc(IProperty property) - { - var comparer = property.GetValueComparer(); - - return comparer != null - ? (Func)((l, r) => comparer.Equals(l, r)) - : (l, r) => Equals(l, r); - } + => property.GetValueComparer().Equals; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/ChangeTracking/Internal/OriginalValues.cs b/src/EFCore/ChangeTracking/Internal/OriginalValues.cs index 1bef2ae9a44..7d0fb1ba7c2 100644 --- a/src/EFCore/ChangeTracking/Internal/OriginalValues.cs +++ b/src/EFCore/ChangeTracking/Internal/OriginalValues.cs @@ -104,11 +104,7 @@ public void AcceptChanges(InternalEntityEntry entry) } private static object? SnapshotValue(IProperty property, object? value) - { - var comparer = property.GetValueComparer(); - - return comparer == null ? value : comparer.Snapshot(value); - } + => property.GetValueComparer().Snapshot(value); public bool IsEmpty => _values == null; diff --git a/src/EFCore/ChangeTracking/Internal/SidecarValues.cs b/src/EFCore/ChangeTracking/Internal/SidecarValues.cs index cfb96a663ad..7a3ffba7ab0 100644 --- a/src/EFCore/ChangeTracking/Internal/SidecarValues.cs +++ b/src/EFCore/ChangeTracking/Internal/SidecarValues.cs @@ -50,11 +50,7 @@ public void SetValue(IProperty property, object? value, int index) } private static object? SnapshotValue(IProperty property, object? value) - { - var comparer = property.GetValueComparer(); - - return comparer == null ? value : comparer.Snapshot(value); - } + => property.GetValueComparer().Snapshot(value); public bool IsEmpty => _values == null; diff --git a/src/EFCore/ChangeTracking/Internal/StateManager.cs b/src/EFCore/ChangeTracking/Internal/StateManager.cs index e694e0eafd1..92bfb477ded 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManager.cs @@ -415,7 +415,7 @@ public virtual InternalEntityEntry StartTrackingFromQuery( ? throwOnTypeMismatch ? throw new InvalidOperationException( CoreStrings.TrackingTypeMismatch(entry.EntityType.DisplayName(), entityType.DisplayName())) - : (InternalEntityEntry?)null + : null : entry : null; @@ -496,8 +496,9 @@ public virtual int GetCountForState( bool added = false, bool modified = false, bool deleted = false, - bool unchanged = false) - => _entityReferenceMap.GetCountForState(added, modified, deleted, unchanged); + bool unchanged = false, + bool countDeletedSharedIdentity = false) + => _entityReferenceMap.GetCountForState(added, modified, deleted, unchanged, countDeletedSharedIdentity); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -506,7 +507,7 @@ public virtual int GetCountForState( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual int Count - => GetCountForState(added: true, modified: true, deleted: true, unchanged: true); + => GetCountForState(added: true, modified: true, deleted: true, unchanged: true, countDeletedSharedIdentity: true); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -518,8 +519,9 @@ public virtual IEnumerable GetEntriesForState( bool added = false, bool modified = false, bool deleted = false, - bool unchanged = false) - => _entityReferenceMap.GetEntriesForState(added, modified, deleted, unchanged); + bool unchanged = false, + bool returnDeletedSharedIdentity = false) + => _entityReferenceMap.GetEntriesForState(added, modified, deleted, unchanged, returnDeletedSharedIdentity); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -528,7 +530,7 @@ public virtual IEnumerable GetEntriesForState( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual IEnumerable Entries - => GetEntriesForState(added: true, modified: true, deleted: true, unchanged: true); + => GetEntriesForState(added: true, modified: true, deleted: true, unchanged: true, returnDeletedSharedIdentity: true); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/ChangeTracking/Internal/StateManagerExtensions.cs b/src/EFCore/ChangeTracking/Internal/StateManagerExtensions.cs index 8bb7f336879..96b12757b64 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManagerExtensions.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManagerExtensions.cs @@ -24,12 +24,13 @@ public static IReadOnlyList ToListForState( bool added = false, bool modified = false, bool deleted = false, - bool unchanged = false) + bool unchanged = false, + bool returnDeletedSharedIdentity = false) { var list = new List( - stateManager.GetCountForState(added, modified, deleted, unchanged)); + stateManager.GetCountForState(added, modified, deleted, unchanged, returnDeletedSharedIdentity)); - foreach (var entry in stateManager.GetEntriesForState(added, modified, deleted, unchanged)) + foreach (var entry in stateManager.GetEntriesForState(added, modified, deleted, unchanged, returnDeletedSharedIdentity)) { list.Add(entry); } @@ -45,6 +46,6 @@ public static IReadOnlyList ToListForState( /// public static IReadOnlyList ToList( this IStateManager stateManager) - => stateManager.ToListForState(added: true, modified: true, deleted: true, unchanged: true); + => stateManager.ToListForState(added: true, modified: true, deleted: true, unchanged: true, returnDeletedSharedIdentity: true); } } diff --git a/src/EFCore/Extensions/PropertyBaseExtensions.cs b/src/EFCore/Extensions/PropertyBaseExtensions.cs index c236d9f0dd4..7d6777a3caa 100644 --- a/src/EFCore/Extensions/PropertyBaseExtensions.cs +++ b/src/EFCore/Extensions/PropertyBaseExtensions.cs @@ -33,7 +33,7 @@ public static bool IsShadowProperty(this IPropertyBase property) /// when throwing exceptions about keys, indexes, etc. that use the properties. /// /// The properties to format. - /// If true, then type names are included in the string. The default is . + /// If true, then type names are included in the string. The default is . /// The string representation. public static string Format(this IEnumerable properties, bool includeTypes = false) => "{" diff --git a/src/EFCore/Metadata/IReadOnlyIndex.cs b/src/EFCore/Metadata/IReadOnlyIndex.cs index 00f732c578c..58638980196 100644 --- a/src/EFCore/Metadata/IReadOnlyIndex.cs +++ b/src/EFCore/Metadata/IReadOnlyIndex.cs @@ -68,7 +68,7 @@ string ToDebugString(MetadataDebugStringOptions options = MetadataDebugStringOpt ", ", Properties.Select( p => singleLine - ? p.DeclaringEntityType.DisplayName() + "." + p.Name + ? p.DeclaringEntityType.DisplayName(omitSharedType: true) + "." + p.Name : p.Name)); builder.Append(" " + Name ?? ""); diff --git a/src/EFCore/Metadata/IReadOnlyKey.cs b/src/EFCore/Metadata/IReadOnlyKey.cs index c72d8f4bae5..71e55ddfde7 100644 --- a/src/EFCore/Metadata/IReadOnlyKey.cs +++ b/src/EFCore/Metadata/IReadOnlyKey.cs @@ -69,7 +69,7 @@ string ToDebugString(MetadataDebugStringOptions options = MetadataDebugStringOpt builder.AppendJoin( ", ", Properties.Select( p => singleLine - ? p.DeclaringEntityType.DisplayName() + "." + p.Name + ? p.DeclaringEntityType.DisplayName(omitSharedType: true) + "." + p.Name : p.Name)); if (IsPrimaryKey()) diff --git a/src/EFCore/Metadata/IReadOnlyTypeBase.cs b/src/EFCore/Metadata/IReadOnlyTypeBase.cs index 484c487d173..efe988e9256 100644 --- a/src/EFCore/Metadata/IReadOnlyTypeBase.cs +++ b/src/EFCore/Metadata/IReadOnlyTypeBase.cs @@ -64,6 +64,17 @@ public interface IReadOnlyTypeBase : IReadOnlyAnnotatable /// The display name. [DebuggerStepThrough] string DisplayName() + => DisplayName(omitSharedType: false); + + /// + /// Gets the friendly display name for the given . + /// + /// + /// A value indicating whether the name of the type for shared type entity types should be omitted from the returned value. + /// + /// The display name. + [DebuggerStepThrough] + string DisplayName(bool omitSharedType) { if (!HasSharedClrType) { @@ -97,8 +108,8 @@ string DisplayName() } return shortName == Name - ? shortName + " (" + ClrType.ShortDisplayName() + ")" - : shortName; + ? shortName + " (" + ClrType.ShortDisplayName() + ")" + : shortName; } /// diff --git a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs index ecc0398c898..d57a8ad97f7 100644 --- a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs +++ b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs @@ -5798,7 +5798,7 @@ protected IModel BuildModelFromSnapshotSource(string code) Activator.CreateInstance(factoryType), new object[] { builder }); - var services = TestHelpers.CreateContextServices(); + var services = TestHelpers.CreateContextServices(new ServiceCollection().AddEntityFrameworkSqlServerNetTopologySuite()); var processor = new SnapshotModelProcessor(new TestOperationReporter(), services.GetService()); return processor.Process(builder.Model); diff --git a/test/EFCore.Specification.Tests/ManyToManyTrackingTestBase.cs b/test/EFCore.Specification.Tests/ManyToManyTrackingTestBase.cs index b8aa1ad7cad..61e6c0e841b 100644 --- a/test/EFCore.Specification.Tests/ManyToManyTrackingTestBase.cs +++ b/test/EFCore.Specification.Tests/ManyToManyTrackingTestBase.cs @@ -808,10 +808,10 @@ public virtual void Can_delete_with_many_to_many_composite_shared_with_navs() Assert.All( context.ChangeTracker.Entries>(), e => Assert.Equal( - ((int)e.Entity["CompositeId1"] == key1 - && (string)e.Entity["CompositeId2"] == key2 - && (DateTime)e.Entity["CompositeId3"] == key3) - || (int)e.Entity["RootId"] == id + ((int)e.Entity["CompositeKeySkipSharedKey1"] == key1 + && (string)e.Entity["CompositeKeySkipSharedKey2"] == key2 + && (DateTime)e.Entity["CompositeKeySkipSharedKey3"] == key3) + || (int)e.Entity["RootSkipSharedId"] == id ? EntityState.Deleted : EntityState.Unchanged, e.State)); @@ -828,10 +828,10 @@ public virtual void Can_delete_with_many_to_many_composite_shared_with_navs() Assert.DoesNotContain( context.ChangeTracker.Entries>(), - e => ((int)e.Entity["CompositeId1"] == key1 - && (string)e.Entity["CompositeId2"] == key2 - && (DateTime)e.Entity["CompositeId3"] == key3) - || (int)e.Entity["RootId"] == id); + e => ((int)e.Entity["CompositeKeySkipSharedKey1"] == key1 + && (string)e.Entity["CompositeKeySkipSharedKey2"] == key2 + && (DateTime)e.Entity["CompositeKeySkipSharedKey3"] == key3) + || (int)e.Entity["RootSkipSharedId"] == id); }, context => { @@ -842,10 +842,10 @@ public virtual void Can_delete_with_many_to_many_composite_shared_with_navs() Assert.DoesNotContain( context.ChangeTracker.Entries>(), - e => ((int)e.Entity["CompositeId1"] == key1 - && (string)e.Entity["CompositeId2"] == key2 - && (DateTime)e.Entity["CompositeId3"] == key3) - || (int)e.Entity["RootId"] == id); + e => ((int)e.Entity["CompositeKeySkipSharedKey1"] == key1 + && (string)e.Entity["CompositeKeySkipSharedKey2"] == key2 + && (DateTime)e.Entity["CompositeKeySkipSharedKey3"] == key3) + || (int)e.Entity["RootSkipSharedId"] == id); }); void ValidateNavigations( @@ -4869,7 +4869,7 @@ static void ValidateFixup(DbContext context, IList leftEntities, ILis } } - protected void VerifyRelationshipSnapshots(DbContext context, IEnumerable entities) + protected static void VerifyRelationshipSnapshots(DbContext context, IEnumerable entities) { var detectChanges = context.ChangeTracker.AutoDetectChangesEnabled; try diff --git a/test/EFCore.Specification.Tests/Query/ManyToManyQueryFixtureBase.cs b/test/EFCore.Specification.Tests/Query/ManyToManyQueryFixtureBase.cs index cc14f4d1b24..2c5f163cbc8 100644 --- a/test/EFCore.Specification.Tests/Query/ManyToManyQueryFixtureBase.cs +++ b/test/EFCore.Specification.Tests/Query/ManyToManyQueryFixtureBase.cs @@ -258,25 +258,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con l => l.HasOne(x => x.Two).WithMany(e => e.JoinThreeFull)); // Nav:2 Payload:No Join:Shared Extra:Self-ref - // TODO: Remove UsingEntity modelBuilder.Entity() .HasMany(e => e.SelfSkipSharedLeft) - .WithMany(e => e.SelfSkipSharedRight) - .UsingEntity>( - "JoinTwoSelfShared", - l => l.HasOne().WithMany().HasForeignKey("LeftId"), - r => r.HasOne().WithMany().HasForeignKey("RightId")); + .WithMany(e => e.SelfSkipSharedRight); // Nav:2 Payload:No Join:Shared Extra:CompositeKey - // TODO: Remove UsingEntity modelBuilder.Entity() .HasMany(e => e.CompositeKeySkipShared) - .WithMany(e => e.TwoSkipShared) - .UsingEntity>( - "JoinTwoToCompositeKeyShared", - r => r.HasOne().WithMany().HasForeignKey("CompositeId1", "CompositeId2", "CompositeId3"), - l => l.HasOne().WithMany().HasForeignKey("TwoId")) - .HasKey("TwoId", "CompositeId1", "CompositeId2", "CompositeId3"); + .WithMany(e => e.TwoSkipShared); // Nav:6 Payload:No Join:Concrete Extra:CompositeKey modelBuilder.Entity() @@ -293,23 +282,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con r => r.HasOne(x => x.Three).WithMany(x => x.JoinCompositeKeyFull).IsRequired()); // Nav:2 Payload:No Join:Shared Extra:Inheritance - // TODO: Remove UsingEntity - modelBuilder.Entity().HasMany(e => e.RootSkipShared).WithMany(e => e.ThreeSkipShared) - .UsingEntity>( - "EntityRootEntityThree", - r => r.HasOne().WithMany().HasForeignKey("EntityRootId"), - l => l.HasOne().WithMany().HasForeignKey("EntityThreeId")); + modelBuilder.Entity() + .HasMany(e => e.RootSkipShared) + .WithMany(e => e.ThreeSkipShared); // Nav:2 Payload:No Join:Shared Extra:Inheritance,CompositeKey - // TODO: Remove UsingEntity modelBuilder.Entity() .HasMany(e => e.RootSkipShared) - .WithMany(e => e.CompositeKeySkipShared) - .UsingEntity>( - "JoinCompositeKeyToRootShared", - r => r.HasOne().WithMany().HasForeignKey("RootId"), - l => l.HasOne().WithMany().HasForeignKey("CompositeId1", "CompositeId2", "CompositeId3")) - .HasKey("CompositeId1", "CompositeId2", "CompositeId3", "RootId"); + .WithMany(e => e.CompositeKeySkipShared); // Nav:6 Payload:No Join:Concrete Extra:Inheritance,CompositeKey modelBuilder.Entity() diff --git a/test/EFCore.Specification.Tests/TestModels/ManyToManyModel/ManyToManyData.cs b/test/EFCore.Specification.Tests/TestModels/ManyToManyModel/ManyToManyData.cs index d898dda95df..c484568dcb7 100644 --- a/test/EFCore.Specification.Tests/TestModels/ManyToManyModel/ManyToManyData.cs +++ b/test/EFCore.Specification.Tests/TestModels/ManyToManyModel/ManyToManyData.cs @@ -43,10 +43,10 @@ public ManyToManyData(ManyToManyContext context, bool useGeneratedKeys) context.Set>("EntityOneEntityTwo").AddRange(CreateEntityOneEntityTwos(context)); context.Set>("JoinOneToThreePayloadFullShared") .AddRange(CreateJoinOneToThreePayloadFullShareds(context)); - context.Set>("JoinTwoSelfShared").AddRange(CreateJoinTwoSelfShareds(context)); - context.Set>("JoinTwoToCompositeKeyShared").AddRange(CreateJoinTwoToCompositeKeyShareds(context)); + context.Set>("EntityTwoEntityTwo").AddRange(CreateJoinTwoSelfShareds(context)); + context.Set>("EntityCompositeKeyEntityTwo").AddRange(CreateJoinTwoToCompositeKeyShareds(context)); context.Set>("EntityRootEntityThree").AddRange(CreateEntityRootEntityThrees(context)); - context.Set>("JoinCompositeKeyToRootShared").AddRange(CreateJoinCompositeKeyToRootShareds(context)); + context.Set>("EntityCompositeKeyEntityRoot").AddRange(CreateJoinCompositeKeyToRootShareds(context)); } public IQueryable Set() @@ -1064,10 +1064,10 @@ private static Dictionary CreateJoinTwoSelfShared( EntityTwo left, EntityTwo right) => CreateInstance( - context?.Set>("JoinTwoSelfShared"), (e, p) => + context?.Set>("EntityTwoEntityTwo"), (e, p) => { - e["LeftId"] = context?.Entry(left).Property(e => e.Id).CurrentValue ?? left.Id; - e["RightId"] = context?.Entry(right).Property(e => e.Id).CurrentValue ?? right.Id; + e["SelfSkipSharedLeftId"] = context?.Entry(left).Property(e => e.Id).CurrentValue ?? left.Id; + e["SelfSkipSharedRightId"] = context?.Entry(right).Property(e => e.Id).CurrentValue ?? right.Id; }); private Dictionary[] CreateJoinTwoToCompositeKeyShareds(ManyToManyContext context) @@ -1116,12 +1116,12 @@ private static Dictionary CreateJoinTwoToCompositeKeyShared( EntityTwo two, EntityCompositeKey composite) => CreateInstance( - context?.Set>("JoinTwoToCompositeKeyShared"), (e, p) => + context?.Set>("EntityCompositeKeyEntityTwo"), (e, p) => { - e["TwoId"] = context?.Entry(two).Property(e => e.Id).CurrentValue ?? two.Id; - e["CompositeId1"] = context?.Entry(composite).Property(e => e.Key1).CurrentValue ?? composite.Key1; - e["CompositeId2"] = composite.Key2; - e["CompositeId3"] = composite.Key3; + e["TwoSkipSharedId"] = context?.Entry(two).Property(e => e.Id).CurrentValue ?? two.Id; + e["CompositeKeySkipSharedKey1"] = context?.Entry(composite).Property(e => e.Key1).CurrentValue ?? composite.Key1; + e["CompositeKeySkipSharedKey2"] = composite.Key2; + e["CompositeKeySkipSharedKey3"] = composite.Key3; }); private Dictionary[] CreateEntityRootEntityThrees(ManyToManyContext context) @@ -1165,8 +1165,8 @@ private static Dictionary CreateEntityRootEntityThree( => CreateInstance( context?.Set>("EntityRootEntityThree"), (e, p) => { - e["EntityThreeId"] = context?.Entry(three).Property(e => e.Id).CurrentValue ?? three.Id; - e["EntityRootId"] = context?.Entry(root).Property(e => e.Id).CurrentValue ?? root.Id; + e["ThreeSkipSharedId"] = context?.Entry(three).Property(e => e.Id).CurrentValue ?? three.Id; + e["RootSkipSharedId"] = context?.Entry(root).Property(e => e.Id).CurrentValue ?? root.Id; }); private Dictionary[] CreateJoinCompositeKeyToRootShareds(ManyToManyContext context) @@ -1214,19 +1214,19 @@ private Dictionary[] CreateJoinCompositeKeyToRootShareds(ManyToM }; private static ICollection CreateCollection(bool proxy) - => proxy ? (ICollection)new ObservableCollection() : new List(); + => proxy ? new ObservableCollection() : new List(); private static Dictionary CreateJoinCompositeKeyToRootShared( ManyToManyContext context, EntityRoot root, EntityCompositeKey composite) => CreateInstance( - context?.Set>("JoinCompositeKeyToRootShared"), (e, p) => + context?.Set>("EntityCompositeKeyEntityRoot"), (e, p) => { - e["RootId"] = context?.Entry(root).Property(e => e.Id).CurrentValue ?? root.Id; - e["CompositeId1"] = context?.Entry(composite).Property(e => e.Key1).CurrentValue ?? composite.Key1; - e["CompositeId2"] = composite.Key2; - e["CompositeId3"] = composite.Key3; + e["RootSkipSharedId"] = context?.Entry(root).Property(e => e.Id).CurrentValue ?? root.Id; + e["CompositeKeySkipSharedKey1"] = context?.Entry(composite).Property(e => e.Key1).CurrentValue ?? composite.Key1; + e["CompositeKeySkipSharedKey2"] = composite.Key2; + e["CompositeKeySkipSharedKey3"] = composite.Key3; }); private static TEntity CreateInstance(DbSet set, Action configureEntity) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyNoTrackingQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyNoTrackingQuerySqlServerTest.cs index 45685bdd776..a6b59deed1e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyNoTrackingQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyNoTrackingQuerySqlServerTest.cs @@ -130,9 +130,9 @@ public override async Task Skip_navigation_long_count_with_predicate(bool async) FROM [EntityTwos] AS [e] ORDER BY ( SELECT COUNT_BIG(*) - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[LeftId] = [e0].[Id] - WHERE ([e].[Id] = [j].[RightId]) AND ([e0].[Name] IS NOT NULL AND ([e0].[Name] LIKE N'L%'))) DESC, [e].[Id]"); + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedLeftId] = [e1].[Id] + WHERE ([e].[Id] = [e0].[SelfSkipSharedRightId]) AND ([e1].[Name] IS NOT NULL AND ([e1].[Name] LIKE N'L%'))) DESC, [e].[Id]"); } public override async Task Skip_navigation_select_many_average(bool async) @@ -143,10 +143,10 @@ public override async Task Skip_navigation_select_many_average(bool async) @"SELECT AVG(CAST([t].[Key1] AS float)) FROM [EntityTwos] AS [e] INNER JOIN ( - SELECT [e0].[Key1], [j].[TwoId] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[TwoId]"); + SELECT [e1].[Key1], [e0].[TwoSkipSharedId] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[TwoSkipSharedId]"); } public override async Task Skip_navigation_select_many_max(bool async) @@ -171,10 +171,10 @@ public override async Task Skip_navigation_select_many_min(bool async) @"SELECT MIN([t].[Id]) FROM [EntityThrees] AS [e] INNER JOIN ( - SELECT [e1].[Id], [e0].[EntityThreeId] + SELECT [e1].[Id], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityRoots] AS [e1] ON [e0].[EntityRootId] = [e1].[Id] -) AS [t] ON [e].[Id] = [t].[EntityThreeId]"); + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] +) AS [t] ON [e].[Id] = [t].[ThreeSkipSharedId]"); } public override async Task Skip_navigation_select_many_sum(bool async) @@ -185,10 +185,10 @@ public override async Task Skip_navigation_select_many_sum(bool async) @"SELECT COALESCE(SUM([t].[Key1]), 0) FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e0].[Key1], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[RootId]"); + SELECT [e1].[Key1], [e0].[RootSkipSharedId] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId]"); } public override async Task Skip_navigation_select_subquery_average(bool async) @@ -343,15 +343,15 @@ public override async Task Skip_navigation_of_type(bool async) await base.Skip_navigation_of_type(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [e0].[Id], [e0].[Discriminator], [e0].[Name], [e0].[Number], [e0].[IsGreen], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityRoots] AS [e0] ON [j].[RootId] = [e0].[Id] - WHERE [e0].[Discriminator] = N'EntityLeaf' -) AS [t] ON (([e].[Key1] = [t].[CompositeId1]) AND ([e].[Key2] = [t].[CompositeId2])) AND ([e].[Key3] = [t].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId]"); + SELECT [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen], [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] + WHERE [e1].[Discriminator] = N'EntityLeaf' +) AS [t] ON (([e].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3]"); } public override async Task Join_with_skip_navigation(bool async) @@ -362,11 +362,11 @@ public override async Task Join_with_skip_navigation(bool async) @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId] FROM [EntityTwos] AS [e] INNER JOIN [EntityTwos] AS [e0] ON [e].[Id] = ( - SELECT TOP(1) [e1].[Id] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e1] ON [j].[RightId] = [e1].[Id] - WHERE [e0].[Id] = [j].[LeftId] - ORDER BY [e1].[Id])"); + SELECT TOP(1) [e2].[Id] + FROM [EntityTwoEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[SelfSkipSharedRightId] = [e2].[Id] + WHERE [e0].[Id] = [e1].[SelfSkipSharedLeftId] + ORDER BY [e2].[Id])"); } public override async Task Left_join_with_skip_navigation(bool async) @@ -377,16 +377,16 @@ public override async Task Left_join_with_skip_navigation(bool async) @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name] FROM [EntityCompositeKeys] AS [e] LEFT JOIN [EntityCompositeKeys] AS [e0] ON ( - SELECT TOP(1) [e1].[Id] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e1] ON [j].[TwoId] = [e1].[Id] - WHERE (([e].[Key1] = [j].[CompositeId1]) AND ([e].[Key2] = [j].[CompositeId2])) AND ([e].[Key3] = [j].[CompositeId3]) - ORDER BY [e1].[Id]) = ( SELECT TOP(1) [e2].[Id] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e2] ON [j0].[ThreeId] = [e2].[Id] - WHERE (([e0].[Key1] = [j0].[CompositeId1]) AND ([e0].[Key2] = [j0].[CompositeId2])) AND ([e0].[Key3] = [j0].[CompositeId3]) - ORDER BY [e2].[Id]) + FROM [EntityCompositeKeyEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[TwoSkipSharedId] = [e2].[Id] + WHERE (([e].[Key1] = [e1].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [e1].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [e1].[CompositeKeySkipSharedKey3]) + ORDER BY [e2].[Id]) = ( + SELECT TOP(1) [e3].[Id] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e3] ON [j].[ThreeId] = [e3].[Id] + WHERE (([e0].[Key1] = [j].[CompositeId1]) AND ([e0].[Key2] = [j].[CompositeId2])) AND ([e0].[Key3] = [j].[CompositeId3]) + ORDER BY [e3].[Id]) ORDER BY [e].[Key1], [e0].[Key1], [e].[Key2], [e0].[Key2]"); } @@ -398,10 +398,10 @@ public override async Task Select_many_over_skip_navigation(bool async) @"SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[EntityRootId] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[RootSkipSharedId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityThrees] AS [e1] ON [e0].[EntityThreeId] = [e1].[Id] -) AS [t] ON [e].[Id] = [t].[EntityRootId]"); + INNER JOIN [EntityThrees] AS [e1] ON [e0].[ThreeSkipSharedId] = [e1].[Id] +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId]"); } public override async Task Select_many_over_skip_navigation_where(bool async) @@ -480,11 +480,11 @@ public override async Task Select_many_over_skip_navigation_of_type(bool async) @"SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen] FROM [EntityThrees] AS [e] INNER JOIN ( - SELECT [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen], [e0].[EntityThreeId] + SELECT [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityRoots] AS [e1] ON [e0].[EntityRootId] = [e1].[Id] + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] WHERE [e1].[Discriminator] IN (N'EntityBranch', N'EntityLeaf') -) AS [t] ON [e].[Id] = [t].[EntityThreeId]"); +) AS [t] ON [e].[Id] = [t].[ThreeSkipSharedId]"); } public override async Task Select_many_over_skip_navigation_cast(bool async) @@ -525,7 +525,7 @@ public override async Task Select_skip_navigation_multiple(bool async) await base.Select_skip_navigation_multiple(async); AssertSql( - @"SELECT [e].[Id], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[ThreeId], [t].[TwoId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[LeftId], [t0].[RightId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[TwoId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3] + @"SELECT [e].[Id], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[ThreeId], [t].[TwoId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[TwoSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3] FROM [EntityTwos] AS [e] LEFT JOIN ( SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [j].[ThreeId], [j].[TwoId] @@ -533,16 +533,16 @@ FROM [JoinTwoToThree] AS [j] INNER JOIN [EntityThrees] AS [e0] ON [j].[ThreeId] = [e0].[Id] ) AS [t] ON [e].[Id] = [t].[TwoId] LEFT JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [j0].[LeftId], [j0].[RightId] - FROM [JoinTwoSelfShared] AS [j0] - INNER JOIN [EntityTwos] AS [e1] ON [j0].[LeftId] = [e1].[Id] -) AS [t0] ON [e].[Id] = [t0].[RightId] + SELECT [e2].[Id], [e2].[CollectionInverseId], [e2].[ExtraId], [e2].[Name], [e2].[ReferenceInverseId], [e1].[SelfSkipSharedLeftId], [e1].[SelfSkipSharedRightId] + FROM [EntityTwoEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[SelfSkipSharedLeftId] = [e2].[Id] +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedRightId] LEFT JOIN ( - SELECT [e2].[Key1], [e2].[Key2], [e2].[Key3], [e2].[Name], [j1].[TwoId], [j1].[CompositeId1], [j1].[CompositeId2], [j1].[CompositeId3] - FROM [JoinTwoToCompositeKeyShared] AS [j1] - INNER JOIN [EntityCompositeKeys] AS [e2] ON (([j1].[CompositeId1] = [e2].[Key1]) AND ([j1].[CompositeId2] = [e2].[Key2])) AND ([j1].[CompositeId3] = [e2].[Key3]) -) AS [t1] ON [e].[Id] = [t1].[TwoId] -ORDER BY [e].[Id], [t].[ThreeId], [t].[TwoId], [t].[Id], [t0].[LeftId], [t0].[RightId], [t0].[Id], [t1].[TwoId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[Key1], [t1].[Key2]"); + SELECT [e4].[Key1], [e4].[Key2], [e4].[Key3], [e4].[Name], [e3].[TwoSkipSharedId], [e3].[CompositeKeySkipSharedKey1], [e3].[CompositeKeySkipSharedKey2], [e3].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityTwo] AS [e3] + INNER JOIN [EntityCompositeKeys] AS [e4] ON (([e3].[CompositeKeySkipSharedKey1] = [e4].[Key1]) AND ([e3].[CompositeKeySkipSharedKey2] = [e4].[Key2])) AND ([e3].[CompositeKeySkipSharedKey3] = [e4].[Key3]) +) AS [t1] ON [e].[Id] = [t1].[TwoSkipSharedId] +ORDER BY [e].[Id], [t].[ThreeId], [t].[TwoId], [t].[Id], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t0].[Id], [t1].[TwoSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2]"); } public override async Task Select_skip_navigation_first_or_default(bool async) @@ -569,14 +569,14 @@ public override async Task Include_skip_navigation(bool async) await base.Include_skip_navigation(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [e0].[Id], [e0].[Discriminator], [e0].[Name], [e0].[Number], [e0].[IsGreen], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityRoots] AS [e0] ON [j].[RootId] = [e0].[Id] -) AS [t] ON (([e].[Key1] = [t].[CompositeId1]) AND ([e].[Key2] = [t].[CompositeId2])) AND ([e].[Key3] = [t].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId]"); + SELECT [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen], [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] +) AS [t] ON (([e].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3]"); } public override async Task Include_skip_navigation_then_reference(bool async) @@ -692,18 +692,18 @@ public override async Task Filtered_include_skip_navigation_order_by_skip(bool a await base.Filtered_include_skip_navigation_order_by_skip(async); AssertSql( - @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[LeftId], [t0].[RightId] + @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId] FROM [EntityTwos] AS [e] LEFT JOIN ( - SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[LeftId], [t].[RightId] + SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[SelfSkipSharedLeftId], [t].[SelfSkipSharedRightId] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j].[LeftId], [j].[RightId], ROW_NUMBER() OVER(PARTITION BY [j].[LeftId] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[RightId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[SelfSkipSharedLeftId], [e0].[SelfSkipSharedRightId], ROW_NUMBER() OVER(PARTITION BY [e0].[SelfSkipSharedLeftId] ORDER BY [e1].[Id]) AS [row] + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedRightId] = [e1].[Id] ) AS [t] WHERE 2 < [t].[row] -) AS [t0] ON [e].[Id] = [t0].[LeftId] -ORDER BY [e].[Id], [t0].[LeftId], [t0].[Id]"); +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedLeftId] +ORDER BY [e].[Id], [t0].[SelfSkipSharedLeftId], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_take(bool async) @@ -711,18 +711,18 @@ public override async Task Filtered_include_skip_navigation_order_by_take(bool a await base.Filtered_include_skip_navigation_order_by_take(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[TwoId], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[TwoId], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3] + SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j].[TwoId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[TwoId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[TwoSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], ROW_NUMBER() OVER(PARTITION BY [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] ORDER BY [e1].[Id]) AS [row] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] ) AS [t] WHERE [t].[row] <= 2 -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take(bool async) @@ -749,20 +749,20 @@ public override async Task Filtered_then_include_skip_navigation_where(bool asyn await base.Filtered_then_include_skip_navigation_where(async); AssertSql( - @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[EntityRootId], [t0].[EntityThreeId], [t0].[Id0], [t0].[Name0], [t0].[OneId], [t0].[ThreeId] + @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[RootSkipSharedId], [t0].[ThreeSkipSharedId], [t0].[Id0], [t0].[Name0], [t0].[OneId], [t0].[ThreeId] FROM [EntityRoots] AS [e] LEFT JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[EntityRootId], [e0].[EntityThreeId], [t].[Id] AS [Id0], [t].[Name] AS [Name0], [t].[OneId], [t].[ThreeId] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[RootSkipSharedId], [e0].[ThreeSkipSharedId], [t].[Id] AS [Id0], [t].[Name] AS [Name0], [t].[OneId], [t].[ThreeId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityThrees] AS [e1] ON [e0].[EntityThreeId] = [e1].[Id] + INNER JOIN [EntityThrees] AS [e1] ON [e0].[ThreeSkipSharedId] = [e1].[Id] LEFT JOIN ( SELECT [e2].[Id], [e2].[Name], [j].[OneId], [j].[ThreeId] FROM [JoinOneToThreePayloadFullShared] AS [j] INNER JOIN [EntityOnes] AS [e2] ON [j].[OneId] = [e2].[Id] WHERE [e2].[Id] < 10 ) AS [t] ON [e1].[Id] = [t].[ThreeId] -) AS [t0] ON [e].[Id] = [t0].[EntityRootId] -ORDER BY [e].[Id], [t0].[EntityRootId], [t0].[EntityThreeId], [t0].[Id], [t0].[OneId], [t0].[ThreeId]"); +) AS [t0] ON [e].[Id] = [t0].[RootSkipSharedId] +ORDER BY [e].[Id], [t0].[RootSkipSharedId], [t0].[ThreeSkipSharedId], [t0].[Id], [t0].[OneId], [t0].[ThreeId]"); } public override async Task Filtered_then_include_skip_navigation_order_by_skip_take(bool async) @@ -770,23 +770,23 @@ public override async Task Filtered_then_include_skip_navigation_order_by_skip_t await base.Filtered_then_include_skip_navigation_order_by_skip_take(async); AssertSql( - @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[RootId], [t1].[Id], [t1].[CollectionInverseId], [t1].[Name0], [t1].[ReferenceInverseId], [t1].[Id0] + @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[RootSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Id], [t1].[CollectionInverseId], [t1].[Name0], [t1].[ReferenceInverseId], [t1].[Id0] FROM [EntityRoots] AS [e] LEFT JOIN ( - SELECT [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name] AS [Name0], [t0].[ReferenceInverseId], [t0].[Id0], [t0].[CompositeId1] AS [CompositeId10], [t0].[CompositeId2] AS [CompositeId20], [t0].[CompositeId3] AS [CompositeId30] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) + SELECT [e1].[Key1], [e1].[Key2], [e1].[Key3], [e1].[Name], [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name] AS [Name0], [t0].[ReferenceInverseId], [t0].[Id0], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) LEFT JOIN ( SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[Id0], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3] FROM ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [j0].[Id] AS [Id0], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] ORDER BY [e1].[Id]) AS [row] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e1] ON [j0].[ThreeId] = [e1].[Id] + SELECT [e2].[Id], [e2].[CollectionInverseId], [e2].[Name], [e2].[ReferenceInverseId], [j].[Id] AS [Id0], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e2].[Id]) AS [row] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e2] ON [j].[ThreeId] = [e2].[Id] ) AS [t] WHERE (1 < [t].[row]) AND ([t].[row] <= 3) - ) AS [t0] ON (([e0].[Key1] = [t0].[CompositeId1]) AND ([e0].[Key2] = [t0].[CompositeId2])) AND ([e0].[Key3] = [t0].[CompositeId3]) -) AS [t1] ON [e].[Id] = [t1].[RootId] -ORDER BY [e].[Id], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[RootId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[CompositeId10], [t1].[CompositeId20], [t1].[CompositeId30], [t1].[Id]"); + ) AS [t0] ON (([e1].[Key1] = [t0].[CompositeId1]) AND ([e1].[Key2] = [t0].[CompositeId2])) AND ([e1].[Key3] = [t0].[CompositeId3]) +) AS [t1] ON [e].[Id] = [t1].[RootSkipSharedId] +ORDER BY [e].[Id], [t1].[RootSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[Id]"); } public override async Task Filtered_include_skip_navigation_where_then_include_skip_navigation(bool async) @@ -794,21 +794,21 @@ public override async Task Filtered_include_skip_navigation_where_then_include_s await base.Filtered_include_skip_navigation_where_then_include_skip_navigation(async); AssertSql( - @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[Name], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId], [t0].[TwoId], [t0].[CompositeId10], [t0].[CompositeId20], [t0].[CompositeId30] + @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[Name], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3] FROM [EntityRoots] AS [e] LEFT JOIN ( - SELECT [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[LeafId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name] AS [Name0], [t].[ReferenceInverseId], [t].[TwoId], [t].[CompositeId1] AS [CompositeId10], [t].[CompositeId2] AS [CompositeId20], [t].[CompositeId3] AS [CompositeId30] + SELECT [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[LeafId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name] AS [Name0], [t].[ReferenceInverseId], [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM [JoinCompositeKeyToLeaf] AS [j] INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) LEFT JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [j0].[TwoId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] - FROM [JoinTwoToCompositeKeyShared] AS [j0] - INNER JOIN [EntityTwos] AS [e1] ON [j0].[TwoId] = [e1].[Id] - ) AS [t] ON (([e0].[Key1] = [t].[CompositeId1]) AND ([e0].[Key2] = [t].[CompositeId2])) AND ([e0].[Key3] = [t].[CompositeId3]) + SELECT [e2].[Id], [e2].[CollectionInverseId], [e2].[ExtraId], [e2].[Name], [e2].[ReferenceInverseId], [e1].[TwoSkipSharedId], [e1].[CompositeKeySkipSharedKey1], [e1].[CompositeKeySkipSharedKey2], [e1].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[TwoSkipSharedId] = [e2].[Id] + ) AS [t] ON (([e0].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e0].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e0].[Key3] = [t].[CompositeKeySkipSharedKey3]) WHERE [e0].[Key1] < 5 ) AS [t0] ON [e].[Id] = [t0].[LeafId] WHERE [e].[Discriminator] = N'EntityLeaf' -ORDER BY [e].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[TwoId], [t0].[CompositeId10], [t0].[CompositeId20], [t0].[CompositeId30]"); +ORDER BY [e].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take_then_include_skip_navigation_where(bool async) @@ -836,6 +836,7 @@ WHERE [e1].[Id] < 10 ) AS [t0] ON [t].[Id] = [t0].[TwoId] ) AS [t1] ORDER BY [e].[Id], [t1].[Id], [t1].[OneId], [t1].[TwoId], [t1].[ThreeId], [t1].[TwoId0]"); + } public override async Task Filtered_include_skip_navigation_where_then_include_skip_navigation_order_by_skip_take(bool async) @@ -984,10 +985,10 @@ FROM [EntityCompositeKeys] AS [e] @"SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen], [e].[Key1], [e].[Key2], [e].[Key3] FROM [EntityCompositeKeys] AS [e] INNER JOIN ( - SELECT [e0].[Id], [e0].[Discriminator], [e0].[Name], [e0].[Number], [e0].[IsGreen], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityRoots] AS [e0] ON [j].[RootId] = [e0].[Id] -) AS [t] ON (([e].[Key1] = [t].[CompositeId1]) AND ([e].[Key2] = [t].[CompositeId2])) AND ([e].[Key3] = [t].[CompositeId3]) + SELECT [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] +) AS [t] ON (([e].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t].[CompositeKeySkipSharedKey3]) ORDER BY [e].[Key1], [e].[Key2], [e].[Key3]"); } @@ -1159,15 +1160,15 @@ FROM [EntityTwos] AS [e] @"SELECT [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id] FROM [EntityTwos] AS [e] INNER JOIN ( - SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[LeftId] + SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[SelfSkipSharedLeftId] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j].[LeftId], ROW_NUMBER() OVER(PARTITION BY [j].[LeftId] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[RightId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[SelfSkipSharedLeftId], ROW_NUMBER() OVER(PARTITION BY [e0].[SelfSkipSharedLeftId] ORDER BY [e1].[Id]) AS [row] + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedRightId] = [e1].[Id] ) AS [t] WHERE 2 < [t].[row] -) AS [t0] ON [e].[Id] = [t0].[LeftId] -ORDER BY [e].[Id], [t0].[LeftId], [t0].[Id]"); +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedLeftId] +ORDER BY [e].[Id], [t0].[SelfSkipSharedLeftId], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_take_split(bool async) @@ -1182,15 +1183,15 @@ FROM [EntityCompositeKeys] AS [e] @"SELECT [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Key1], [e].[Key2], [e].[Key3] FROM [EntityCompositeKeys] AS [e] INNER JOIN ( - SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3] + SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[TwoId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], ROW_NUMBER() OVER(PARTITION BY [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] ORDER BY [e1].[Id]) AS [row] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] ) AS [t] WHERE [t].[row] <= 2 -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take_split(bool async) @@ -1225,29 +1226,29 @@ public override async Task Filtered_then_include_skip_navigation_where_split(boo FROM [EntityRoots] AS [e] ORDER BY [e].[Id]", // - @"SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [e].[Id], [t].[EntityRootId], [t].[EntityThreeId] + @"SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [e].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[EntityRootId], [e0].[EntityThreeId] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[RootSkipSharedId], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityThrees] AS [e1] ON [e0].[EntityThreeId] = [e1].[Id] -) AS [t] ON [e].[Id] = [t].[EntityRootId] -ORDER BY [e].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id]", + INNER JOIN [EntityThrees] AS [e1] ON [e0].[ThreeSkipSharedId] = [e1].[Id] +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId] +ORDER BY [e].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id]", // - @"SELECT [t0].[Id], [t0].[Name], [e].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id] + @"SELECT [t0].[Id], [t0].[Name], [e].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e1].[Id], [e0].[EntityRootId], [e0].[EntityThreeId] + SELECT [e1].[Id], [e0].[RootSkipSharedId], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityThrees] AS [e1] ON [e0].[EntityThreeId] = [e1].[Id] -) AS [t] ON [e].[Id] = [t].[EntityRootId] + INNER JOIN [EntityThrees] AS [e1] ON [e0].[ThreeSkipSharedId] = [e1].[Id] +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId] INNER JOIN ( SELECT [e2].[Id], [e2].[Name], [j].[ThreeId] FROM [JoinOneToThreePayloadFullShared] AS [j] INNER JOIN [EntityOnes] AS [e2] ON [j].[OneId] = [e2].[Id] WHERE [e2].[Id] < 10 ) AS [t0] ON [t].[Id] = [t0].[ThreeId] -ORDER BY [e].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id]"); +ORDER BY [e].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id]"); } public override async Task Filtered_then_include_skip_navigation_order_by_skip_take_split(bool async) @@ -1259,32 +1260,32 @@ public override async Task Filtered_then_include_skip_navigation_order_by_skip_t FROM [EntityRoots] AS [e] ORDER BY [e].[Id]", // - @"SELECT [t].[Key1], [t].[Key2], [t].[Key3], [t].[Name], [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId] + @"SELECT [t].[Key1], [t].[Key2], [t].[Key3], [t].[Name], [e].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[RootId] -ORDER BY [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3]", + SELECT [e1].[Key1], [e1].[Key2], [e1].[Key3], [e1].[Name], [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId] +ORDER BY [e].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3]", // - @"SELECT [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3] + @"SELECT [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e0].[Key1], [e0].[Key2], [e0].[Key3], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[RootId] + SELECT [e1].[Key1], [e1].[Key2], [e1].[Key3], [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId] INNER JOIN ( SELECT [t1].[Id], [t1].[CollectionInverseId], [t1].[Name], [t1].[ReferenceInverseId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3] FROM ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] ORDER BY [e1].[Id]) AS [row] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e1] ON [j0].[ThreeId] = [e1].[Id] + SELECT [e2].[Id], [e2].[CollectionInverseId], [e2].[Name], [e2].[ReferenceInverseId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e2].[Id]) AS [row] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e2] ON [j].[ThreeId] = [e2].[Id] ) AS [t1] WHERE (1 < [t1].[row]) AND ([t1].[row] <= 3) ) AS [t0] ON (([t].[Key1] = [t0].[CompositeId1]) AND ([t].[Key2] = [t0].[CompositeId2])) AND ([t].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +ORDER BY [e].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_where_then_include_skip_navigation_split(bool async) @@ -1317,10 +1318,10 @@ INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) WHERE [e0].[Key1] < 5 ) AS [t] ON [e].[Id] = [t].[LeafId] INNER JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] - FROM [JoinTwoToCompositeKeyShared] AS [j0] - INNER JOIN [EntityTwos] AS [e1] ON [j0].[TwoId] = [e1].[Id] -) AS [t0] ON (([t].[Key1] = [t0].[CompositeId1]) AND ([t].[Key2] = [t0].[CompositeId2])) AND ([t].[Key3] = [t0].[CompositeId3]) + SELECT [e2].[Id], [e2].[CollectionInverseId], [e2].[ExtraId], [e2].[Name], [e2].[ReferenceInverseId], [e1].[CompositeKeySkipSharedKey1], [e1].[CompositeKeySkipSharedKey2], [e1].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[TwoSkipSharedId] = [e2].[Id] +) AS [t0] ON (([t].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([t].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([t].[Key3] = [t0].[CompositeKeySkipSharedKey3]) WHERE [e].[Discriminator] = N'EntityLeaf' ORDER BY [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyQuerySqlServerTest.cs index 98c5654374b..a69c55f9d54 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyQuerySqlServerTest.cs @@ -129,9 +129,9 @@ public override async Task Skip_navigation_long_count_with_predicate(bool async) FROM [EntityTwos] AS [e] ORDER BY ( SELECT COUNT_BIG(*) - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[LeftId] = [e0].[Id] - WHERE ([e].[Id] = [j].[RightId]) AND ([e0].[Name] IS NOT NULL AND ([e0].[Name] LIKE N'L%'))) DESC, [e].[Id]"); + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedLeftId] = [e1].[Id] + WHERE ([e].[Id] = [e0].[SelfSkipSharedRightId]) AND ([e1].[Name] IS NOT NULL AND ([e1].[Name] LIKE N'L%'))) DESC, [e].[Id]"); } public override async Task Skip_navigation_select_many_average(bool async) @@ -142,10 +142,10 @@ public override async Task Skip_navigation_select_many_average(bool async) @"SELECT AVG(CAST([t].[Key1] AS float)) FROM [EntityTwos] AS [e] INNER JOIN ( - SELECT [e0].[Key1], [j].[TwoId] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[TwoId]"); + SELECT [e1].[Key1], [e0].[TwoSkipSharedId] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[TwoSkipSharedId]"); } public override async Task Skip_navigation_select_many_max(bool async) @@ -170,10 +170,10 @@ public override async Task Skip_navigation_select_many_min(bool async) @"SELECT MIN([t].[Id]) FROM [EntityThrees] AS [e] INNER JOIN ( - SELECT [e1].[Id], [e0].[EntityThreeId] + SELECT [e1].[Id], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityRoots] AS [e1] ON [e0].[EntityRootId] = [e1].[Id] -) AS [t] ON [e].[Id] = [t].[EntityThreeId]"); + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] +) AS [t] ON [e].[Id] = [t].[ThreeSkipSharedId]"); } public override async Task Skip_navigation_select_many_sum(bool async) @@ -184,10 +184,10 @@ public override async Task Skip_navigation_select_many_sum(bool async) @"SELECT COALESCE(SUM([t].[Key1]), 0) FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e0].[Key1], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[RootId]"); + SELECT [e1].[Key1], [e0].[RootSkipSharedId] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId]"); } public override async Task Skip_navigation_select_subquery_average(bool async) @@ -342,15 +342,15 @@ public override async Task Skip_navigation_of_type(bool async) await base.Skip_navigation_of_type(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [e0].[Id], [e0].[Discriminator], [e0].[Name], [e0].[Number], [e0].[IsGreen], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityRoots] AS [e0] ON [j].[RootId] = [e0].[Id] - WHERE [e0].[Discriminator] = N'EntityLeaf' -) AS [t] ON (([e].[Key1] = [t].[CompositeId1]) AND ([e].[Key2] = [t].[CompositeId2])) AND ([e].[Key3] = [t].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId]"); + SELECT [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen], [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] + WHERE [e1].[Discriminator] = N'EntityLeaf' +) AS [t] ON (([e].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3]"); } public override async Task Join_with_skip_navigation(bool async) @@ -361,11 +361,11 @@ public override async Task Join_with_skip_navigation(bool async) @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId] FROM [EntityTwos] AS [e] INNER JOIN [EntityTwos] AS [e0] ON [e].[Id] = ( - SELECT TOP(1) [e1].[Id] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e1] ON [j].[RightId] = [e1].[Id] - WHERE [e0].[Id] = [j].[LeftId] - ORDER BY [e1].[Id])"); + SELECT TOP(1) [e2].[Id] + FROM [EntityTwoEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[SelfSkipSharedRightId] = [e2].[Id] + WHERE [e0].[Id] = [e1].[SelfSkipSharedLeftId] + ORDER BY [e2].[Id])"); } public override async Task Left_join_with_skip_navigation(bool async) @@ -376,16 +376,16 @@ public override async Task Left_join_with_skip_navigation(bool async) @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name] FROM [EntityCompositeKeys] AS [e] LEFT JOIN [EntityCompositeKeys] AS [e0] ON ( - SELECT TOP(1) [e1].[Id] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e1] ON [j].[TwoId] = [e1].[Id] - WHERE (([e].[Key1] = [j].[CompositeId1]) AND ([e].[Key2] = [j].[CompositeId2])) AND ([e].[Key3] = [j].[CompositeId3]) - ORDER BY [e1].[Id]) = ( SELECT TOP(1) [e2].[Id] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e2] ON [j0].[ThreeId] = [e2].[Id] - WHERE (([e0].[Key1] = [j0].[CompositeId1]) AND ([e0].[Key2] = [j0].[CompositeId2])) AND ([e0].[Key3] = [j0].[CompositeId3]) - ORDER BY [e2].[Id]) + FROM [EntityCompositeKeyEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[TwoSkipSharedId] = [e2].[Id] + WHERE (([e].[Key1] = [e1].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [e1].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [e1].[CompositeKeySkipSharedKey3]) + ORDER BY [e2].[Id]) = ( + SELECT TOP(1) [e3].[Id] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e3] ON [j].[ThreeId] = [e3].[Id] + WHERE (([e0].[Key1] = [j].[CompositeId1]) AND ([e0].[Key2] = [j].[CompositeId2])) AND ([e0].[Key3] = [j].[CompositeId3]) + ORDER BY [e3].[Id]) ORDER BY [e].[Key1], [e0].[Key1], [e].[Key2], [e0].[Key2]"); } @@ -397,10 +397,10 @@ public override async Task Select_many_over_skip_navigation(bool async) @"SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[EntityRootId] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[RootSkipSharedId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityThrees] AS [e1] ON [e0].[EntityThreeId] = [e1].[Id] -) AS [t] ON [e].[Id] = [t].[EntityRootId]"); + INNER JOIN [EntityThrees] AS [e1] ON [e0].[ThreeSkipSharedId] = [e1].[Id] +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId]"); } public override async Task Select_many_over_skip_navigation_where(bool async) @@ -479,11 +479,11 @@ public override async Task Select_many_over_skip_navigation_of_type(bool async) @"SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen] FROM [EntityThrees] AS [e] INNER JOIN ( - SELECT [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen], [e0].[EntityThreeId] + SELECT [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityRoots] AS [e1] ON [e0].[EntityRootId] = [e1].[Id] + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] WHERE [e1].[Discriminator] IN (N'EntityBranch', N'EntityLeaf') -) AS [t] ON [e].[Id] = [t].[EntityThreeId]"); +) AS [t] ON [e].[Id] = [t].[ThreeSkipSharedId]"); } public override async Task Select_many_over_skip_navigation_cast(bool async) @@ -524,7 +524,7 @@ public override async Task Select_skip_navigation_multiple(bool async) await base.Select_skip_navigation_multiple(async); AssertSql( - @"SELECT [e].[Id], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[ThreeId], [t].[TwoId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[LeftId], [t0].[RightId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[TwoId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3] + @"SELECT [e].[Id], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[ThreeId], [t].[TwoId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[TwoSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3] FROM [EntityTwos] AS [e] LEFT JOIN ( SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [j].[ThreeId], [j].[TwoId] @@ -532,16 +532,16 @@ FROM [JoinTwoToThree] AS [j] INNER JOIN [EntityThrees] AS [e0] ON [j].[ThreeId] = [e0].[Id] ) AS [t] ON [e].[Id] = [t].[TwoId] LEFT JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [j0].[LeftId], [j0].[RightId] - FROM [JoinTwoSelfShared] AS [j0] - INNER JOIN [EntityTwos] AS [e1] ON [j0].[LeftId] = [e1].[Id] -) AS [t0] ON [e].[Id] = [t0].[RightId] + SELECT [e2].[Id], [e2].[CollectionInverseId], [e2].[ExtraId], [e2].[Name], [e2].[ReferenceInverseId], [e1].[SelfSkipSharedLeftId], [e1].[SelfSkipSharedRightId] + FROM [EntityTwoEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[SelfSkipSharedLeftId] = [e2].[Id] +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedRightId] LEFT JOIN ( - SELECT [e2].[Key1], [e2].[Key2], [e2].[Key3], [e2].[Name], [j1].[TwoId], [j1].[CompositeId1], [j1].[CompositeId2], [j1].[CompositeId3] - FROM [JoinTwoToCompositeKeyShared] AS [j1] - INNER JOIN [EntityCompositeKeys] AS [e2] ON (([j1].[CompositeId1] = [e2].[Key1]) AND ([j1].[CompositeId2] = [e2].[Key2])) AND ([j1].[CompositeId3] = [e2].[Key3]) -) AS [t1] ON [e].[Id] = [t1].[TwoId] -ORDER BY [e].[Id], [t].[ThreeId], [t].[TwoId], [t].[Id], [t0].[LeftId], [t0].[RightId], [t0].[Id], [t1].[TwoId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[Key1], [t1].[Key2]"); + SELECT [e4].[Key1], [e4].[Key2], [e4].[Key3], [e4].[Name], [e3].[TwoSkipSharedId], [e3].[CompositeKeySkipSharedKey1], [e3].[CompositeKeySkipSharedKey2], [e3].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityTwo] AS [e3] + INNER JOIN [EntityCompositeKeys] AS [e4] ON (([e3].[CompositeKeySkipSharedKey1] = [e4].[Key1]) AND ([e3].[CompositeKeySkipSharedKey2] = [e4].[Key2])) AND ([e3].[CompositeKeySkipSharedKey3] = [e4].[Key3]) +) AS [t1] ON [e].[Id] = [t1].[TwoSkipSharedId] +ORDER BY [e].[Id], [t].[ThreeId], [t].[TwoId], [t].[Id], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t0].[Id], [t1].[TwoSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2]"); } public override async Task Select_skip_navigation_first_or_default(bool async) @@ -568,14 +568,14 @@ public override async Task Include_skip_navigation(bool async) await base.Include_skip_navigation(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [e0].[Id], [e0].[Discriminator], [e0].[Name], [e0].[Number], [e0].[IsGreen] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityRoots] AS [e0] ON [j].[RootId] = [e0].[Id] -) AS [t] ON (([e].[Key1] = [t].[CompositeId1]) AND ([e].[Key2] = [t].[CompositeId2])) AND ([e].[Key3] = [t].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId]"); + SELECT [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] +) AS [t] ON (([e].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3]"); } public override async Task Include_skip_navigation_then_reference(bool async) @@ -691,18 +691,18 @@ public override async Task Filtered_include_skip_navigation_order_by_skip(bool a await base.Filtered_include_skip_navigation_order_by_skip(async); AssertSql( - @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [t0].[LeftId], [t0].[RightId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId] + @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId] FROM [EntityTwos] AS [e] LEFT JOIN ( - SELECT [t].[LeftId], [t].[RightId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] + SELECT [t].[SelfSkipSharedLeftId], [t].[SelfSkipSharedRightId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j].[LeftId], [j].[RightId], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[LeftId] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[RightId] = [e0].[Id] + SELECT [e0].[SelfSkipSharedLeftId], [e0].[SelfSkipSharedRightId], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [e0].[SelfSkipSharedLeftId] ORDER BY [e1].[Id]) AS [row] + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedRightId] = [e1].[Id] ) AS [t] WHERE 2 < [t].[row] -) AS [t0] ON [e].[Id] = [t0].[LeftId] -ORDER BY [e].[Id], [t0].[LeftId], [t0].[Id]"); +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedLeftId] +ORDER BY [e].[Id], [t0].[SelfSkipSharedLeftId], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_take(bool async) @@ -710,18 +710,18 @@ public override async Task Filtered_include_skip_navigation_order_by_take(bool a await base.Filtered_include_skip_navigation_order_by_take(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[TwoId], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [t].[TwoId], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] + SELECT [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j].[TwoId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[TwoId] = [e0].[Id] + SELECT [e0].[TwoSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] ORDER BY [e1].[Id]) AS [row] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] ) AS [t] WHERE [t].[row] <= 2 -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take(bool async) @@ -748,20 +748,20 @@ public override async Task Filtered_then_include_skip_navigation_where(bool asyn await base.Filtered_then_include_skip_navigation_where(async); AssertSql( - @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t0].[EntityRootId], [t0].[EntityThreeId], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[OneId], [t0].[ThreeId], [t0].[Payload], [t0].[Id0], [t0].[Name0] + @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t0].[RootSkipSharedId], [t0].[ThreeSkipSharedId], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[OneId], [t0].[ThreeId], [t0].[Payload], [t0].[Id0], [t0].[Name0] FROM [EntityRoots] AS [e] LEFT JOIN ( - SELECT [e0].[EntityRootId], [e0].[EntityThreeId], [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [t].[OneId], [t].[ThreeId], [t].[Payload], [t].[Id] AS [Id0], [t].[Name] AS [Name0] + SELECT [e0].[RootSkipSharedId], [e0].[ThreeSkipSharedId], [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [t].[OneId], [t].[ThreeId], [t].[Payload], [t].[Id] AS [Id0], [t].[Name] AS [Name0] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityThrees] AS [e1] ON [e0].[EntityThreeId] = [e1].[Id] + INNER JOIN [EntityThrees] AS [e1] ON [e0].[ThreeSkipSharedId] = [e1].[Id] LEFT JOIN ( SELECT [j].[OneId], [j].[ThreeId], [j].[Payload], [e2].[Id], [e2].[Name] FROM [JoinOneToThreePayloadFullShared] AS [j] INNER JOIN [EntityOnes] AS [e2] ON [j].[OneId] = [e2].[Id] WHERE [e2].[Id] < 10 ) AS [t] ON [e1].[Id] = [t].[ThreeId] -) AS [t0] ON [e].[Id] = [t0].[EntityRootId] -ORDER BY [e].[Id], [t0].[EntityRootId], [t0].[EntityThreeId], [t0].[Id], [t0].[OneId], [t0].[ThreeId]"); +) AS [t0] ON [e].[Id] = [t0].[RootSkipSharedId] +ORDER BY [e].[Id], [t0].[RootSkipSharedId], [t0].[ThreeSkipSharedId], [t0].[Id], [t0].[OneId], [t0].[ThreeId]"); } public override async Task Filtered_then_include_skip_navigation_order_by_skip_take(bool async) @@ -769,23 +769,23 @@ public override async Task Filtered_then_include_skip_navigation_order_by_skip_t await base.Filtered_then_include_skip_navigation_order_by_skip_take(async); AssertSql( - @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[RootId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[Id], [t1].[CompositeId10], [t1].[CompositeId20], [t1].[CompositeId30], [t1].[ThreeId], [t1].[Id0], [t1].[CollectionInverseId], [t1].[Name0], [t1].[ReferenceInverseId] + @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t1].[RootSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[Id], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[ThreeId], [t1].[Id0], [t1].[CollectionInverseId], [t1].[Name0], [t1].[ReferenceInverseId] FROM [EntityRoots] AS [e] LEFT JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [t0].[Id], [t0].[CompositeId1] AS [CompositeId10], [t0].[CompositeId2] AS [CompositeId20], [t0].[CompositeId3] AS [CompositeId30], [t0].[ThreeId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[Name] AS [Name0], [t0].[ReferenceInverseId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) + SELECT [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Key1], [e1].[Key2], [e1].[Key3], [e1].[Name], [t0].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[ThreeId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[Name] AS [Name0], [t0].[ReferenceInverseId] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) LEFT JOIN ( SELECT [t].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[ThreeId], [t].[Id0], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j0].[Id], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], [j0].[ThreeId], [e1].[Id] AS [Id0], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] ORDER BY [e1].[Id]) AS [row] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e1] ON [j0].[ThreeId] = [e1].[Id] + SELECT [j].[Id], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[ThreeId], [e2].[Id] AS [Id0], [e2].[CollectionInverseId], [e2].[Name], [e2].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e2].[Id]) AS [row] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e2] ON [j].[ThreeId] = [e2].[Id] ) AS [t] WHERE (1 < [t].[row]) AND ([t].[row] <= 3) - ) AS [t0] ON (([e0].[Key1] = [t0].[CompositeId1]) AND ([e0].[Key2] = [t0].[CompositeId2])) AND ([e0].[Key3] = [t0].[CompositeId3]) -) AS [t1] ON [e].[Id] = [t1].[RootId] -ORDER BY [e].[Id], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[RootId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[CompositeId10], [t1].[CompositeId20], [t1].[CompositeId30], [t1].[Id0]"); + ) AS [t0] ON (([e1].[Key1] = [t0].[CompositeId1]) AND ([e1].[Key2] = [t0].[CompositeId2])) AND ([e1].[Key3] = [t0].[CompositeId3]) +) AS [t1] ON [e].[Id] = [t1].[RootSkipSharedId] +ORDER BY [e].[Id], [t1].[RootSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[Id0]"); } public override async Task Filtered_include_skip_navigation_where_then_include_skip_navigation(bool async) @@ -793,21 +793,21 @@ public override async Task Filtered_include_skip_navigation_where_then_include_s await base.Filtered_include_skip_navigation_where_then_include_skip_navigation(async); AssertSql( - @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[Name], [t0].[TwoId], [t0].[CompositeId10], [t0].[CompositeId20], [t0].[CompositeId30], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId] + @"SELECT [e].[Id], [e].[Discriminator], [e].[Name], [e].[Number], [e].[IsGreen], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[Name], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId] FROM [EntityRoots] AS [e] LEFT JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[LeafId], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [t].[TwoId], [t].[CompositeId1] AS [CompositeId10], [t].[CompositeId2] AS [CompositeId20], [t].[CompositeId3] AS [CompositeId30], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name] AS [Name0], [t].[ReferenceInverseId] + SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[LeafId], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name] AS [Name0], [t].[ReferenceInverseId] FROM [JoinCompositeKeyToLeaf] AS [j] INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) LEFT JOIN ( - SELECT [j0].[TwoId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId] - FROM [JoinTwoToCompositeKeyShared] AS [j0] - INNER JOIN [EntityTwos] AS [e1] ON [j0].[TwoId] = [e1].[Id] - ) AS [t] ON (([e0].[Key1] = [t].[CompositeId1]) AND ([e0].[Key2] = [t].[CompositeId2])) AND ([e0].[Key3] = [t].[CompositeId3]) + SELECT [e1].[TwoSkipSharedId], [e1].[CompositeKeySkipSharedKey1], [e1].[CompositeKeySkipSharedKey2], [e1].[CompositeKeySkipSharedKey3], [e2].[Id], [e2].[CollectionInverseId], [e2].[ExtraId], [e2].[Name], [e2].[ReferenceInverseId] + FROM [EntityCompositeKeyEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[TwoSkipSharedId] = [e2].[Id] + ) AS [t] ON (([e0].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e0].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e0].[Key3] = [t].[CompositeKeySkipSharedKey3]) WHERE [e0].[Key1] < 5 ) AS [t0] ON [e].[Id] = [t0].[LeafId] WHERE [e].[Discriminator] = N'EntityLeaf' -ORDER BY [e].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[TwoId], [t0].[CompositeId10], [t0].[CompositeId20], [t0].[CompositeId30]"); +ORDER BY [e].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take_then_include_skip_navigation_where(bool async) @@ -980,13 +980,13 @@ public override async Task Include_skip_navigation_split(bool async) FROM [EntityCompositeKeys] AS [e] ORDER BY [e].[Key1], [e].[Key2], [e].[Key3]", // - @"SELECT [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen], [e].[Key1], [e].[Key2], [e].[Key3] + @"SELECT [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Id], [t].[Discriminator], [t].[Name], [t].[Number], [t].[IsGreen], [e].[Key1], [e].[Key2], [e].[Key3] FROM [EntityCompositeKeys] AS [e] INNER JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [e0].[Id], [e0].[Discriminator], [e0].[Name], [e0].[Number], [e0].[IsGreen] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityRoots] AS [e0] ON [j].[RootId] = [e0].[Id] -) AS [t] ON (([e].[Key1] = [t].[CompositeId1]) AND ([e].[Key2] = [t].[CompositeId2])) AND ([e].[Key3] = [t].[CompositeId3]) + SELECT [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Id], [e1].[Discriminator], [e1].[Name], [e1].[Number], [e1].[IsGreen] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityRoots] AS [e1] ON [e0].[RootSkipSharedId] = [e1].[Id] +) AS [t] ON (([e].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t].[CompositeKeySkipSharedKey3]) ORDER BY [e].[Key1], [e].[Key2], [e].[Key3]"); } @@ -1155,18 +1155,18 @@ public override async Task Filtered_include_skip_navigation_order_by_skip_split( FROM [EntityTwos] AS [e] ORDER BY [e].[Id]", // - @"SELECT [t0].[LeftId], [t0].[RightId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id] + @"SELECT [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id] FROM [EntityTwos] AS [e] INNER JOIN ( - SELECT [t].[LeftId], [t].[RightId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] + SELECT [t].[SelfSkipSharedLeftId], [t].[SelfSkipSharedRightId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j].[LeftId], [j].[RightId], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[LeftId] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[RightId] = [e0].[Id] + SELECT [e0].[SelfSkipSharedLeftId], [e0].[SelfSkipSharedRightId], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [e0].[SelfSkipSharedLeftId] ORDER BY [e1].[Id]) AS [row] + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedRightId] = [e1].[Id] ) AS [t] WHERE 2 < [t].[row] -) AS [t0] ON [e].[Id] = [t0].[LeftId] -ORDER BY [e].[Id], [t0].[LeftId], [t0].[Id]"); +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedLeftId] +ORDER BY [e].[Id], [t0].[SelfSkipSharedLeftId], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_take_split(bool async) @@ -1178,18 +1178,18 @@ public override async Task Filtered_include_skip_navigation_order_by_take_split( FROM [EntityCompositeKeys] AS [e] ORDER BY [e].[Key1], [e].[Key2], [e].[Key3]", // - @"SELECT [t0].[TwoId], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Key1], [e].[Key2], [e].[Key3] + @"SELECT [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Key1], [e].[Key2], [e].[Key3] FROM [EntityCompositeKeys] AS [e] INNER JOIN ( - SELECT [t].[TwoId], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] + SELECT [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j].[TwoId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[TwoId] = [e0].[Id] + SELECT [e0].[TwoSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] ORDER BY [e1].[Id]) AS [row] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] ) AS [t] WHERE [t].[row] <= 2 -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take_split(bool async) @@ -1224,29 +1224,29 @@ public override async Task Filtered_then_include_skip_navigation_where_split(boo FROM [EntityRoots] AS [e] ORDER BY [e].[Id]", // - @"SELECT [t].[EntityRootId], [t].[EntityThreeId], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [e].[Id] + @"SELECT [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [e].[Id] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e0].[EntityRootId], [e0].[EntityThreeId], [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId] + SELECT [e0].[RootSkipSharedId], [e0].[ThreeSkipSharedId], [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityThrees] AS [e1] ON [e0].[EntityThreeId] = [e1].[Id] -) AS [t] ON [e].[Id] = [t].[EntityRootId] -ORDER BY [e].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id]", + INNER JOIN [EntityThrees] AS [e1] ON [e0].[ThreeSkipSharedId] = [e1].[Id] +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId] +ORDER BY [e].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id]", // - @"SELECT [t0].[OneId], [t0].[ThreeId], [t0].[Payload], [t0].[Id], [t0].[Name], [e].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id] + @"SELECT [t0].[OneId], [t0].[ThreeId], [t0].[Payload], [t0].[Id], [t0].[Name], [e].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [e0].[EntityRootId], [e0].[EntityThreeId], [e1].[Id] + SELECT [e0].[RootSkipSharedId], [e0].[ThreeSkipSharedId], [e1].[Id] FROM [EntityRootEntityThree] AS [e0] - INNER JOIN [EntityThrees] AS [e1] ON [e0].[EntityThreeId] = [e1].[Id] -) AS [t] ON [e].[Id] = [t].[EntityRootId] + INNER JOIN [EntityThrees] AS [e1] ON [e0].[ThreeSkipSharedId] = [e1].[Id] +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId] INNER JOIN ( SELECT [j].[OneId], [j].[ThreeId], [j].[Payload], [e2].[Id], [e2].[Name] FROM [JoinOneToThreePayloadFullShared] AS [j] INNER JOIN [EntityOnes] AS [e2] ON [j].[OneId] = [e2].[Id] WHERE [e2].[Id] < 10 ) AS [t0] ON [t].[Id] = [t0].[ThreeId] -ORDER BY [e].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id]"); +ORDER BY [e].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id]"); } public override async Task Filtered_then_include_skip_navigation_order_by_skip_take_split(bool async) @@ -1258,32 +1258,32 @@ public override async Task Filtered_then_include_skip_navigation_order_by_skip_t FROM [EntityRoots] AS [e] ORDER BY [e].[Id]", // - @"SELECT [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3], [t].[Name], [e].[Id] + @"SELECT [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3], [t].[Name], [e].[Id] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[RootId] -ORDER BY [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3]", + SELECT [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Key1], [e1].[Key2], [e1].[Key3], [e1].[Name] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId] +ORDER BY [e].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3]", // - @"SELECT [t0].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[ThreeId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3] + @"SELECT [t0].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[ThreeId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3] FROM [EntityRoots] AS [e] INNER JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [e0].[Key1], [e0].[Key2], [e0].[Key3] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[RootId] + SELECT [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Key1], [e1].[Key2], [e1].[Key3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[RootSkipSharedId] INNER JOIN ( SELECT [t1].[Id], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[ThreeId], [t1].[Id0], [t1].[CollectionInverseId], [t1].[Name], [t1].[ReferenceInverseId] FROM ( - SELECT [j0].[Id], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], [j0].[ThreeId], [e1].[Id] AS [Id0], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] ORDER BY [e1].[Id]) AS [row] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e1] ON [j0].[ThreeId] = [e1].[Id] + SELECT [j].[Id], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[ThreeId], [e2].[Id] AS [Id0], [e2].[CollectionInverseId], [e2].[Name], [e2].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e2].[Id]) AS [row] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e2] ON [j].[ThreeId] = [e2].[Id] ) AS [t1] WHERE (1 < [t1].[row]) AND ([t1].[row] <= 3) ) AS [t0] ON (([t].[Key1] = [t0].[CompositeId1]) AND ([t].[Key2] = [t0].[CompositeId2])) AND ([t].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id0]"); +ORDER BY [e].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id0]"); } public override async Task Filtered_include_skip_navigation_where_then_include_skip_navigation_split(bool async) @@ -1307,7 +1307,7 @@ WHERE [e0].[Key1] < 5 WHERE [e].[Discriminator] = N'EntityLeaf' ORDER BY [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3]", // - @"SELECT [t0].[TwoId], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3] + @"SELECT [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3] FROM [EntityRoots] AS [e] INNER JOIN ( SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[LeafId], [e0].[Key1], [e0].[Key2], [e0].[Key3] @@ -1316,10 +1316,10 @@ INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) WHERE [e0].[Key1] < 5 ) AS [t] ON [e].[Id] = [t].[LeafId] INNER JOIN ( - SELECT [j0].[TwoId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId] - FROM [JoinTwoToCompositeKeyShared] AS [j0] - INNER JOIN [EntityTwos] AS [e1] ON [j0].[TwoId] = [e1].[Id] -) AS [t0] ON (([t].[Key1] = [t0].[CompositeId1]) AND ([t].[Key2] = [t0].[CompositeId2])) AND ([t].[Key3] = [t0].[CompositeId3]) + SELECT [e1].[TwoSkipSharedId], [e1].[CompositeKeySkipSharedKey1], [e1].[CompositeKeySkipSharedKey2], [e1].[CompositeKeySkipSharedKey3], [e2].[Id], [e2].[CollectionInverseId], [e2].[ExtraId], [e2].[Name], [e2].[ReferenceInverseId] + FROM [EntityCompositeKeyEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[TwoSkipSharedId] = [e2].[Id] +) AS [t0] ON (([t].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([t].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([t].[Key3] = [t0].[CompositeKeySkipSharedKey3]) WHERE [e].[Discriminator] = N'EntityLeaf' ORDER BY [e].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyNoTrackingQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyNoTrackingQuerySqlServerTest.cs index 077f6ce7d67..1d35c33bc87 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyNoTrackingQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyNoTrackingQuerySqlServerTest.cs @@ -133,9 +133,9 @@ public override async Task Skip_navigation_long_count_with_predicate(bool async) FROM [EntityTwos] AS [e] ORDER BY ( SELECT COUNT_BIG(*) - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[LeftId] = [e0].[Id] - WHERE ([e].[Id] = [j].[RightId]) AND ([e0].[Name] IS NOT NULL AND ([e0].[Name] LIKE N'L%'))) DESC, [e].[Id]"); + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedLeftId] = [e1].[Id] + WHERE ([e].[Id] = [e0].[SelfSkipSharedRightId]) AND ([e1].[Name] IS NOT NULL AND ([e1].[Name] LIKE N'L%'))) DESC, [e].[Id]"); } public override async Task Skip_navigation_select_many_average(bool async) @@ -146,10 +146,10 @@ public override async Task Skip_navigation_select_many_average(bool async) @"SELECT AVG(CAST([t].[Key1] AS float)) FROM [EntityTwos] AS [e] INNER JOIN ( - SELECT [e0].[Key1], [j].[TwoId] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[TwoId]"); + SELECT [e1].[Key1], [e0].[TwoSkipSharedId] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[TwoSkipSharedId]"); } public override async Task Skip_navigation_select_many_max(bool async) @@ -174,13 +174,13 @@ public override async Task Skip_navigation_select_many_min(bool async) @"SELECT MIN([t0].[Id]) FROM [EntityThrees] AS [e] INNER JOIN ( - SELECT [t].[Id], [e0].[EntityThreeId] + SELECT [t].[Id], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] INNER JOIN ( SELECT [r].[Id] FROM [Roots] AS [r] - ) AS [t] ON [e0].[EntityRootId] = [t].[Id] -) AS [t0] ON [e].[Id] = [t0].[EntityThreeId]"); + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] +) AS [t0] ON [e].[Id] = [t0].[ThreeSkipSharedId]"); } public override async Task Skip_navigation_select_many_sum(bool async) @@ -191,10 +191,10 @@ public override async Task Skip_navigation_select_many_sum(bool async) @"SELECT COALESCE(SUM([t].[Key1]), 0) FROM [Roots] AS [r] INNER JOIN ( - SELECT [e].[Key1], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) -) AS [t] ON [r].[Id] = [t].[RootId]"); + SELECT [e0].[Key1], [e].[RootSkipSharedId] + FROM [EntityCompositeKeyEntityRoot] AS [e] + INNER JOIN [EntityCompositeKeys] AS [e0] ON (([e].[CompositeKeySkipSharedKey1] = [e0].[Key1]) AND ([e].[CompositeKeySkipSharedKey2] = [e0].[Key2])) AND ([e].[CompositeKeySkipSharedKey3] = [e0].[Key3]) +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId]"); } public override async Task Skip_navigation_select_subquery_average(bool async) @@ -351,11 +351,11 @@ public override async Task Skip_navigation_of_type(bool async) await base.Skip_navigation_of_type(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[RootId] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator], [t0].[RootSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] + SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] INNER JOIN ( SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' @@ -364,10 +364,10 @@ END AS [Discriminator] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] - ) AS [t] ON [j].[RootId] = [t].[Id] + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] WHERE [t].[Discriminator] = N'EntityLeaf' -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[RootId]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[RootSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3]"); } public override async Task Join_with_skip_navigation(bool async) @@ -378,11 +378,11 @@ public override async Task Join_with_skip_navigation(bool async) @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId] FROM [EntityTwos] AS [e] INNER JOIN [EntityTwos] AS [e0] ON [e].[Id] = ( - SELECT TOP(1) [e1].[Id] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e1] ON [j].[RightId] = [e1].[Id] - WHERE [e0].[Id] = [j].[LeftId] - ORDER BY [e1].[Id])"); + SELECT TOP(1) [e2].[Id] + FROM [EntityTwoEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[SelfSkipSharedRightId] = [e2].[Id] + WHERE [e0].[Id] = [e1].[SelfSkipSharedLeftId] + ORDER BY [e2].[Id])"); } public override async Task Left_join_with_skip_navigation(bool async) @@ -393,16 +393,16 @@ public override async Task Left_join_with_skip_navigation(bool async) @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name] FROM [EntityCompositeKeys] AS [e] LEFT JOIN [EntityCompositeKeys] AS [e0] ON ( - SELECT TOP(1) [e1].[Id] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e1] ON [j].[TwoId] = [e1].[Id] - WHERE (([e].[Key1] = [j].[CompositeId1]) AND ([e].[Key2] = [j].[CompositeId2])) AND ([e].[Key3] = [j].[CompositeId3]) - ORDER BY [e1].[Id]) = ( SELECT TOP(1) [e2].[Id] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e2] ON [j0].[ThreeId] = [e2].[Id] - WHERE (([e0].[Key1] = [j0].[CompositeId1]) AND ([e0].[Key2] = [j0].[CompositeId2])) AND ([e0].[Key3] = [j0].[CompositeId3]) - ORDER BY [e2].[Id]) + FROM [EntityCompositeKeyEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[TwoSkipSharedId] = [e2].[Id] + WHERE (([e].[Key1] = [e1].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [e1].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [e1].[CompositeKeySkipSharedKey3]) + ORDER BY [e2].[Id]) = ( + SELECT TOP(1) [e3].[Id] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e3] ON [j].[ThreeId] = [e3].[Id] + WHERE (([e0].[Key1] = [j].[CompositeId1]) AND ([e0].[Key2] = [j].[CompositeId2])) AND ([e0].[Key3] = [j].[CompositeId3]) + ORDER BY [e3].[Id]) ORDER BY [e].[Key1], [e0].[Key1], [e].[Key2], [e0].[Key2]"); } @@ -414,10 +414,10 @@ public override async Task Select_many_over_skip_navigation(bool async) @"SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId] FROM [Roots] AS [r] INNER JOIN ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [e].[EntityRootId] + SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [e].[RootSkipSharedId] FROM [EntityRootEntityThree] AS [e] - INNER JOIN [EntityThrees] AS [e0] ON [e].[EntityThreeId] = [e0].[Id] -) AS [t] ON [r].[Id] = [t].[EntityRootId]"); + INNER JOIN [EntityThrees] AS [e0] ON [e].[ThreeSkipSharedId] = [e0].[Id] +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId]"); } public override async Task Select_many_over_skip_navigation_where(bool async) @@ -496,7 +496,7 @@ public override async Task Select_many_over_skip_navigation_of_type(bool async) @"SELECT [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator] FROM [EntityThrees] AS [e] INNER JOIN ( - SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [e0].[EntityThreeId] + SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] INNER JOIN ( SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE @@ -506,9 +506,9 @@ END AS [Discriminator] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] - ) AS [t] ON [e0].[EntityRootId] = [t].[Id] + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] WHERE [t].[Discriminator] IN (N'EntityBranch', N'EntityLeaf') -) AS [t0] ON [e].[Id] = [t0].[EntityThreeId]"); +) AS [t0] ON [e].[Id] = [t0].[ThreeSkipSharedId]"); } public override async Task Select_many_over_skip_navigation_cast(bool async) @@ -552,7 +552,7 @@ public override async Task Select_skip_navigation_multiple(bool async) await base.Select_skip_navigation_multiple(async); AssertSql( - @"SELECT [e].[Id], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[ThreeId], [t].[TwoId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[LeftId], [t0].[RightId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[TwoId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3] + @"SELECT [e].[Id], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[ThreeId], [t].[TwoId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[TwoSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3] FROM [EntityTwos] AS [e] LEFT JOIN ( SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [j].[ThreeId], [j].[TwoId] @@ -560,16 +560,16 @@ FROM [JoinTwoToThree] AS [j] INNER JOIN [EntityThrees] AS [e0] ON [j].[ThreeId] = [e0].[Id] ) AS [t] ON [e].[Id] = [t].[TwoId] LEFT JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [j0].[LeftId], [j0].[RightId] - FROM [JoinTwoSelfShared] AS [j0] - INNER JOIN [EntityTwos] AS [e1] ON [j0].[LeftId] = [e1].[Id] -) AS [t0] ON [e].[Id] = [t0].[RightId] + SELECT [e2].[Id], [e2].[CollectionInverseId], [e2].[ExtraId], [e2].[Name], [e2].[ReferenceInverseId], [e1].[SelfSkipSharedLeftId], [e1].[SelfSkipSharedRightId] + FROM [EntityTwoEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[SelfSkipSharedLeftId] = [e2].[Id] +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedRightId] LEFT JOIN ( - SELECT [e2].[Key1], [e2].[Key2], [e2].[Key3], [e2].[Name], [j1].[TwoId], [j1].[CompositeId1], [j1].[CompositeId2], [j1].[CompositeId3] - FROM [JoinTwoToCompositeKeyShared] AS [j1] - INNER JOIN [EntityCompositeKeys] AS [e2] ON (([j1].[CompositeId1] = [e2].[Key1]) AND ([j1].[CompositeId2] = [e2].[Key2])) AND ([j1].[CompositeId3] = [e2].[Key3]) -) AS [t1] ON [e].[Id] = [t1].[TwoId] -ORDER BY [e].[Id], [t].[ThreeId], [t].[TwoId], [t].[Id], [t0].[LeftId], [t0].[RightId], [t0].[Id], [t1].[TwoId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[Key1], [t1].[Key2]"); + SELECT [e4].[Key1], [e4].[Key2], [e4].[Key3], [e4].[Name], [e3].[TwoSkipSharedId], [e3].[CompositeKeySkipSharedKey1], [e3].[CompositeKeySkipSharedKey2], [e3].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityTwo] AS [e3] + INNER JOIN [EntityCompositeKeys] AS [e4] ON (([e3].[CompositeKeySkipSharedKey1] = [e4].[Key1]) AND ([e3].[CompositeKeySkipSharedKey2] = [e4].[Key2])) AND ([e3].[CompositeKeySkipSharedKey3] = [e4].[Key3]) +) AS [t1] ON [e].[Id] = [t1].[TwoSkipSharedId] +ORDER BY [e].[Id], [t].[ThreeId], [t].[TwoId], [t].[Id], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t0].[Id], [t1].[TwoSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2]"); } public override async Task Select_skip_navigation_first_or_default(bool async) @@ -596,11 +596,11 @@ public override async Task Include_skip_navigation(bool async) await base.Include_skip_navigation(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[RootId] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator], [t0].[RootSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] + SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] INNER JOIN ( SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' @@ -609,9 +609,9 @@ END AS [Discriminator] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] - ) AS [t] ON [j].[RootId] = [t].[Id] -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[RootId]"); + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[RootSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3]"); } public override async Task Include_skip_navigation_then_reference(bool async) @@ -728,18 +728,18 @@ public override async Task Filtered_include_skip_navigation_order_by_skip(bool a await base.Filtered_include_skip_navigation_order_by_skip(async); AssertSql( - @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[LeftId], [t0].[RightId] + @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId] FROM [EntityTwos] AS [e] LEFT JOIN ( - SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[LeftId], [t].[RightId] + SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[SelfSkipSharedLeftId], [t].[SelfSkipSharedRightId] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j].[LeftId], [j].[RightId], ROW_NUMBER() OVER(PARTITION BY [j].[LeftId] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[RightId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[SelfSkipSharedLeftId], [e0].[SelfSkipSharedRightId], ROW_NUMBER() OVER(PARTITION BY [e0].[SelfSkipSharedLeftId] ORDER BY [e1].[Id]) AS [row] + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedRightId] = [e1].[Id] ) AS [t] WHERE 2 < [t].[row] -) AS [t0] ON [e].[Id] = [t0].[LeftId] -ORDER BY [e].[Id], [t0].[LeftId], [t0].[Id]"); +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedLeftId] +ORDER BY [e].[Id], [t0].[SelfSkipSharedLeftId], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_take(bool async) @@ -747,18 +747,18 @@ public override async Task Filtered_include_skip_navigation_order_by_take(bool a await base.Filtered_include_skip_navigation_order_by_take(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[TwoId], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[TwoId], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3] + SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j].[TwoId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[TwoId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[TwoSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], ROW_NUMBER() OVER(PARTITION BY [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] ORDER BY [e1].[Id]) AS [row] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] ) AS [t] WHERE [t].[row] <= 2 -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take(bool async) @@ -788,22 +788,22 @@ public override async Task Filtered_then_include_skip_navigation_where(bool asyn @"SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' WHEN [b].[Id] IS NOT NULL THEN N'EntityBranch' -END AS [Discriminator], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[EntityRootId], [t0].[EntityThreeId], [t0].[Id0], [t0].[Name0], [t0].[OneId], [t0].[ThreeId] +END AS [Discriminator], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[RootSkipSharedId], [t0].[ThreeSkipSharedId], [t0].[Id0], [t0].[Name0], [t0].[OneId], [t0].[ThreeId] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] LEFT JOIN ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [e].[EntityRootId], [e].[EntityThreeId], [t].[Id] AS [Id0], [t].[Name] AS [Name0], [t].[OneId], [t].[ThreeId] + SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [e].[RootSkipSharedId], [e].[ThreeSkipSharedId], [t].[Id] AS [Id0], [t].[Name] AS [Name0], [t].[OneId], [t].[ThreeId] FROM [EntityRootEntityThree] AS [e] - INNER JOIN [EntityThrees] AS [e0] ON [e].[EntityThreeId] = [e0].[Id] + INNER JOIN [EntityThrees] AS [e0] ON [e].[ThreeSkipSharedId] = [e0].[Id] LEFT JOIN ( SELECT [e1].[Id], [e1].[Name], [j].[OneId], [j].[ThreeId] FROM [JoinOneToThreePayloadFullShared] AS [j] INNER JOIN [EntityOnes] AS [e1] ON [j].[OneId] = [e1].[Id] WHERE [e1].[Id] < 10 ) AS [t] ON [e0].[Id] = [t].[ThreeId] -) AS [t0] ON [r].[Id] = [t0].[EntityRootId] -ORDER BY [r].[Id], [t0].[EntityRootId], [t0].[EntityThreeId], [t0].[Id], [t0].[OneId], [t0].[ThreeId]"); +) AS [t0] ON [r].[Id] = [t0].[RootSkipSharedId] +ORDER BY [r].[Id], [t0].[RootSkipSharedId], [t0].[ThreeSkipSharedId], [t0].[Id], [t0].[OneId], [t0].[ThreeId]"); } public override async Task Filtered_then_include_skip_navigation_order_by_skip_take(bool async) @@ -814,25 +814,25 @@ public override async Task Filtered_then_include_skip_navigation_order_by_skip_t @"SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' WHEN [b].[Id] IS NOT NULL THEN N'EntityBranch' -END AS [Discriminator], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[RootId], [t1].[Id], [t1].[CollectionInverseId], [t1].[Name0], [t1].[ReferenceInverseId], [t1].[Id0] +END AS [Discriminator], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[RootSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Id], [t1].[CollectionInverseId], [t1].[Name0], [t1].[ReferenceInverseId], [t1].[Id0] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] LEFT JOIN ( - SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name] AS [Name0], [t0].[ReferenceInverseId], [t0].[Id0], [t0].[CompositeId1] AS [CompositeId10], [t0].[CompositeId2] AS [CompositeId20], [t0].[CompositeId3] AS [CompositeId30] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) + SELECT [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [e].[RootSkipSharedId], [e].[CompositeKeySkipSharedKey1], [e].[CompositeKeySkipSharedKey2], [e].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name] AS [Name0], [t0].[ReferenceInverseId], [t0].[Id0], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3] + FROM [EntityCompositeKeyEntityRoot] AS [e] + INNER JOIN [EntityCompositeKeys] AS [e0] ON (([e].[CompositeKeySkipSharedKey1] = [e0].[Key1]) AND ([e].[CompositeKeySkipSharedKey2] = [e0].[Key2])) AND ([e].[CompositeKeySkipSharedKey3] = [e0].[Key3]) LEFT JOIN ( SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[Id0], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [j0].[Id] AS [Id0], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e0] ON [j0].[ThreeId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [j].[Id] AS [Id0], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e1].[Id]) AS [row] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e1] ON [j].[ThreeId] = [e1].[Id] ) AS [t] WHERE (1 < [t].[row]) AND ([t].[row] <= 3) - ) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -) AS [t1] ON [r].[Id] = [t1].[RootId] -ORDER BY [r].[Id], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[RootId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[CompositeId10], [t1].[CompositeId20], [t1].[CompositeId30], [t1].[Id]"); + ) AS [t0] ON (([e0].[Key1] = [t0].[CompositeId1]) AND ([e0].[Key2] = [t0].[CompositeId2])) AND ([e0].[Key3] = [t0].[CompositeId3]) +) AS [t1] ON [r].[Id] = [t1].[RootSkipSharedId] +ORDER BY [r].[Id], [t1].[RootSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[Id]"); } public override async Task Filtered_include_skip_navigation_where_then_include_skip_navigation(bool async) @@ -840,22 +840,22 @@ public override async Task Filtered_include_skip_navigation_where_then_include_s await base.Filtered_include_skip_navigation_where_then_include_skip_navigation(async); AssertSql( - @"SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[Name], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId], [t0].[TwoId], [t0].[CompositeId10], [t0].[CompositeId20], [t0].[CompositeId30] + @"SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[Name], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3] FROM [Roots] AS [r] INNER JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] INNER JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] LEFT JOIN ( - SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[LeafId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name] AS [Name0], [t].[ReferenceInverseId], [t].[TwoId], [t].[CompositeId1] AS [CompositeId10], [t].[CompositeId2] AS [CompositeId20], [t].[CompositeId3] AS [CompositeId30] + SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[LeafId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name] AS [Name0], [t].[ReferenceInverseId], [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM [JoinCompositeKeyToLeaf] AS [j] INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) LEFT JOIN ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j0].[TwoId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] - FROM [JoinTwoToCompositeKeyShared] AS [j0] - INNER JOIN [EntityTwos] AS [e0] ON [j0].[TwoId] = [e0].[Id] - ) AS [t] ON (([e].[Key1] = [t].[CompositeId1]) AND ([e].[Key2] = [t].[CompositeId2])) AND ([e].[Key3] = [t].[CompositeId3]) + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[TwoSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] + ) AS [t] ON (([e].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t].[CompositeKeySkipSharedKey3]) WHERE [e].[Key1] < 5 ) AS [t0] ON [r].[Id] = [t0].[LeafId] -ORDER BY [r].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[TwoId], [t0].[CompositeId10], [t0].[CompositeId20], [t0].[CompositeId30]"); +ORDER BY [r].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take_then_include_skip_navigation_where(bool async) @@ -1034,8 +1034,8 @@ FROM [EntityCompositeKeys] AS [e] @"SELECT [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator], [e].[Key1], [e].[Key2], [e].[Key3] FROM [EntityCompositeKeys] AS [e] INNER JOIN ( - SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] - FROM [JoinCompositeKeyToRootShared] AS [j] + SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] INNER JOIN ( SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' @@ -1044,8 +1044,8 @@ END AS [Discriminator] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] - ) AS [t] ON [j].[RootId] = [t].[Id] -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) ORDER BY [e].[Key1], [e].[Key2], [e].[Key3]"); } @@ -1219,15 +1219,15 @@ FROM [EntityTwos] AS [e] @"SELECT [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id] FROM [EntityTwos] AS [e] INNER JOIN ( - SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[LeftId] + SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[SelfSkipSharedLeftId] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j].[LeftId], ROW_NUMBER() OVER(PARTITION BY [j].[LeftId] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[RightId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[SelfSkipSharedLeftId], ROW_NUMBER() OVER(PARTITION BY [e0].[SelfSkipSharedLeftId] ORDER BY [e1].[Id]) AS [row] + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedRightId] = [e1].[Id] ) AS [t] WHERE 2 < [t].[row] -) AS [t0] ON [e].[Id] = [t0].[LeftId] -ORDER BY [e].[Id], [t0].[LeftId], [t0].[Id]"); +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedLeftId] +ORDER BY [e].[Id], [t0].[SelfSkipSharedLeftId], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_take_split(bool async) @@ -1242,15 +1242,15 @@ FROM [EntityCompositeKeys] AS [e] @"SELECT [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Key1], [e].[Key2], [e].[Key3] FROM [EntityCompositeKeys] AS [e] INNER JOIN ( - SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3] + SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[TwoId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], ROW_NUMBER() OVER(PARTITION BY [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] ORDER BY [e1].[Id]) AS [row] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] ) AS [t] WHERE [t].[row] <= 2 -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take_split(bool async) @@ -1290,29 +1290,29 @@ FROM [Roots] AS [r] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] ORDER BY [r].[Id]", // - @"SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [r].[Id], [t].[EntityRootId], [t].[EntityThreeId] + @"SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [r].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId] FROM [Roots] AS [r] INNER JOIN ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [e].[EntityRootId], [e].[EntityThreeId] + SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [e].[RootSkipSharedId], [e].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e] - INNER JOIN [EntityThrees] AS [e0] ON [e].[EntityThreeId] = [e0].[Id] -) AS [t] ON [r].[Id] = [t].[EntityRootId] -ORDER BY [r].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id]", + INNER JOIN [EntityThrees] AS [e0] ON [e].[ThreeSkipSharedId] = [e0].[Id] +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId] +ORDER BY [r].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id]", // - @"SELECT [t0].[Id], [t0].[Name], [r].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id] + @"SELECT [t0].[Id], [t0].[Name], [r].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id] FROM [Roots] AS [r] INNER JOIN ( - SELECT [e0].[Id], [e].[EntityRootId], [e].[EntityThreeId] + SELECT [e0].[Id], [e].[RootSkipSharedId], [e].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e] - INNER JOIN [EntityThrees] AS [e0] ON [e].[EntityThreeId] = [e0].[Id] -) AS [t] ON [r].[Id] = [t].[EntityRootId] + INNER JOIN [EntityThrees] AS [e0] ON [e].[ThreeSkipSharedId] = [e0].[Id] +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId] INNER JOIN ( SELECT [e1].[Id], [e1].[Name], [j].[ThreeId] FROM [JoinOneToThreePayloadFullShared] AS [j] INNER JOIN [EntityOnes] AS [e1] ON [j].[OneId] = [e1].[Id] WHERE [e1].[Id] < 10 ) AS [t0] ON [t].[Id] = [t0].[ThreeId] -ORDER BY [r].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id]"); +ORDER BY [r].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id]"); } public override async Task Filtered_then_include_skip_navigation_order_by_skip_take_split(bool async) @@ -1329,32 +1329,32 @@ FROM [Roots] AS [r] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] ORDER BY [r].[Id]", // - @"SELECT [t].[Key1], [t].[Key2], [t].[Key3], [t].[Name], [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId] + @"SELECT [t].[Key1], [t].[Key2], [t].[Key3], [t].[Name], [r].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3] FROM [Roots] AS [r] INNER JOIN ( - SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) -) AS [t] ON [r].[Id] = [t].[RootId] -ORDER BY [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3]", + SELECT [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [e].[RootSkipSharedId], [e].[CompositeKeySkipSharedKey1], [e].[CompositeKeySkipSharedKey2], [e].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e] + INNER JOIN [EntityCompositeKeys] AS [e0] ON (([e].[CompositeKeySkipSharedKey1] = [e0].[Key1]) AND ([e].[CompositeKeySkipSharedKey2] = [e0].[Key2])) AND ([e].[CompositeKeySkipSharedKey3] = [e0].[Key3]) +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId] +ORDER BY [r].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3]", // - @"SELECT [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3] + @"SELECT [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [r].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3] FROM [Roots] AS [r] INNER JOIN ( - SELECT [e].[Key1], [e].[Key2], [e].[Key3], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) -) AS [t] ON [r].[Id] = [t].[RootId] + SELECT [e0].[Key1], [e0].[Key2], [e0].[Key3], [e].[RootSkipSharedId], [e].[CompositeKeySkipSharedKey1], [e].[CompositeKeySkipSharedKey2], [e].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e] + INNER JOIN [EntityCompositeKeys] AS [e0] ON (([e].[CompositeKeySkipSharedKey1] = [e0].[Key1]) AND ([e].[CompositeKeySkipSharedKey2] = [e0].[Key2])) AND ([e].[CompositeKeySkipSharedKey3] = [e0].[Key3]) +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId] INNER JOIN ( SELECT [t1].[Id], [t1].[CollectionInverseId], [t1].[Name], [t1].[ReferenceInverseId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3] FROM ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e0] ON [j0].[ThreeId] = [e0].[Id] + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e1].[Id]) AS [row] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e1] ON [j].[ThreeId] = [e1].[Id] ) AS [t1] WHERE (1 < [t1].[row]) AND ([t1].[row] <= 3) ) AS [t0] ON (([t].[Key1] = [t0].[CompositeId1]) AND ([t].[Key2] = [t0].[CompositeId2])) AND ([t].[Key3] = [t0].[CompositeId3]) -ORDER BY [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +ORDER BY [r].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_where_then_include_skip_navigation_split(bool async) @@ -1391,10 +1391,10 @@ INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AN WHERE [e].[Key1] < 5 ) AS [t] ON [r].[Id] = [t].[LeafId] INNER JOIN ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] - FROM [JoinTwoToCompositeKeyShared] AS [j0] - INNER JOIN [EntityTwos] AS [e0] ON [j0].[TwoId] = [e0].[Id] -) AS [t0] ON (([t].[Key1] = [t0].[CompositeId1]) AND ([t].[Key2] = [t0].[CompositeId2])) AND ([t].[Key3] = [t0].[CompositeId3]) + SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] +) AS [t0] ON (([t].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([t].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([t].[Key3] = [t0].[CompositeKeySkipSharedKey3]) ORDER BY [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyQuerySqlServerTest.cs index 24420ea6e9f..aa12f125426 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyQuerySqlServerTest.cs @@ -132,9 +132,9 @@ public override async Task Skip_navigation_long_count_with_predicate(bool async) FROM [EntityTwos] AS [e] ORDER BY ( SELECT COUNT_BIG(*) - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[LeftId] = [e0].[Id] - WHERE ([e].[Id] = [j].[RightId]) AND ([e0].[Name] IS NOT NULL AND ([e0].[Name] LIKE N'L%'))) DESC, [e].[Id]"); + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedLeftId] = [e1].[Id] + WHERE ([e].[Id] = [e0].[SelfSkipSharedRightId]) AND ([e1].[Name] IS NOT NULL AND ([e1].[Name] LIKE N'L%'))) DESC, [e].[Id]"); } public override async Task Skip_navigation_select_many_average(bool async) @@ -145,10 +145,10 @@ public override async Task Skip_navigation_select_many_average(bool async) @"SELECT AVG(CAST([t].[Key1] AS float)) FROM [EntityTwos] AS [e] INNER JOIN ( - SELECT [e0].[Key1], [j].[TwoId] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e0] ON (([j].[CompositeId1] = [e0].[Key1]) AND ([j].[CompositeId2] = [e0].[Key2])) AND ([j].[CompositeId3] = [e0].[Key3]) -) AS [t] ON [e].[Id] = [t].[TwoId]"); + SELECT [e1].[Key1], [e0].[TwoSkipSharedId] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityCompositeKeys] AS [e1] ON (([e0].[CompositeKeySkipSharedKey1] = [e1].[Key1]) AND ([e0].[CompositeKeySkipSharedKey2] = [e1].[Key2])) AND ([e0].[CompositeKeySkipSharedKey3] = [e1].[Key3]) +) AS [t] ON [e].[Id] = [t].[TwoSkipSharedId]"); } public override async Task Skip_navigation_select_many_max(bool async) @@ -173,13 +173,13 @@ public override async Task Skip_navigation_select_many_min(bool async) @"SELECT MIN([t0].[Id]) FROM [EntityThrees] AS [e] INNER JOIN ( - SELECT [t].[Id], [e0].[EntityThreeId] + SELECT [t].[Id], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] INNER JOIN ( SELECT [r].[Id] FROM [Roots] AS [r] - ) AS [t] ON [e0].[EntityRootId] = [t].[Id] -) AS [t0] ON [e].[Id] = [t0].[EntityThreeId]"); + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] +) AS [t0] ON [e].[Id] = [t0].[ThreeSkipSharedId]"); } public override async Task Skip_navigation_select_many_sum(bool async) @@ -190,10 +190,10 @@ public override async Task Skip_navigation_select_many_sum(bool async) @"SELECT COALESCE(SUM([t].[Key1]), 0) FROM [Roots] AS [r] INNER JOIN ( - SELECT [e].[Key1], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) -) AS [t] ON [r].[Id] = [t].[RootId]"); + SELECT [e0].[Key1], [e].[RootSkipSharedId] + FROM [EntityCompositeKeyEntityRoot] AS [e] + INNER JOIN [EntityCompositeKeys] AS [e0] ON (([e].[CompositeKeySkipSharedKey1] = [e0].[Key1]) AND ([e].[CompositeKeySkipSharedKey2] = [e0].[Key2])) AND ([e].[CompositeKeySkipSharedKey3] = [e0].[Key3]) +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId]"); } public override async Task Skip_navigation_select_subquery_average(bool async) @@ -350,11 +350,11 @@ public override async Task Skip_navigation_of_type(bool async) await base.Skip_navigation_of_type(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[RootId] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator], [t0].[RootSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId] - FROM [JoinCompositeKeyToRootShared] AS [j] + SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityRoot] AS [e0] INNER JOIN ( SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' @@ -363,10 +363,10 @@ END AS [Discriminator] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] - ) AS [t] ON [j].[RootId] = [t].[Id] + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] WHERE [t].[Discriminator] = N'EntityLeaf' -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[RootId]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[RootSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3]"); } public override async Task Join_with_skip_navigation(bool async) @@ -377,11 +377,11 @@ public override async Task Join_with_skip_navigation(bool async) @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId] FROM [EntityTwos] AS [e] INNER JOIN [EntityTwos] AS [e0] ON [e].[Id] = ( - SELECT TOP(1) [e1].[Id] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e1] ON [j].[RightId] = [e1].[Id] - WHERE [e0].[Id] = [j].[LeftId] - ORDER BY [e1].[Id])"); + SELECT TOP(1) [e2].[Id] + FROM [EntityTwoEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[SelfSkipSharedRightId] = [e2].[Id] + WHERE [e0].[Id] = [e1].[SelfSkipSharedLeftId] + ORDER BY [e2].[Id])"); } public override async Task Left_join_with_skip_navigation(bool async) @@ -392,16 +392,16 @@ public override async Task Left_join_with_skip_navigation(bool async) @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name] FROM [EntityCompositeKeys] AS [e] LEFT JOIN [EntityCompositeKeys] AS [e0] ON ( - SELECT TOP(1) [e1].[Id] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e1] ON [j].[TwoId] = [e1].[Id] - WHERE (([e].[Key1] = [j].[CompositeId1]) AND ([e].[Key2] = [j].[CompositeId2])) AND ([e].[Key3] = [j].[CompositeId3]) - ORDER BY [e1].[Id]) = ( SELECT TOP(1) [e2].[Id] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e2] ON [j0].[ThreeId] = [e2].[Id] - WHERE (([e0].[Key1] = [j0].[CompositeId1]) AND ([e0].[Key2] = [j0].[CompositeId2])) AND ([e0].[Key3] = [j0].[CompositeId3]) - ORDER BY [e2].[Id]) + FROM [EntityCompositeKeyEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[TwoSkipSharedId] = [e2].[Id] + WHERE (([e].[Key1] = [e1].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [e1].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [e1].[CompositeKeySkipSharedKey3]) + ORDER BY [e2].[Id]) = ( + SELECT TOP(1) [e3].[Id] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e3] ON [j].[ThreeId] = [e3].[Id] + WHERE (([e0].[Key1] = [j].[CompositeId1]) AND ([e0].[Key2] = [j].[CompositeId2])) AND ([e0].[Key3] = [j].[CompositeId3]) + ORDER BY [e3].[Id]) ORDER BY [e].[Key1], [e0].[Key1], [e].[Key2], [e0].[Key2]"); } @@ -413,10 +413,10 @@ public override async Task Select_many_over_skip_navigation(bool async) @"SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId] FROM [Roots] AS [r] INNER JOIN ( - SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [e].[EntityRootId] + SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [e].[RootSkipSharedId] FROM [EntityRootEntityThree] AS [e] - INNER JOIN [EntityThrees] AS [e0] ON [e].[EntityThreeId] = [e0].[Id] -) AS [t] ON [r].[Id] = [t].[EntityRootId]"); + INNER JOIN [EntityThrees] AS [e0] ON [e].[ThreeSkipSharedId] = [e0].[Id] +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId]"); } public override async Task Select_many_over_skip_navigation_where(bool async) @@ -495,7 +495,7 @@ public override async Task Select_many_over_skip_navigation_of_type(bool async) @"SELECT [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator] FROM [EntityThrees] AS [e] INNER JOIN ( - SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [e0].[EntityThreeId] + SELECT [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator], [e0].[ThreeSkipSharedId] FROM [EntityRootEntityThree] AS [e0] INNER JOIN ( SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE @@ -505,9 +505,9 @@ END AS [Discriminator] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] - ) AS [t] ON [e0].[EntityRootId] = [t].[Id] + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] WHERE [t].[Discriminator] IN (N'EntityBranch', N'EntityLeaf') -) AS [t0] ON [e].[Id] = [t0].[EntityThreeId]"); +) AS [t0] ON [e].[Id] = [t0].[ThreeSkipSharedId]"); } public override async Task Select_many_over_skip_navigation_cast(bool async) @@ -551,7 +551,7 @@ public override async Task Select_skip_navigation_multiple(bool async) await base.Select_skip_navigation_multiple(async); AssertSql( - @"SELECT [e].[Id], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[ThreeId], [t].[TwoId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[LeftId], [t0].[RightId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[TwoId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3] + @"SELECT [e].[Id], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t].[ThreeId], [t].[TwoId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[TwoSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3] FROM [EntityTwos] AS [e] LEFT JOIN ( SELECT [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [j].[ThreeId], [j].[TwoId] @@ -559,16 +559,16 @@ FROM [JoinTwoToThree] AS [j] INNER JOIN [EntityThrees] AS [e0] ON [j].[ThreeId] = [e0].[Id] ) AS [t] ON [e].[Id] = [t].[TwoId] LEFT JOIN ( - SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [j0].[LeftId], [j0].[RightId] - FROM [JoinTwoSelfShared] AS [j0] - INNER JOIN [EntityTwos] AS [e1] ON [j0].[LeftId] = [e1].[Id] -) AS [t0] ON [e].[Id] = [t0].[RightId] + SELECT [e2].[Id], [e2].[CollectionInverseId], [e2].[ExtraId], [e2].[Name], [e2].[ReferenceInverseId], [e1].[SelfSkipSharedLeftId], [e1].[SelfSkipSharedRightId] + FROM [EntityTwoEntityTwo] AS [e1] + INNER JOIN [EntityTwos] AS [e2] ON [e1].[SelfSkipSharedLeftId] = [e2].[Id] +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedRightId] LEFT JOIN ( - SELECT [e2].[Key1], [e2].[Key2], [e2].[Key3], [e2].[Name], [j1].[TwoId], [j1].[CompositeId1], [j1].[CompositeId2], [j1].[CompositeId3] - FROM [JoinTwoToCompositeKeyShared] AS [j1] - INNER JOIN [EntityCompositeKeys] AS [e2] ON (([j1].[CompositeId1] = [e2].[Key1]) AND ([j1].[CompositeId2] = [e2].[Key2])) AND ([j1].[CompositeId3] = [e2].[Key3]) -) AS [t1] ON [e].[Id] = [t1].[TwoId] -ORDER BY [e].[Id], [t].[ThreeId], [t].[TwoId], [t].[Id], [t0].[LeftId], [t0].[RightId], [t0].[Id], [t1].[TwoId], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[Key1], [t1].[Key2]"); + SELECT [e4].[Key1], [e4].[Key2], [e4].[Key3], [e4].[Name], [e3].[TwoSkipSharedId], [e3].[CompositeKeySkipSharedKey1], [e3].[CompositeKeySkipSharedKey2], [e3].[CompositeKeySkipSharedKey3] + FROM [EntityCompositeKeyEntityTwo] AS [e3] + INNER JOIN [EntityCompositeKeys] AS [e4] ON (([e3].[CompositeKeySkipSharedKey1] = [e4].[Key1]) AND ([e3].[CompositeKeySkipSharedKey2] = [e4].[Key2])) AND ([e3].[CompositeKeySkipSharedKey3] = [e4].[Key3]) +) AS [t1] ON [e].[Id] = [t1].[TwoSkipSharedId] +ORDER BY [e].[Id], [t].[ThreeId], [t].[TwoId], [t].[Id], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t0].[Id], [t1].[TwoSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2]"); } public override async Task Select_skip_navigation_first_or_default(bool async) @@ -595,11 +595,11 @@ public override async Task Include_skip_navigation(bool async) await base.Include_skip_navigation(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[RootId], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[RootSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator] - FROM [JoinCompositeKeyToRootShared] AS [j] + SELECT [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator] + FROM [EntityCompositeKeyEntityRoot] AS [e0] INNER JOIN ( SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' @@ -608,9 +608,9 @@ END AS [Discriminator] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] - ) AS [t] ON [j].[RootId] = [t].[Id] -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[RootId]"); + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[RootSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3]"); } public override async Task Include_skip_navigation_then_reference(bool async) @@ -727,18 +727,18 @@ public override async Task Filtered_include_skip_navigation_order_by_skip(bool a await base.Filtered_include_skip_navigation_order_by_skip(async); AssertSql( - @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [t0].[LeftId], [t0].[RightId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId] + @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId] FROM [EntityTwos] AS [e] LEFT JOIN ( - SELECT [t].[LeftId], [t].[RightId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] + SELECT [t].[SelfSkipSharedLeftId], [t].[SelfSkipSharedRightId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j].[LeftId], [j].[RightId], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[LeftId] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[RightId] = [e0].[Id] + SELECT [e0].[SelfSkipSharedLeftId], [e0].[SelfSkipSharedRightId], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [e0].[SelfSkipSharedLeftId] ORDER BY [e1].[Id]) AS [row] + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedRightId] = [e1].[Id] ) AS [t] WHERE 2 < [t].[row] -) AS [t0] ON [e].[Id] = [t0].[LeftId] -ORDER BY [e].[Id], [t0].[LeftId], [t0].[Id]"); +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedLeftId] +ORDER BY [e].[Id], [t0].[SelfSkipSharedLeftId], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_take(bool async) @@ -746,18 +746,18 @@ public override async Task Filtered_include_skip_navigation_order_by_take(bool a await base.Filtered_include_skip_navigation_order_by_take(async); AssertSql( - @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[TwoId], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId] + @"SELECT [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId] FROM [EntityCompositeKeys] AS [e] LEFT JOIN ( - SELECT [t].[TwoId], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] + SELECT [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j].[TwoId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[TwoId] = [e0].[Id] + SELECT [e0].[TwoSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] ORDER BY [e1].[Id]) AS [row] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] ) AS [t] WHERE [t].[row] <= 2 -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take(bool async) @@ -787,22 +787,22 @@ public override async Task Filtered_then_include_skip_navigation_where(bool asyn @"SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' WHEN [b].[Id] IS NOT NULL THEN N'EntityBranch' -END AS [Discriminator], [t0].[EntityRootId], [t0].[EntityThreeId], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[OneId], [t0].[ThreeId], [t0].[Payload], [t0].[Id0], [t0].[Name0] +END AS [Discriminator], [t0].[RootSkipSharedId], [t0].[ThreeSkipSharedId], [t0].[Id], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [t0].[OneId], [t0].[ThreeId], [t0].[Payload], [t0].[Id0], [t0].[Name0] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] LEFT JOIN ( - SELECT [e].[EntityRootId], [e].[EntityThreeId], [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [t].[OneId], [t].[ThreeId], [t].[Payload], [t].[Id] AS [Id0], [t].[Name] AS [Name0] + SELECT [e].[RootSkipSharedId], [e].[ThreeSkipSharedId], [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [t].[OneId], [t].[ThreeId], [t].[Payload], [t].[Id] AS [Id0], [t].[Name] AS [Name0] FROM [EntityRootEntityThree] AS [e] - INNER JOIN [EntityThrees] AS [e0] ON [e].[EntityThreeId] = [e0].[Id] + INNER JOIN [EntityThrees] AS [e0] ON [e].[ThreeSkipSharedId] = [e0].[Id] LEFT JOIN ( SELECT [j].[OneId], [j].[ThreeId], [j].[Payload], [e1].[Id], [e1].[Name] FROM [JoinOneToThreePayloadFullShared] AS [j] INNER JOIN [EntityOnes] AS [e1] ON [j].[OneId] = [e1].[Id] WHERE [e1].[Id] < 10 ) AS [t] ON [e0].[Id] = [t].[ThreeId] -) AS [t0] ON [r].[Id] = [t0].[EntityRootId] -ORDER BY [r].[Id], [t0].[EntityRootId], [t0].[EntityThreeId], [t0].[Id], [t0].[OneId], [t0].[ThreeId]"); +) AS [t0] ON [r].[Id] = [t0].[RootSkipSharedId] +ORDER BY [r].[Id], [t0].[RootSkipSharedId], [t0].[ThreeSkipSharedId], [t0].[Id], [t0].[OneId], [t0].[ThreeId]"); } public override async Task Filtered_then_include_skip_navigation_order_by_skip_take(bool async) @@ -813,25 +813,25 @@ public override async Task Filtered_then_include_skip_navigation_order_by_skip_t @"SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' WHEN [b].[Id] IS NOT NULL THEN N'EntityBranch' -END AS [Discriminator], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[RootId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[Id], [t1].[CompositeId10], [t1].[CompositeId20], [t1].[CompositeId30], [t1].[ThreeId], [t1].[Id0], [t1].[CollectionInverseId], [t1].[Name0], [t1].[ReferenceInverseId] +END AS [Discriminator], [t1].[RootSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[Name], [t1].[Id], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[ThreeId], [t1].[Id0], [t1].[CollectionInverseId], [t1].[Name0], [t1].[ReferenceInverseId] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] LEFT JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t0].[Id], [t0].[CompositeId1] AS [CompositeId10], [t0].[CompositeId2] AS [CompositeId20], [t0].[CompositeId3] AS [CompositeId30], [t0].[ThreeId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[Name] AS [Name0], [t0].[ReferenceInverseId] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) + SELECT [e].[RootSkipSharedId], [e].[CompositeKeySkipSharedKey1], [e].[CompositeKeySkipSharedKey2], [e].[CompositeKeySkipSharedKey3], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name], [t0].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[ThreeId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[Name] AS [Name0], [t0].[ReferenceInverseId] + FROM [EntityCompositeKeyEntityRoot] AS [e] + INNER JOIN [EntityCompositeKeys] AS [e0] ON (([e].[CompositeKeySkipSharedKey1] = [e0].[Key1]) AND ([e].[CompositeKeySkipSharedKey2] = [e0].[Key2])) AND ([e].[CompositeKeySkipSharedKey3] = [e0].[Key3]) LEFT JOIN ( SELECT [t].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[ThreeId], [t].[Id0], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j0].[Id], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], [j0].[ThreeId], [e0].[Id] AS [Id0], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e0] ON [j0].[ThreeId] = [e0].[Id] + SELECT [j].[Id], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[ThreeId], [e1].[Id] AS [Id0], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e1].[Id]) AS [row] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e1] ON [j].[ThreeId] = [e1].[Id] ) AS [t] WHERE (1 < [t].[row]) AND ([t].[row] <= 3) - ) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -) AS [t1] ON [r].[Id] = [t1].[RootId] -ORDER BY [r].[Id], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[RootId], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[CompositeId10], [t1].[CompositeId20], [t1].[CompositeId30], [t1].[Id0]"); + ) AS [t0] ON (([e0].[Key1] = [t0].[CompositeId1]) AND ([e0].[Key2] = [t0].[CompositeId2])) AND ([e0].[Key3] = [t0].[CompositeId3]) +) AS [t1] ON [r].[Id] = [t1].[RootSkipSharedId] +ORDER BY [r].[Id], [t1].[RootSkipSharedId], [t1].[CompositeKeySkipSharedKey1], [t1].[CompositeKeySkipSharedKey2], [t1].[CompositeKeySkipSharedKey3], [t1].[Key1], [t1].[Key2], [t1].[Key3], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[Id0]"); } public override async Task Filtered_include_skip_navigation_where_then_include_skip_navigation(bool async) @@ -839,22 +839,23 @@ public override async Task Filtered_include_skip_navigation_where_then_include_s await base.Filtered_include_skip_navigation_where_then_include_skip_navigation(async); AssertSql( - @"SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[Name], [t0].[TwoId], [t0].[CompositeId10], [t0].[CompositeId20], [t0].[CompositeId30], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId] + @"SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[Name], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId] FROM [Roots] AS [r] INNER JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] INNER JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] LEFT JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[LeafId], [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t].[TwoId], [t].[CompositeId1] AS [CompositeId10], [t].[CompositeId2] AS [CompositeId20], [t].[CompositeId3] AS [CompositeId30], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name] AS [Name0], [t].[ReferenceInverseId] + SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[LeafId], [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name], [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name] AS [Name0], [t].[ReferenceInverseId] FROM [JoinCompositeKeyToLeaf] AS [j] INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) LEFT JOIN ( - SELECT [j0].[TwoId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId] - FROM [JoinTwoToCompositeKeyShared] AS [j0] - INNER JOIN [EntityTwos] AS [e0] ON [j0].[TwoId] = [e0].[Id] - ) AS [t] ON (([e].[Key1] = [t].[CompositeId1]) AND ([e].[Key2] = [t].[CompositeId2])) AND ([e].[Key3] = [t].[CompositeId3]) + SELECT [e0].[TwoSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] + ) AS [t] ON (([e].[Key1] = [t].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t].[CompositeKeySkipSharedKey3]) WHERE [e].[Key1] < 5 ) AS [t0] ON [r].[Id] = [t0].[LeafId] -ORDER BY [r].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[TwoId], [t0].[CompositeId10], [t0].[CompositeId20], [t0].[CompositeId30]"); +ORDER BY [r].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[LeafId], [t0].[Key1], [t0].[Key2], [t0].[Key3], [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3]"); + } public override async Task Filtered_include_skip_navigation_order_by_skip_take_then_include_skip_navigation_where(bool async) @@ -1030,11 +1031,11 @@ public override async Task Include_skip_navigation_split(bool async) FROM [EntityCompositeKeys] AS [e] ORDER BY [e].[Key1], [e].[Key2], [e].[Key3]", // - @"SELECT [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[RootId], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator], [e].[Key1], [e].[Key2], [e].[Key3] + @"SELECT [t0].[RootSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[Name], [t0].[Number], [t0].[IsGreen], [t0].[Discriminator], [e].[Key1], [e].[Key2], [e].[Key3] FROM [EntityCompositeKeys] AS [e] INNER JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator] - FROM [JoinCompositeKeyToRootShared] AS [j] + SELECT [e0].[RootSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [t].[Id], [t].[Name], [t].[Number], [t].[IsGreen], [t].[Discriminator] + FROM [EntityCompositeKeyEntityRoot] AS [e0] INNER JOIN ( SELECT [r].[Id], [r].[Name], [b].[Number], [l].[IsGreen], CASE WHEN [l].[Id] IS NOT NULL THEN N'EntityLeaf' @@ -1043,8 +1044,8 @@ END AS [Discriminator] FROM [Roots] AS [r] LEFT JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] - ) AS [t] ON [j].[RootId] = [t].[Id] -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) + ) AS [t] ON [e0].[RootSkipSharedId] = [t].[Id] +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) ORDER BY [e].[Key1], [e].[Key2], [e].[Key3]"); } @@ -1215,18 +1216,18 @@ public override async Task Filtered_include_skip_navigation_order_by_skip_split( FROM [EntityTwos] AS [e] ORDER BY [e].[Id]", // - @"SELECT [t0].[LeftId], [t0].[RightId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id] + @"SELECT [t0].[SelfSkipSharedLeftId], [t0].[SelfSkipSharedRightId], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Id] FROM [EntityTwos] AS [e] INNER JOIN ( - SELECT [t].[LeftId], [t].[RightId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] + SELECT [t].[SelfSkipSharedLeftId], [t].[SelfSkipSharedRightId], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j].[LeftId], [j].[RightId], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[LeftId] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoSelfShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[RightId] = [e0].[Id] + SELECT [e0].[SelfSkipSharedLeftId], [e0].[SelfSkipSharedRightId], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [e0].[SelfSkipSharedLeftId] ORDER BY [e1].[Id]) AS [row] + FROM [EntityTwoEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[SelfSkipSharedRightId] = [e1].[Id] ) AS [t] WHERE 2 < [t].[row] -) AS [t0] ON [e].[Id] = [t0].[LeftId] -ORDER BY [e].[Id], [t0].[LeftId], [t0].[Id]"); +) AS [t0] ON [e].[Id] = [t0].[SelfSkipSharedLeftId] +ORDER BY [e].[Id], [t0].[SelfSkipSharedLeftId], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_take_split(bool async) @@ -1238,18 +1239,18 @@ public override async Task Filtered_include_skip_navigation_order_by_take_split( FROM [EntityCompositeKeys] AS [e] ORDER BY [e].[Key1], [e].[Key2], [e].[Key3]", // - @"SELECT [t0].[TwoId], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Key1], [e].[Key2], [e].[Key3] + @"SELECT [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [e].[Key1], [e].[Key2], [e].[Key3] FROM [EntityCompositeKeys] AS [e] INNER JOIN ( - SELECT [t].[TwoId], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] + SELECT [t].[TwoSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId] FROM ( - SELECT [j].[TwoId], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinTwoToCompositeKeyShared] AS [j] - INNER JOIN [EntityTwos] AS [e0] ON [j].[TwoId] = [e0].[Id] + SELECT [e0].[TwoSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3] ORDER BY [e1].[Id]) AS [row] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] ) AS [t] WHERE [t].[row] <= 2 -) AS [t0] ON (([e].[Key1] = [t0].[CompositeId1]) AND ([e].[Key2] = [t0].[CompositeId2])) AND ([e].[Key3] = [t0].[CompositeId3]) -ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id]"); +) AS [t0] ON (([e].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([e].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([e].[Key3] = [t0].[CompositeKeySkipSharedKey3]) +ORDER BY [e].[Key1], [e].[Key2], [e].[Key3], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id]"); } public override async Task Filtered_include_skip_navigation_order_by_skip_take_split(bool async) @@ -1289,29 +1290,29 @@ FROM [Roots] AS [r] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] ORDER BY [r].[Id]", // - @"SELECT [t].[EntityRootId], [t].[EntityThreeId], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [r].[Id] + @"SELECT [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [r].[Id] FROM [Roots] AS [r] INNER JOIN ( - SELECT [e].[EntityRootId], [e].[EntityThreeId], [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId] + SELECT [e].[RootSkipSharedId], [e].[ThreeSkipSharedId], [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId] FROM [EntityRootEntityThree] AS [e] - INNER JOIN [EntityThrees] AS [e0] ON [e].[EntityThreeId] = [e0].[Id] -) AS [t] ON [r].[Id] = [t].[EntityRootId] -ORDER BY [r].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id]", + INNER JOIN [EntityThrees] AS [e0] ON [e].[ThreeSkipSharedId] = [e0].[Id] +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId] +ORDER BY [r].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id]", // - @"SELECT [t0].[OneId], [t0].[ThreeId], [t0].[Payload], [t0].[Id], [t0].[Name], [r].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id] + @"SELECT [t0].[OneId], [t0].[ThreeId], [t0].[Payload], [t0].[Id], [t0].[Name], [r].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id] FROM [Roots] AS [r] INNER JOIN ( - SELECT [e].[EntityRootId], [e].[EntityThreeId], [e0].[Id] + SELECT [e].[RootSkipSharedId], [e].[ThreeSkipSharedId], [e0].[Id] FROM [EntityRootEntityThree] AS [e] - INNER JOIN [EntityThrees] AS [e0] ON [e].[EntityThreeId] = [e0].[Id] -) AS [t] ON [r].[Id] = [t].[EntityRootId] + INNER JOIN [EntityThrees] AS [e0] ON [e].[ThreeSkipSharedId] = [e0].[Id] +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId] INNER JOIN ( SELECT [j].[OneId], [j].[ThreeId], [j].[Payload], [e1].[Id], [e1].[Name] FROM [JoinOneToThreePayloadFullShared] AS [j] INNER JOIN [EntityOnes] AS [e1] ON [j].[OneId] = [e1].[Id] WHERE [e1].[Id] < 10 ) AS [t0] ON [t].[Id] = [t0].[ThreeId] -ORDER BY [r].[Id], [t].[EntityRootId], [t].[EntityThreeId], [t].[Id]"); +ORDER BY [r].[Id], [t].[RootSkipSharedId], [t].[ThreeSkipSharedId], [t].[Id]"); } public override async Task Filtered_then_include_skip_navigation_order_by_skip_take_split(bool async) @@ -1328,32 +1329,32 @@ FROM [Roots] AS [r] LEFT JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] ORDER BY [r].[Id]", // - @"SELECT [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3], [t].[Name], [r].[Id] + @"SELECT [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3], [t].[Name], [r].[Id] FROM [Roots] AS [r] INNER JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [e].[Key1], [e].[Key2], [e].[Key3], [e].[Name] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) -) AS [t] ON [r].[Id] = [t].[RootId] -ORDER BY [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3]", + SELECT [e].[RootSkipSharedId], [e].[CompositeKeySkipSharedKey1], [e].[CompositeKeySkipSharedKey2], [e].[CompositeKeySkipSharedKey3], [e0].[Key1], [e0].[Key2], [e0].[Key3], [e0].[Name] + FROM [EntityCompositeKeyEntityRoot] AS [e] + INNER JOIN [EntityCompositeKeys] AS [e0] ON (([e].[CompositeKeySkipSharedKey1] = [e0].[Key1]) AND ([e].[CompositeKeySkipSharedKey2] = [e0].[Key2])) AND ([e].[CompositeKeySkipSharedKey3] = [e0].[Key3]) +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId] +ORDER BY [r].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3]", // - @"SELECT [t0].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[ThreeId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3] + @"SELECT [t0].[Id], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[ThreeId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[Name], [t0].[ReferenceInverseId], [r].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3] FROM [Roots] AS [r] INNER JOIN ( - SELECT [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[RootId], [e].[Key1], [e].[Key2], [e].[Key3] - FROM [JoinCompositeKeyToRootShared] AS [j] - INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AND ([j].[CompositeId2] = [e].[Key2])) AND ([j].[CompositeId3] = [e].[Key3]) -) AS [t] ON [r].[Id] = [t].[RootId] + SELECT [e].[RootSkipSharedId], [e].[CompositeKeySkipSharedKey1], [e].[CompositeKeySkipSharedKey2], [e].[CompositeKeySkipSharedKey3], [e0].[Key1], [e0].[Key2], [e0].[Key3] + FROM [EntityCompositeKeyEntityRoot] AS [e] + INNER JOIN [EntityCompositeKeys] AS [e0] ON (([e].[CompositeKeySkipSharedKey1] = [e0].[Key1]) AND ([e].[CompositeKeySkipSharedKey2] = [e0].[Key2])) AND ([e].[CompositeKeySkipSharedKey3] = [e0].[Key3]) +) AS [t] ON [r].[Id] = [t].[RootSkipSharedId] INNER JOIN ( SELECT [t1].[Id], [t1].[CompositeId1], [t1].[CompositeId2], [t1].[CompositeId3], [t1].[ThreeId], [t1].[Id0], [t1].[CollectionInverseId], [t1].[Name], [t1].[ReferenceInverseId] FROM ( - SELECT [j0].[Id], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], [j0].[ThreeId], [e0].[Id] AS [Id0], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3] ORDER BY [e0].[Id]) AS [row] - FROM [JoinThreeToCompositeKeyFull] AS [j0] - INNER JOIN [EntityThrees] AS [e0] ON [j0].[ThreeId] = [e0].[Id] + SELECT [j].[Id], [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3], [j].[ThreeId], [e1].[Id] AS [Id0], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], ROW_NUMBER() OVER(PARTITION BY [j].[CompositeId1], [j].[CompositeId2], [j].[CompositeId3] ORDER BY [e1].[Id]) AS [row] + FROM [JoinThreeToCompositeKeyFull] AS [j] + INNER JOIN [EntityThrees] AS [e1] ON [j].[ThreeId] = [e1].[Id] ) AS [t1] WHERE (1 < [t1].[row]) AND ([t1].[row] <= 3) ) AS [t0] ON (([t].[Key1] = [t0].[CompositeId1]) AND ([t].[Key2] = [t0].[CompositeId2])) AND ([t].[Key3] = [t0].[CompositeId3]) -ORDER BY [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[RootId], [t].[Key1], [t].[Key2], [t].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id0]"); +ORDER BY [r].[Id], [t].[RootSkipSharedId], [t].[CompositeKeySkipSharedKey1], [t].[CompositeKeySkipSharedKey2], [t].[CompositeKeySkipSharedKey3], [t].[Key1], [t].[Key2], [t].[Key3], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id0]"); } public override async Task Filtered_include_skip_navigation_where_then_include_skip_navigation_split(bool async) @@ -1379,7 +1380,7 @@ WHERE [e].[Key1] < 5 ) AS [t] ON [r].[Id] = [t].[LeafId] ORDER BY [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3]", // - @"SELECT [t0].[TwoId], [t0].[CompositeId1], [t0].[CompositeId2], [t0].[CompositeId3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3] + @"SELECT [t0].[TwoSkipSharedId], [t0].[CompositeKeySkipSharedKey1], [t0].[CompositeKeySkipSharedKey2], [t0].[CompositeKeySkipSharedKey3], [t0].[Id], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name], [t0].[ReferenceInverseId], [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3] FROM [Roots] AS [r] INNER JOIN [Branches] AS [b] ON [r].[Id] = [b].[Id] INNER JOIN [Leaves] AS [l] ON [r].[Id] = [l].[Id] @@ -1390,10 +1391,10 @@ INNER JOIN [EntityCompositeKeys] AS [e] ON (([j].[CompositeId1] = [e].[Key1]) AN WHERE [e].[Key1] < 5 ) AS [t] ON [r].[Id] = [t].[LeafId] INNER JOIN ( - SELECT [j0].[TwoId], [j0].[CompositeId1], [j0].[CompositeId2], [j0].[CompositeId3], [e0].[Id], [e0].[CollectionInverseId], [e0].[ExtraId], [e0].[Name], [e0].[ReferenceInverseId] - FROM [JoinTwoToCompositeKeyShared] AS [j0] - INNER JOIN [EntityTwos] AS [e0] ON [j0].[TwoId] = [e0].[Id] -) AS [t0] ON (([t].[Key1] = [t0].[CompositeId1]) AND ([t].[Key2] = [t0].[CompositeId2])) AND ([t].[Key3] = [t0].[CompositeId3]) + SELECT [e0].[TwoSkipSharedId], [e0].[CompositeKeySkipSharedKey1], [e0].[CompositeKeySkipSharedKey2], [e0].[CompositeKeySkipSharedKey3], [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId] + FROM [EntityCompositeKeyEntityTwo] AS [e0] + INNER JOIN [EntityTwos] AS [e1] ON [e0].[TwoSkipSharedId] = [e1].[Id] +) AS [t0] ON (([t].[Key1] = [t0].[CompositeKeySkipSharedKey1]) AND ([t].[Key2] = [t0].[CompositeKeySkipSharedKey2])) AND ([t].[Key3] = [t0].[CompositeKeySkipSharedKey3]) ORDER BY [r].[Id], [t].[CompositeId1], [t].[CompositeId2], [t].[CompositeId3], [t].[LeafId], [t].[Key1], [t].[Key2], [t].[Key3]"); } diff --git a/test/EFCore.Tests/ChangeTracking/ChangeTrackerTest.cs b/test/EFCore.Tests/ChangeTracking/ChangeTrackerTest.cs index 0d4b7b87658..3582079735d 100644 --- a/test/EFCore.Tests/ChangeTracking/ChangeTrackerTest.cs +++ b/test/EFCore.Tests/ChangeTracking/ChangeTrackerTest.cs @@ -49,6 +49,8 @@ public void Can_Add_with_identifying_relationships_dependent_first(int principal var added4 = context.Add(new DependentGN { Id = dependentKeyValue, PrincipalGN = new PrincipalGN { Id = principalKeyValue} }).Entity; Assert.Equal(EntityState.Added, context.Entry(added4).State); Assert.Equal(EntityState.Added, context.Entry(added4.PrincipalGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalTheory] @@ -75,6 +77,8 @@ public void Can_Add_with_identifying_relationships_principal_first(int principal var added4 = context.Add(new PrincipalGN { Id = principalKeyValue, DependentGN = new DependentGN { Id = dependentKeyValue} }).Entity; Assert.Equal(EntityState.Added, context.Entry(added4).State); Assert.Equal(EntityState.Added, context.Entry(added4.DependentGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalFact] @@ -97,6 +101,8 @@ public void Can_Attach_with_identifying_relationships_dependent_first() var added4 = context.Attach(new DependentGN { PrincipalGN = new PrincipalGN() }).Entity; Assert.Equal(EntityState.Added, context.Entry(added4).State); Assert.Equal(EntityState.Added, context.Entry(added4.PrincipalGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalFact] @@ -119,6 +125,8 @@ public void Can_Attach_with_identifying_relationships_dependent_first_with_princ var added4 = context.Attach(new DependentGN { PrincipalGN = new PrincipalGN { Id = 1 } }).Entity; Assert.Equal(EntityState.Added, context.Entry(added4).State); Assert.Equal(EntityState.Unchanged, context.Entry(added4.PrincipalGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalFact] @@ -141,6 +149,8 @@ public void Can_Attach_with_identifying_relationships_dependent_first_with_depen var added4 = context.Attach(new DependentGN { Id = 1, PrincipalGN = new PrincipalGN() }).Entity; Assert.Equal(EntityState.Unchanged, context.Entry(added4).State); Assert.Equal(EntityState.Added, context.Entry(added4.PrincipalGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalFact] @@ -163,6 +173,8 @@ public void Can_Attach_with_identifying_relationships_dependent_first_with_all_k var added4 = context.Attach(new DependentGN { Id = 1, PrincipalGN = new PrincipalGN { Id = 1 } }).Entity; Assert.Equal(EntityState.Unchanged, context.Entry(added4).State); Assert.Equal(EntityState.Unchanged, context.Entry(added4.PrincipalGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalFact] @@ -185,6 +197,8 @@ public void Can_Attach_with_identifying_relationships_principal_first() var added4 = context.Attach(new PrincipalGN { DependentGN = new DependentGN() }).Entity; Assert.Equal(EntityState.Added, context.Entry(added4).State); Assert.Equal(EntityState.Added, context.Entry(added4.DependentGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalFact] @@ -207,6 +221,8 @@ public void Can_Attach_with_identifying_relationships_principal_first_with_princ var added4 = context.Attach(new PrincipalGN { Id = 1, DependentGN = new DependentGN() }).Entity; Assert.Equal(EntityState.Unchanged, context.Entry(added4).State); Assert.Equal(EntityState.Added, context.Entry(added4.DependentGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalFact] @@ -229,6 +245,8 @@ public void Can_Attach_with_identifying_relationships_principal_first_with_depen var added4 = context.Attach(new PrincipalGN { DependentGN = new DependentGN { Id = 1 } }).Entity; Assert.Equal(EntityState.Added, context.Entry(added4).State); Assert.Equal(EntityState.Unchanged, context.Entry(added4.DependentGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalFact] @@ -251,6 +269,8 @@ public void Can_Attach_with_identifying_relationships_principal_first_with_all_k var added4 = context.Attach(new PrincipalGN { Id = 1, DependentGN = new DependentGN { Id = 1 } }).Entity; Assert.Equal(EntityState.Unchanged, context.Entry(added4).State); Assert.Equal(EntityState.Unchanged, context.Entry(added4.DependentGN).State); + + Assert.Equal(8, context.ChangeTracker.Entries().Count()); } [ConditionalFact] diff --git a/test/EFCore.Tests/ChangeTracking/Internal/OwnedFixupTest.cs b/test/EFCore.Tests/ChangeTracking/Internal/OwnedFixupTest.cs index 413ba95436f..ebde491af80 100644 --- a/test/EFCore.Tests/ChangeTracking/Internal/OwnedFixupTest.cs +++ b/test/EFCore.Tests/ChangeTracking/Internal/OwnedFixupTest.cs @@ -927,7 +927,7 @@ public void Instance_changed_unidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(3, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 3 : 5, context.ChangeTracker.Entries().Count()); Assert.Null(principal.Child1); Assert.Same(dependent2, principal.Child2); Assert.Equal(entityState, context.Entry(principal).State); @@ -958,7 +958,7 @@ public void Instance_changed_unidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(3, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 3 : 5, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); @@ -1001,7 +1001,7 @@ public void Instance_changed_bidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(3, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 3 : 5, context.ChangeTracker.Entries().Count()); Assert.Null(principal.Child2); Assert.Same(principal, dependent2.Parent); Assert.Same(dependent2, principal.Child1); @@ -1034,7 +1034,7 @@ public void Instance_changed_bidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(3, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 3 : 5, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); @@ -1112,7 +1112,7 @@ public void Instance_changed_unidirectional_collection(EntityState entityState, Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(3, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 3 : 5, context.ChangeTracker.Entries().Count()); Assert.Null(principal.ChildCollection1); Assert.Contains(principal.ChildCollection2, e => ReferenceEquals(e, dependent2)); Assert.Equal(entityState, context.Entry(principal).State); @@ -1141,7 +1141,7 @@ public void Instance_changed_unidirectional_collection(EntityState entityState, Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(3, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 3 : 5, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); @@ -1219,7 +1219,7 @@ public void Instance_changed_bidirectional_collection(EntityState entityState, C Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(3, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 3 : 5, context.ChangeTracker.Entries().Count()); Assert.Null(principal.ChildCollection2); Assert.Same(principal, dependent2.Parent); Assert.Contains(principal.ChildCollection1, e => ReferenceEquals(e, dependent2)); @@ -1250,7 +1250,7 @@ public void Instance_changed_bidirectional_collection(EntityState entityState, C Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(3, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 3 : 5, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); @@ -1647,7 +1647,7 @@ public void Identity_swapped_unidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(5, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 5 : 9, context.ChangeTracker.Entries().Count()); Assert.Same(dependent1, principal.Child2); Assert.Same(dependent2, principal.Child1); Assert.Equal(entityState, context.Entry(principal).State); @@ -1706,7 +1706,7 @@ public void Identity_swapped_unidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(5, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 5 : 9, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); @@ -1754,7 +1754,7 @@ public void Identity_swapped_bidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(5, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 5 : 9, context.ChangeTracker.Entries().Count()); Assert.Same(principal, dependent1.Parent); Assert.Same(dependent1, principal.Child2); Assert.Same(principal, dependent2.Parent); @@ -1817,7 +1817,7 @@ public void Identity_swapped_bidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(5, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 5 : 9, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); @@ -1914,7 +1914,7 @@ public void Identity_swapped_unidirectional_collection(EntityState entityState, Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(5, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 5 : 9, context.ChangeTracker.Entries().Count()); Assert.Contains(principal.ChildCollection2, e => ReferenceEquals(e, dependent1)); Assert.Contains(principal.ChildCollection1, e => ReferenceEquals(e, dependent2)); Assert.Equal(entityState, context.Entry(principal).State); @@ -1969,7 +1969,7 @@ public void Identity_swapped_unidirectional_collection(EntityState entityState, Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(5, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 5 : 9, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); @@ -2065,7 +2065,7 @@ public void Identity_swapped_bidirectional_collection(EntityState entityState, C Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(5, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 5 : 9, context.ChangeTracker.Entries().Count()); Assert.Same(principal, dependent1.Parent); Assert.Contains(principal.ChildCollection2, e => ReferenceEquals(e, dependent1)); Assert.Same(principal, dependent2.Parent); @@ -2124,7 +2124,7 @@ public void Identity_swapped_bidirectional_collection(EntityState entityState, C Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(5, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 5 : 9, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); @@ -3569,7 +3569,7 @@ public void Parent_and_identity_swapped_unidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(6, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 6 : 10, context.ChangeTracker.Entries().Count()); Assert.Null(principal1.Child1); Assert.Same(dependent2, principal1.Child2); Assert.Same(dependent1, principal2.Child1); @@ -3631,7 +3631,7 @@ public void Parent_and_identity_swapped_unidirectional(EntityState entityState) Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(6, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 6 : 10, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); @@ -3863,7 +3863,7 @@ public void Parent_and_identity_swapped_unidirectional_collection(EntityState en context.ChangeTracker.DetectChanges(); - Assert.Equal(6, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 6 : 10, context.ChangeTracker.Entries().Count()); Assert.Null(principal1.ChildCollection1); Assert.Contains(principal1.ChildCollection2, e => ReferenceEquals(e, dependent2)); Assert.Contains(principal2.ChildCollection1, e => ReferenceEquals(e, dependent1)); @@ -3923,7 +3923,7 @@ public void Parent_and_identity_swapped_unidirectional_collection(EntityState en Assert.True(context.ChangeTracker.HasChanges()); - Assert.Equal(6, context.ChangeTracker.Entries().Count()); + Assert.Equal(entityState == EntityState.Added ? 6 : 10, context.ChangeTracker.Entries().Count()); context.ChangeTracker.AcceptAllChanges(); diff --git a/test/EFCore.Tests/TestUtilities/FakeStateManager.cs b/test/EFCore.Tests/TestUtilities/FakeStateManager.cs index 066289f09b2..e627633e18e 100644 --- a/test/EFCore.Tests/TestUtilities/FakeStateManager.cs +++ b/test/EFCore.Tests/TestUtilities/FakeStateManager.cs @@ -53,14 +53,16 @@ public IEnumerable GetEntriesForState( bool added = false, bool modified = false, bool deleted = false, - bool unchanged = false) + bool unchanged = false, + bool returnSharedIdentity = false) => throw new NotImplementedException(); public int GetCountForState( bool added = false, bool modified = false, bool deleted = false, - bool unchanged = false) + bool unchanged = false, + bool countSharedIdentity = false) => throw new NotImplementedException(); public int ChangedCount { get; set; } From eb0e6d856b02c6e8a88bd1a5cc9c9eb5b0d50e40 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 15 Sep 2021 03:09:24 +0000 Subject: [PATCH 119/346] [release/6.0] Update dependencies from dotnet/runtime (#26003) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 8dd64dd47bd..7d9bd40afe0 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d - + https://github.com/dotnet/runtime - 71fe9fb8ecc11197ad8e7bee0a6c4317a667327c + b3a9b0b740cce9322b03200db0b4ab736d7cd12d diff --git a/eng/Versions.props b/eng/Versions.props index 58bcda78739..1b0b6289d34 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 - 6.0.0-rc.2.21461.1 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 + 6.0.0-rc.2.21464.21 3.7.0 From 2a3a4c3608c49ce1a0530faa15cb2b93972d26a9 Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Wed, 15 Sep 2021 03:46:42 +0000 Subject: [PATCH 120/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions --- NuGet.config | 5 +- eng/Version.Details.xml | 142 ++++++++++++++++++++-------------------- eng/Versions.props | 2 +- 3 files changed, 75 insertions(+), 74 deletions(-) diff --git a/NuGet.config b/NuGet.config index c381bb3b1a2..e005c35cf17 100644 --- a/NuGet.config +++ b/NuGet.config @@ -7,7 +7,7 @@ - + @@ -22,7 +22,7 @@ - + @@ -30,6 +30,7 @@ + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a4e4a7dbffc..b9a55b74714 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 @@ -124,143 +124,143 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - c3b46f7460c9e94ef7760dc2d1d491ce458e6bb9 + 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup diff --git a/eng/Versions.props b/eng/Versions.props index d0fef5e758b..85b3cd5c368 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 3.1.20 3.1.20 3.1.20 - 3.1.20-servicing.21459.11 + 3.1.20-servicing.21464.2 3.1.20 From 5d7ca16a1a6f85834a6bb44afb5979c1ea0ff47e Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 15 Sep 2021 08:38:19 +0100 Subject: [PATCH 121/346] Allow UseTransaction to replace existing transaction (#25979) * Allow UseTransaction to replace existing transaction Fixes #25946 * Don't dispose current transaction when replaced with new one. --- .../Storage/RelationalConnection.cs | 13 +- .../TransactionTestBase.cs | 44 +++-- .../ExecutionStrategyTest.cs | 172 ++++++++++++++++++ 3 files changed, 216 insertions(+), 13 deletions(-) diff --git a/src/EFCore.Relational/Storage/RelationalConnection.cs b/src/EFCore.Relational/Storage/RelationalConnection.cs index 90ed38a1fd9..d40d2f534b2 100644 --- a/src/EFCore.Relational/Storage/RelationalConnection.cs +++ b/src/EFCore.Relational/Storage/RelationalConnection.cs @@ -429,6 +429,11 @@ private void EnsureNoTransactions() throw new InvalidOperationException(RelationalStrings.TransactionAlreadyStarted); } + EnsureNoAmbientOrEnlistedTransactions(); + } + + private void EnsureNoAmbientOrEnlistedTransactions() + { if (CurrentAmbientTransaction != null) { throw new InvalidOperationException(RelationalStrings.ConflictingAmbientTransaction); @@ -540,7 +545,13 @@ private bool ShouldUseTransaction([NotNullWhen(true)] DbTransaction? transaction return false; } - EnsureNoTransactions(); + EnsureNoAmbientOrEnlistedTransactions(); + + if (CurrentTransaction != null + && transaction == CurrentTransaction.GetDbTransaction()) + { + return false; + } return true; } diff --git a/test/EFCore.Relational.Specification.Tests/TransactionTestBase.cs b/test/EFCore.Relational.Specification.Tests/TransactionTestBase.cs index e1c43e6f11e..c66ade4fdfc 100644 --- a/test/EFCore.Relational.Specification.Tests/TransactionTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/TransactionTestBase.cs @@ -935,21 +935,41 @@ public virtual void UseTransaction_throws_if_mismatched_connection() Assert.Equal(RelationalStrings.TransactionAssociatedWithDifferentConnection, ex.Message); } - [ConditionalFact] - public virtual void UseTransaction_throws_if_another_transaction_started() + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task UseTransaction_is_no_op_if_same_DbTransaction_is_used(bool async) { - using var transaction = TestStore.BeginTransaction(); - using var context = CreateContextWithConnectionString(); - using (context.Database.BeginTransaction( - DirtyReadsOccur - ? IsolationLevel.ReadUncommitted - : IsolationLevel.Unspecified)) + using (var transaction = TestStore.BeginTransaction()) { - var ex = Assert.Throws( - () => - context.Database.UseTransaction(transaction)); - Assert.Equal(RelationalStrings.TransactionAlreadyStarted, ex.Message); + using var context = CreateContext(); + + var currentTransaction = async + ? await context.Database.UseTransactionAsync(transaction) + : context.Database.UseTransaction(transaction); + + Assert.Same(transaction, currentTransaction!.GetDbTransaction()); + + var newTransaction = async + ? await context.Database.UseTransactionAsync(transaction) + : context.Database.UseTransaction(transaction); + + Assert.Same(currentTransaction, newTransaction); + Assert.Same(transaction, newTransaction!.GetDbTransaction()); + + context.Entry(context.Set().OrderBy(c => c.Id).First()).State = EntityState.Deleted; + + if (async) + { + await context.SaveChangesAsync(); + } + else + { + context.SaveChanges(); + } } + + AssertStoreInitialState(); } [ConditionalFact] diff --git a/test/EFCore.SqlServer.FunctionalTests/ExecutionStrategyTest.cs b/test/EFCore.SqlServer.FunctionalTests/ExecutionStrategyTest.cs index 72f3ec9c8cf..89b8ccaa7e7 100644 --- a/test/EFCore.SqlServer.FunctionalTests/ExecutionStrategyTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/ExecutionStrategyTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Data; using System.Linq; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -381,6 +382,163 @@ public async Task Retries_SaveChanges_on_execution_failure( } } + [ConditionalTheory] // Issue #25946 + [MemberData(nameof(DataGenerator.GetBoolCombinations), 3, MemberType = typeof(DataGenerator))] + public async Task Retries_SaveChanges_on_execution_failure_with_two_contexts( + bool realFailure, + bool openConnection, + bool async) + { + CleanContext(); + + using (var context = CreateContext()) + { + using var auditContext = new AuditContext(); + + var connection = (TestSqlServerConnection)context.GetService(); + + connection.ExecutionFailures.Enqueue(new bool?[] { null, realFailure }); + + Assert.Equal(ConnectionState.Closed, context.Database.GetDbConnection().State); + + if (openConnection) + { + if (async) + { + await context.Database.OpenConnectionAsync(); + } + else + { + context.Database.OpenConnection(); + } + + Assert.Equal(ConnectionState.Open, context.Database.GetDbConnection().State); + } + + context.Products.Add(new Product()); + context.Products.Add(new Product()); + + var throwTransientError = true; + + if (async) + { + await new TestSqlServerRetryingExecutionStrategy(context).ExecuteInTransactionAsync( + (MainContext: context, AuditContext: auditContext), + async (c, ct) => + { + var result = await c.MainContext.SaveChangesAsync(false, ct); + + c.AuditContext.ChangeTracker.Clear(); + c.AuditContext.Database.SetDbConnection(c.MainContext.Database.GetDbConnection()); + + var currentTransaction = c.AuditContext.Database.CurrentTransaction; + if (throwTransientError) + { + Assert.Null(currentTransaction); + } + else + { + Assert.NotNull(currentTransaction); + } + + await c.AuditContext.Database.UseTransactionAsync( + c.MainContext.Database.CurrentTransaction!.GetDbTransaction(), ct); + + Assert.NotSame(currentTransaction, c.AuditContext.Database.CurrentTransaction); + + await c.AuditContext.Audits.AddAsync(new Audit(), ct); + await c.AuditContext.SaveChangesAsync(ct); + + if (throwTransientError) + { + throwTransientError = false; + throw SqlExceptionFactory.CreateSqlException(10928); + } + + return result; + }, + (c, _) => + { + Assert.True(false); + return Task.FromResult(false); + }); + + context.ChangeTracker.AcceptAllChanges(); + } + else + { + new TestSqlServerRetryingExecutionStrategy(context).ExecuteInTransaction( + (MainContext: context, AuditContext: auditContext), + c => + { + var result = c.MainContext.SaveChanges(false); + + c.AuditContext.ChangeTracker.Clear(); + c.AuditContext.Database.SetDbConnection(c.MainContext.Database.GetDbConnection()); + + var currentTransaction = c.AuditContext.Database.CurrentTransaction; + if (throwTransientError) + { + Assert.Null(currentTransaction); + } + else + { + Assert.NotNull(currentTransaction); + } + + c.AuditContext.Database.UseTransaction(c.MainContext.Database.CurrentTransaction!.GetDbTransaction()); + + Assert.NotSame(currentTransaction, c.AuditContext.Database.CurrentTransaction); + + c.AuditContext.Audits.Add(new Audit()); + c.AuditContext.SaveChanges(); + + if (throwTransientError) + { + throwTransientError = false; + throw SqlExceptionFactory.CreateSqlException(10928); + } + + return result; + }, + c => + { + Assert.True(false); + return false; + }); + + context.ChangeTracker.AcceptAllChanges(); + } + + Assert.Equal(openConnection ? 2 : 3, connection.OpenCount); + Assert.Equal(6, connection.ExecutionCount); + + Assert.Equal( + openConnection + ? ConnectionState.Open + : ConnectionState.Closed, context.Database.GetDbConnection().State); + + if (openConnection) + { + if (async) + { + await context.Database.CloseConnectionAsync(); + } + else + { + context.Database.CloseConnection(); + } + } + + Assert.Equal(ConnectionState.Closed, context.Database.GetDbConnection().State); + } + + using (var context = CreateContext()) + { + Assert.Equal(2, context.Products.Count()); + } + } + [ConditionalTheory] [MemberData(nameof(DataGenerator.GetBoolCombinations), 2, MemberType = typeof(DataGenerator))] public async Task Retries_query_on_execution_failure(bool externalStrategy, bool async) @@ -629,6 +787,7 @@ public ExecutionStrategyContext(DbContextOptions options) } public DbSet Products { get; set; } + public DbSet Audits { get; set; } } protected class Product @@ -637,6 +796,19 @@ protected class Product public string Name { get; set; } } + public class AuditContext : DbContext + { + public DbSet Audits { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder.UseSqlServer(); + } + + public class Audit + { + public int AuditId { get; set; } + } + protected virtual ExecutionStrategyContext CreateContext() => (ExecutionStrategyContext)Fixture.CreateContext(); From 0ee4a0372d45d734189b577497cff162569cb046 Mon Sep 17 00:00:00 2001 From: Doug Bunting <6431421+dougbu@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:37:37 -0700 Subject: [PATCH 122/346] Update to 5.0.7 SDK and 3.1.19 runtimes (#26035) --- global.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/global.json b/global.json index 010e707d491..413ebbd0f29 100644 --- a/global.json +++ b/global.json @@ -1,17 +1,17 @@ { "tools": { - "dotnet": "5.0.206", + "dotnet": "5.0.207", "runtimes": { "dotnet": [ - "3.1.18" + "3.1.19" ], "aspnetcore": [ - "3.1.18" + "3.1.19" ] } }, "sdk": { - "version": "5.0.206", + "version": "5.0.207", "allowPrerelease": true, "rollForward": "latestMajor" }, From 4e2da08e194ca008675c2e62340bcf8990fef608 Mon Sep 17 00:00:00 2001 From: Doug Bunting <6431421+dougbu@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:40:59 -0700 Subject: [PATCH 123/346] Update to 3.1.119 SDK and 2.1.30 runtime (#26034) --- global.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/global.json b/global.json index 14e148f0bd0..cf9431ef211 100644 --- a/global.json +++ b/global.json @@ -1,15 +1,15 @@ { "tools": { - "dotnet": "3.1.118", + "dotnet": "3.1.119", "runtimes": { "dotnet": [ - "2.1.28", + "2.1.30", "$(MicrosoftNETCoreAppInternalPackageVersion)" ] } }, "sdk": { - "version": "3.1.118" + "version": "3.1.119" }, "msbuild-sdks": { "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.21427.4" From 302b2466a149d3317e76030b5ea68a1e711c6806 Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Wed, 15 Sep 2021 09:43:35 -0700 Subject: [PATCH 124/346] Bundles: Flow configuration from project Resolves #25906 --- src/EFCore.Tools/tools/EntityFrameworkCore.psm1 | 10 +--------- src/dotnet-ef/Properties/Resources.Designer.cs | 8 ++------ src/dotnet-ef/Properties/Resources.resx | 3 --- src/dotnet-ef/RootCommand.cs | 6 ++++++ .../Commands/MigrationsBundleCommand.Configure.cs | 2 -- src/ef/Commands/MigrationsBundleCommand.cs | 6 ++++-- src/ef/Commands/ProjectCommandBase.cs | 2 ++ src/ef/Properties/Resources.Designer.cs | 14 ++++++++------ src/ef/Properties/Resources.resx | 6 +++--- 9 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 index 9f4781679c7..6ba57832088 100644 --- a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 +++ b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 @@ -122,9 +122,6 @@ Register-TabExpansion Bundle-Migration @{ .PARAMETER TargetRuntime The target runtime to bundle for. -.PARAMETER Configuration - The configuration to use for the bundle. - .PARAMETER Framework The target framework. Defaults to the first one in the project. @@ -153,7 +150,6 @@ function Bundle-Migration [switch] $Force, [switch] $SelfContained, [string] $TargetRuntime, - [string] $Configuration, [string] $Framework, [string] $Context, [string] $Project, @@ -190,11 +186,6 @@ function Bundle-Migration $params += '--target-runtime', $TargetRuntime } - if ($Configuration) - { - $params += '--target-configuration', $Configuration - } - $params += GetParams $Context EF $dteProject $dteStartupProject $params $Args @@ -1308,6 +1299,7 @@ function EF($project, $startupProject, $params, $applicationArgs, [switch] $skip '--startup-project', $startupProject.FullName, '--project-dir', $projectDir, '--language', $language, + '--configuration', $activeConfiguration.ConfigurationName, '--working-dir', $PWD.Path if (IsWeb $startupProject) diff --git a/src/dotnet-ef/Properties/Resources.Designer.cs b/src/dotnet-ef/Properties/Resources.Designer.cs index 827a3cc1a93..da56529904c 100644 --- a/src/dotnet-ef/Properties/Resources.Designer.cs +++ b/src/dotnet-ef/Properties/Resources.Designer.cs @@ -1,5 +1,7 @@ // +using System; +using System.Reflection; using System.Resources; #nullable enable @@ -215,12 +217,6 @@ public static string MigrationNameDescription public static string MigrationsAddDescription => GetString("MigrationsAddDescription"); - /// - /// The configuration to use for the bundle. - /// - public static string MigrationsBundleConfigurationDescription - => GetString("MigrationsBundleConfigurationDescription"); - /// /// Creates an executable to update the database. /// diff --git a/src/dotnet-ef/Properties/Resources.resx b/src/dotnet-ef/Properties/Resources.resx index 0dcb21410c0..44abaa2ab77 100644 --- a/src/dotnet-ef/Properties/Resources.resx +++ b/src/dotnet-ef/Properties/Resources.resx @@ -216,9 +216,6 @@ Adds a new migration. - - The configuration to use for the bundle. - Creates an executable to update the database. diff --git a/src/dotnet-ef/RootCommand.cs b/src/dotnet-ef/RootCommand.cs index 9c0ff014884..649b7e2405f 100644 --- a/src/dotnet-ef/RootCommand.cs +++ b/src/dotnet-ef/RootCommand.cs @@ -184,6 +184,12 @@ protected override int Execute(string[] _) args.Add("--framework"); args.Add(startupProject.TargetFramework!); + if (_configuration.HasValue()) + { + args.Add("--configuration"); + args.Add(_configuration.Value()!); + } + if (string.Equals(project.Nullable, "enable", StringComparison.OrdinalIgnoreCase) || string.Equals(project.Nullable, "annotations", StringComparison.OrdinalIgnoreCase)) { diff --git a/src/ef/Commands/MigrationsBundleCommand.Configure.cs b/src/ef/Commands/MigrationsBundleCommand.Configure.cs index 2c3e6cf78f1..edfa7def8c5 100644 --- a/src/ef/Commands/MigrationsBundleCommand.Configure.cs +++ b/src/ef/Commands/MigrationsBundleCommand.Configure.cs @@ -12,7 +12,6 @@ internal partial class MigrationsBundleCommand : ContextCommandBase private CommandOption? _force; private CommandOption? _selfContained; private CommandOption? _runtime; - private CommandOption? _configuration; public override void Configure(CommandLineApplication command) { @@ -22,7 +21,6 @@ public override void Configure(CommandLineApplication command) _force = command.Option("-f|--force", Resources.DbContextScaffoldForceDescription); _selfContained = command.Option("--self-contained", Resources.SelfContainedDescription); _runtime = command.Option("-r|--target-runtime ", Resources.MigrationsBundleRuntimeDescription); - _configuration = command.Option("--target-configuration ", Resources.MigrationsBundleConfigurationDescription); base.Configure(command); } diff --git a/src/ef/Commands/MigrationsBundleCommand.cs b/src/ef/Commands/MigrationsBundleCommand.cs index 4813e5876e8..0adfdd38805 100644 --- a/src/ef/Commands/MigrationsBundleCommand.cs +++ b/src/ef/Commands/MigrationsBundleCommand.cs @@ -165,10 +165,12 @@ protected override int Execute(string[] args) ? "--self-contained" : "--no-self-contained"); - if (_configuration!.HasValue()) + var configuration = Configuration!.Value(); + if (string.Equals(configuration, "Debug", StringComparison.OrdinalIgnoreCase) + || string.Equals(configuration, "Release", StringComparison.OrdinalIgnoreCase)) { publishArgs.Add("--configuration"); - publishArgs.Add(_configuration!.Value()!); + publishArgs.Add(configuration!); } var exitCode = Exe.Run("dotnet", publishArgs, directory, interceptOutput: true); diff --git a/src/ef/Commands/ProjectCommandBase.cs b/src/ef/Commands/ProjectCommandBase.cs index 49e52471f9f..caab03930ce 100644 --- a/src/ef/Commands/ProjectCommandBase.cs +++ b/src/ef/Commands/ProjectCommandBase.cs @@ -28,6 +28,7 @@ internal abstract class ProjectCommandBase : EFCommandBase protected CommandOption? StartupProject { get; private set; } protected CommandOption? WorkingDir { get; private set; } protected CommandOption? Framework { get; private set; } + protected CommandOption? Configuration { get; private set; } protected string? EFCoreVersion => _efcoreVersion ??= System.Reflection.Assembly.Load("Microsoft.EntityFrameworkCore.Design") @@ -49,6 +50,7 @@ public override void Configure(CommandLineApplication command) _nullable = command.Option("--nullable", Resources.NullableDescription); WorkingDir = command.Option("--working-dir ", Resources.WorkingDirDescription); Framework = command.Option("--framework ", Resources.FrameworkDescription); + Configuration = command.Option("--configuration ", Resources.ConfigurationDescription); base.Configure(command); } diff --git a/src/ef/Properties/Resources.Designer.cs b/src/ef/Properties/Resources.Designer.cs index b3aab28affd..d546df8e610 100644 --- a/src/ef/Properties/Resources.Designer.cs +++ b/src/ef/Properties/Resources.Designer.cs @@ -1,5 +1,7 @@ // +using System; +using System.Reflection; using System.Resources; #nullable enable @@ -49,6 +51,12 @@ public static string BuildBundleSucceeded(object? path) GetString("BuildBundleSucceeded", nameof(path)), path); + /// + /// The configuration to use. + /// + public static string ConfigurationDescription + => GetString("ConfigurationDescription"); + /// /// The connection string to the database. /// @@ -285,12 +293,6 @@ public static string MigrationsAddCompleted public static string MigrationsAddDescription => GetString("MigrationsAddDescription"); - /// - /// The configuration to use for the bundle. - /// - public static string MigrationsBundleConfigurationDescription - => GetString("MigrationsBundleConfigurationDescription"); - /// /// Creates an executable to update the database. /// diff --git a/src/ef/Properties/Resources.resx b/src/ef/Properties/Resources.resx index 47b0136bf36..19467b0bca6 100644 --- a/src/ef/Properties/Resources.resx +++ b/src/ef/Properties/Resources.resx @@ -132,6 +132,9 @@ Done. Migrations Bundle: {path} + + The configuration to use. + The connection string to the database. @@ -243,9 +246,6 @@ Adds a new migration. - - The configuration to use for the bundle. - Creates an executable to update the database. From 8059b57c6599f87522904907e14ba9a852786acb Mon Sep 17 00:00:00 2001 From: Maurycy Markowski Date: Wed, 15 Sep 2021 12:57:51 -0700 Subject: [PATCH 125/346] Fix to #26014 - Migrations/Temporal Tables: null value exception when executing Down migration to convert entity from temporal to normal Problem was that we perform a null check on old and new annotation, but null is a valid value for annotation. We should allow this and also mark the annotation value as nullable object. Also fixed small issue in code gen where we would not generate code to add annotation with null value (but we were adding it for old annotation). Fixes #26014 --- .../CSharpMigrationOperationGenerator.cs | 5 --- .../Builders/AlterOperationBuilder.cs | 5 +-- .../Operations/Builders/OperationBuilder.cs | 3 +- .../CSharpMigrationOperationGeneratorTest.cs | 40 +++++++++++++++++++ 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/EFCore.Design/Migrations/Design/CSharpMigrationOperationGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpMigrationOperationGenerator.cs index 05d41c8e68e..b21012324e1 100644 --- a/src/EFCore.Design/Migrations/Design/CSharpMigrationOperationGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/CSharpMigrationOperationGenerator.cs @@ -2242,11 +2242,6 @@ protected virtual void Annotations( foreach (var annotation in annotations) { - if (annotation.Value == null) - { - continue; - } - // TODO: Give providers an opportunity to render these as provider-specific extension methods builder .AppendLine() diff --git a/src/EFCore.Relational/Migrations/Operations/Builders/AlterOperationBuilder.cs b/src/EFCore.Relational/Migrations/Operations/Builders/AlterOperationBuilder.cs index ec3b7b3ac89..0dbd455bcb1 100644 --- a/src/EFCore.Relational/Migrations/Operations/Builders/AlterOperationBuilder.cs +++ b/src/EFCore.Relational/Migrations/Operations/Builders/AlterOperationBuilder.cs @@ -29,7 +29,7 @@ public AlterOperationBuilder(TOperation operation) /// The same builder so that multiple calls can be chained. public new virtual AlterOperationBuilder Annotation( string name, - object value) + object? value) => (AlterOperationBuilder)base.Annotation(name, value); /// @@ -41,10 +41,9 @@ public AlterOperationBuilder(TOperation operation) /// The same builder so that multiple calls can be chained. public virtual AlterOperationBuilder OldAnnotation( string name, - object value) + object? value) { Check.NotEmpty(name, nameof(name)); - Check.NotNull(value, nameof(value)); Operation.OldAnnotations.AddAnnotation(name, value); diff --git a/src/EFCore.Relational/Migrations/Operations/Builders/OperationBuilder.cs b/src/EFCore.Relational/Migrations/Operations/Builders/OperationBuilder.cs index dc0f1a1868b..b940c29e3a1 100644 --- a/src/EFCore.Relational/Migrations/Operations/Builders/OperationBuilder.cs +++ b/src/EFCore.Relational/Migrations/Operations/Builders/OperationBuilder.cs @@ -41,10 +41,9 @@ TOperation IInfrastructure.Instance /// The same builder so that multiple calls can be chained. public virtual OperationBuilder Annotation( string name, - object value) + object? value) { Check.NotEmpty(name, nameof(name)); - Check.NotNull(value, nameof(value)); Operation.AddAnnotation(name, value); diff --git a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs index 603e0e17f67..0c546d7b7cb 100644 --- a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationOperationGeneratorTest.cs @@ -3625,6 +3625,46 @@ public void UpdateDataOperation_with_linebreaks() }); } + [ConditionalFact] + public void AlterTableOperation_annotation_set_to_null() + { + var oldTable = new CreateTableOperation + { + Name = "Customer", + }; + oldTable.AddAnnotation("MyAnnotation1", "Bar"); + oldTable.AddAnnotation("MyAnnotation2", null); + + var alterTable = new AlterTableOperation + { + Name = "NewCustomer", + OldTable = oldTable + }; + + alterTable.AddAnnotation("MyAnnotation1", null); + alterTable.AddAnnotation("MyAnnotation2", "Foo"); + + Test( + alterTable, + "mb.AlterTable(" + + _eol + + " name: \"NewCustomer\")" + + _eol + + " .Annotation(\"MyAnnotation1\", null)" + + _eol + + " .Annotation(\"MyAnnotation2\", \"Foo\")" + + _eol + + " .OldAnnotation(\"MyAnnotation1\", \"Bar\")" + + _eol + + " .OldAnnotation(\"MyAnnotation2\", null);", + operation => + { + Assert.Equal("NewCustomer", operation.Name); + Assert.Null(operation.GetAnnotation("MyAnnotation1").Value); + Assert.Equal("Foo", operation.GetAnnotation("MyAnnotation2").Value); + }); + } + private void Test(T operation, string expectedCode, Action assert) where T : MigrationOperation { From febaf581693f026f19bb03e1d017976e1842ca21 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Wed, 15 Sep 2021 12:15:44 -0700 Subject: [PATCH 126/346] Query: Throw better error message when final result contains IGrouping Part 1 of #26046 --- .../NavigationExpandingExpressionVisitor.cs | 7 +++++ .../Query/NorthwindGroupByQueryTestBase.cs | 28 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs index 2644ef6ffc0..a60786ee949 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs @@ -110,6 +110,13 @@ public NavigationExpandingExpressionVisitor( public virtual Expression Expand(Expression query) { var result = Visit(query); + + if (result is GroupByNavigationExpansionExpression) + { + // This indicates that GroupBy was not condensed out of grouping operator. + throw new InvalidOperationException(CoreStrings.TranslationFailed(query.Print())); + } + result = new PendingSelectorExpandingExpressionVisitor(this, _extensibilityHelper, applyIncludes: true).Visit(result); result = Reduce(result); diff --git a/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs index f11d23ba64b..b814c7bd6f5 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs @@ -2750,6 +2750,34 @@ public virtual Task GroupBy_group_Where_Select_Distinct_aggregate(bool async) #region GroupByWithoutAggregate + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_as_final_operator(bool async) + { + return AssertTranslationFailed(() => AssertQuery( + async, + ss => ss.Set().GroupBy(c => c.City))); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_Where_with_grouping_result(bool async) + { + return AssertTranslationFailed(() => AssertQuery( + async, + ss => ss.Set().GroupBy(c => c.City).Where(e => e.Key.StartsWith("s")))); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_OrderBy_with_grouping_result(bool async) + { + return AssertTranslationFailed(() => AssertQuery( + async, + ss => ss.Set().GroupBy(c => c.City).OrderBy(e => e.Key), + assertOrder: true)); + } + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task GroupBy_SelectMany(bool async) From 0b239971c7e34228e69d1608d97e308fe3d8c497 Mon Sep 17 00:00:00 2001 From: Doug Bunting <6431421+dougbu@users.noreply.github.com> Date: Wed, 15 Sep 2021 17:17:42 -0700 Subject: [PATCH 127/346] Update versions for 6.0.0 RTM (#26051) --- eng/Versions.props | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 1b0b6289d34..296baf2d717 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,8 +1,7 @@ 6.0.0 - rc - 2 + rtm False true - + - + @@ -22,12 +22,14 @@ - + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b9a55b74714..5cc88cea047 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f @@ -124,151 +124,151 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - 839e6f8714218e8a8b64ce425d62d6ed21fa35a3 + cac72e156f4e4331b0b01d96af2bb112a13e990f - + https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - aae002469c4fe298a532e11faa01378048840aa9 + 5c4cc97bcf374f63834874c7655bde3adbc96807 - + https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - aae002469c4fe298a532e11faa01378048840aa9 + 5c4cc97bcf374f63834874c7655bde3adbc96807 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx diff --git a/eng/Versions.props b/eng/Versions.props index 85b3cd5c368..dfc59b37603 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 3.1.20 3.1.20 3.1.20 - 3.1.20-servicing.21464.2 + 3.1.20-servicing.21470.6 3.1.20 @@ -55,8 +55,8 @@ 3.1.6 3.1.6 3.1.0 - 3.1.19 - 3.1.19-servicing.21416.14 + 3.1.20 + 3.1.20-servicing.21470.10 2.1.0 From 254dee81d9e0b407dd4a53c3c301a2dd3d257cf7 Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Tue, 21 Sep 2021 01:22:14 +0000 Subject: [PATCH 162/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions - Coherency Updates: - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Internal: from 3.1.20-servicing.21470.10 to 3.1.20-servicing.21470.22 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) - Microsoft.NETCore.App.Runtime.win-x64: from 3.1.20 to 3.1.20 (parent: Microsoft.Extensions.Logging) --- NuGet.config | 7 +- eng/Version.Details.xml | 148 ++++++++++++++++++++-------------------- eng/Versions.props | 4 +- 3 files changed, 80 insertions(+), 79 deletions(-) diff --git a/NuGet.config b/NuGet.config index 1e422b2dc01..de6f64bc8de 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,10 +4,10 @@ - + - + @@ -22,12 +22,13 @@ - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 5cc88cea047..c785f41f3b1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 @@ -124,151 +124,151 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - cac72e156f4e4331b0b01d96af2bb112a13e990f + e22d8efb08e7e07c353e5eb6b2dac381e90e0239 https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - 5c4cc97bcf374f63834874c7655bde3adbc96807 + 0900090e30756addbd3f545d69db659deb06c3b2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup - 5c4cc97bcf374f63834874c7655bde3adbc96807 + 0900090e30756addbd3f545d69db659deb06c3b2 https://dev.azure.com/dnceng/internal/_git/dotnet-corefx diff --git a/eng/Versions.props b/eng/Versions.props index dfc59b37603..2dfa01e30da 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 3.1.20 3.1.20 3.1.20 - 3.1.20-servicing.21470.6 + 3.1.20-servicing.21470.9 3.1.20 @@ -56,7 +56,7 @@ 3.1.6 3.1.0 3.1.20 - 3.1.20-servicing.21470.10 + 3.1.20-servicing.21470.22 2.1.0 From 904df3fdeae65b41aef77d7a883880377e0d91ae Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 21 Sep 2021 01:32:24 +0000 Subject: [PATCH 163/346] Update dependencies from https://github.com/dotnet/runtime build 20210920.14 (#26117) [release/6.0-rc2] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1f38f87c289..cc45fef5c1a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb - + https://github.com/dotnet/runtime - ea504b8fd2c91aee133d476a9c4fd39ba74a6ea4 + c8741bc2c5902b1597944ed155a1aa185924fafb diff --git a/eng/Versions.props b/eng/Versions.props index 89f7bb8f2f0..1947f4213dd 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 - 6.0.0-rc.2.21470.10 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.14 3.7.0 From 3697418fbdeeb310a13b4bc95328c35ae12acb75 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Mon, 20 Sep 2021 18:39:22 -0700 Subject: [PATCH 164/346] Update the entity type on check constraints when it's converted to a STET Fixes #23399 --- .../Conventions/CheckConstraintConvention.cs | 45 +++++++++++- .../RelationalConventionSetBuilder.cs | 8 +- .../Metadata/Internal/CheckConstraint.cs | 19 +++++ .../InternalCheckConstraintBuilder.cs | 3 +- .../SqlServerModelBuilderGenericTest.cs | 73 +++++++++++++------ 5 files changed, 118 insertions(+), 30 deletions(-) diff --git a/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs b/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs index d7f4451e502..72b8848210a 100644 --- a/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs @@ -13,12 +13,12 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// /// A convention that ensures that the check constraints on the derived types are compatible with - /// the check constraints on the base type. + /// the check constraints on the base type. And also ensures that the declaring type is current. /// /// /// See Model building conventions for more information. /// - public class CheckConstraintConvention : IEntityTypeBaseTypeChangedConvention + public class CheckConstraintConvention : IEntityTypeBaseTypeChangedConvention, IEntityTypeAddedConvention { /// /// Creates a new instance of . @@ -43,6 +43,47 @@ public CheckConstraintConvention( /// protected virtual RelationalConventionSetBuilderDependencies RelationalDependencies { get; } + /// + /// Called after an entity type is added to the model. + /// + /// The builder for the entity type. + /// Additional information associated with convention execution. + public virtual void ProcessEntityTypeAdded(IConventionEntityTypeBuilder entityTypeBuilder, IConventionContext context) + { + var entityType = entityTypeBuilder.Metadata; + if (!entityType.HasSharedClrType) + { + return; + } + + List? constraintsToReattach = null; + foreach (var checkConstraint in entityType.GetCheckConstraints()) + { + if (checkConstraint.EntityType == entityType) + { + continue; + } + + constraintsToReattach ??= new(); + + constraintsToReattach.Add(checkConstraint); + } + + if (constraintsToReattach == null) + { + return; + } + + foreach (var checkConstraint in constraintsToReattach) + { + var removedCheckConstraint = entityType.RemoveCheckConstraint(checkConstraint.ModelName); + if (removedCheckConstraint != null) + { + CheckConstraint.Attach(entityType, removedCheckConstraint); + } + } + } + /// /// Called after the base type of an entity type changes. /// diff --git a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs index 59764963ed2..7e2a71208e5 100644 --- a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs +++ b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs @@ -67,19 +67,23 @@ public override ConventionSet CreateConventionSet() conventionSet.PropertyAddedConventions.Add(relationalColumnAttributeConvention); conventionSet.PropertyAddedConventions.Add(relationalCommentAttributeConvention); + var checkConstraintConvention = new CheckConstraintConvention(Dependencies, RelationalDependencies); var tableNameFromDbSetConvention = new TableNameFromDbSetConvention(Dependencies, RelationalDependencies); conventionSet.EntityTypeAddedConventions.Add(new RelationalTableAttributeConvention(Dependencies, RelationalDependencies)); conventionSet.EntityTypeAddedConventions.Add( new RelationalTableCommentAttributeConvention(Dependencies, RelationalDependencies)); conventionSet.EntityTypeAddedConventions.Add(tableNameFromDbSetConvention); + conventionSet.EntityTypeAddedConventions.Add(checkConstraintConvention); ValueGenerationConvention valueGenerationConvention = new RelationalValueGenerationConvention(Dependencies, RelationalDependencies); ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGenerationConvention); + conventionSet.EntityTypeBaseTypeChangedConventions.Add(tableNameFromDbSetConvention); + conventionSet.EntityTypeBaseTypeChangedConventions.Add(checkConstraintConvention); + ReplaceConvention(conventionSet.ForeignKeyPropertiesChangedConventions, valueGenerationConvention); + ReplaceConvention(conventionSet.ForeignKeyOwnershipChangedConventions, valueGenerationConvention); - conventionSet.EntityTypeBaseTypeChangedConventions.Add(tableNameFromDbSetConvention); - conventionSet.EntityTypeBaseTypeChangedConventions.Add(new CheckConstraintConvention(Dependencies, RelationalDependencies)); conventionSet.EntityTypeAnnotationChangedConventions.Add((RelationalValueGenerationConvention)valueGenerationConvention); diff --git a/src/EFCore.Relational/Metadata/Internal/CheckConstraint.cs b/src/EFCore.Relational/Metadata/Internal/CheckConstraint.cs index 765d6606b71..8b35e3c63bb 100644 --- a/src/EFCore.Relational/Metadata/Internal/CheckConstraint.cs +++ b/src/EFCore.Relational/Metadata/Internal/CheckConstraint.cs @@ -166,6 +166,23 @@ public static IEnumerable GetCheckConstraints(IReadOnl return 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 static void Attach(IConventionEntityType entityType, IConventionCheckConstraint detachedCheckConstraint) + { + var newCheckConstraint = new CheckConstraint( + (IMutableEntityType)entityType, + detachedCheckConstraint.ModelName, + detachedCheckConstraint.Sql, + detachedCheckConstraint.GetConfigurationSource()); + + Attach(detachedCheckConstraint, newCheckConstraint); + } + /// /// 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 @@ -180,6 +197,8 @@ public static void Attach(IConventionCheckConstraint detachedCheckConstraint, IC ((InternalCheckConstraintBuilder)existingCheckConstraint.Builder).HasName( detachedCheckConstraint.Name, nameConfigurationSource.Value); } + + ((InternalCheckConstraintBuilder)existingCheckConstraint.Builder).MergeAnnotationsFrom((CheckConstraint)detachedCheckConstraint); } /// diff --git a/src/EFCore.Relational/Metadata/Internal/InternalCheckConstraintBuilder.cs b/src/EFCore.Relational/Metadata/Internal/InternalCheckConstraintBuilder.cs index 292af98d429..9bb12353ea7 100644 --- a/src/EFCore.Relational/Metadata/Internal/InternalCheckConstraintBuilder.cs +++ b/src/EFCore.Relational/Metadata/Internal/InternalCheckConstraintBuilder.cs @@ -16,8 +16,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Internal /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public class InternalCheckConstraintBuilder : - AnnotatableBuilder, + AnnotatableBuilder, IConventionCheckConstraintBuilder { /// diff --git a/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs b/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs index 947dd045a2a..2d7812e620d 100644 --- a/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs +++ b/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs @@ -813,37 +813,62 @@ public override void Can_configure_owned_type() { var modelBuilder = CreateModelBuilder(); - var ownedBuilder = modelBuilder.Entity().OwnsOne(c => c.Details) - .ToTable("CustomerDetails") + modelBuilder.Ignore(); + modelBuilder.Ignore(); + + var ownedBuilder = modelBuilder.Entity().OwnsOne(c => c.Details) + .ToTable("OtherCustomerDetails") .HasCheckConstraint("CK_CustomerDetails_T", "AlternateKey <> 0", c => c.HasName("CK_Guid")); ownedBuilder.Property(d => d.CustomerId); ownedBuilder.HasIndex(d => d.CustomerId); - ownedBuilder.WithOwner(d => d.Customer) + ownedBuilder.WithOwner(d => (OtherCustomer)d.Customer) .HasPrincipalKey(c => c.AlternateKey); + modelBuilder.Entity().OwnsOne(c => c.Details, b => + { + b.ToTable("SpecialCustomerDetails"); + b.HasCheckConstraint("CK_CustomerDetails_T", "AlternateKey <> 0", c => c.HasName("CK_Guid")); + b.Property(d => d.CustomerId); + b.HasIndex(d => d.CustomerId); + b.WithOwner(d => (SpecialCustomer)d.Customer) + .HasPrincipalKey(c => c.AlternateKey); + }); + var model = modelBuilder.FinalizeModel(); - var owner = model.FindEntityType(typeof(Customer)); - Assert.Equal(typeof(Customer).FullName, owner.Name); - var ownership = owner.FindNavigation(nameof(Customer.Details)).ForeignKey; - Assert.True(ownership.IsOwnership); - Assert.Equal(nameof(Customer.Details), ownership.PrincipalToDependent.Name); - Assert.Equal("CustomerAlternateKey", ownership.Properties.Single().Name); - Assert.Equal(nameof(Customer.AlternateKey), ownership.PrincipalKey.Properties.Single().Name); - var owned = ownership.DeclaringEntityType; - Assert.Same(ownedBuilder.OwnedEntityType, owned); - Assert.Equal("CustomerDetails", owned.GetTableName()); - var checkConstraint = owned.GetCheckConstraints().Single(); - Assert.Equal("CK_CustomerDetails_T", checkConstraint.ModelName); - Assert.Equal("AlternateKey <> 0", checkConstraint.Sql); - Assert.Equal("CK_Guid", checkConstraint.Name); - Assert.Single(owned.GetForeignKeys()); - Assert.Equal(nameof(CustomerDetails.CustomerId), owned.GetIndexes().Single().Properties.Single().Name); - Assert.Equal( - new[] { "CustomerAlternateKey", nameof(CustomerDetails.CustomerId), nameof(CustomerDetails.Id) }, - owned.GetProperties().Select(p => p.Name)); - Assert.NotNull(model.FindEntityType(typeof(CustomerDetails))); - Assert.Equal(1, model.GetEntityTypes().Count(e => e.ClrType == typeof(CustomerDetails))); + var owner1 = model.FindEntityType(typeof(OtherCustomer)); + Assert.Equal(typeof(OtherCustomer).FullName, owner1.Name); + AssertOwnership(owner1); + + var owner2 = model.FindEntityType(typeof(SpecialCustomer)); + Assert.Equal(typeof(SpecialCustomer).FullName, owner2.Name); + AssertOwnership(owner2); + + Assert.Null(model.FindEntityType(typeof(CustomerDetails))); + Assert.Equal(2, model.GetEntityTypes().Count(e => e.ClrType == typeof(CustomerDetails))); + + static void AssertOwnership(IEntityType owner) + { + var ownership1 = owner.FindNavigation(nameof(Customer.Details)).ForeignKey; + Assert.True(ownership1.IsOwnership); + Assert.Equal(nameof(Customer.Details), ownership1.PrincipalToDependent.Name); + Assert.Equal("CustomerAlternateKey", ownership1.Properties.Single().Name); + Assert.Equal(nameof(Customer.AlternateKey), ownership1.PrincipalKey.Properties.Single().Name); + var owned = ownership1.DeclaringEntityType; + Assert.Equal(owner.ShortName() + "Details", owned.GetTableName()); + var checkConstraint = owned.GetCheckConstraints().Single(); + Assert.Same(owned, checkConstraint.EntityType); + Assert.Equal("CK_CustomerDetails_T", checkConstraint.ModelName); + Assert.Equal("AlternateKey <> 0", checkConstraint.Sql); + Assert.Equal("CK_Guid", checkConstraint.Name); + Assert.Single(owned.GetForeignKeys()); + var index = owned.GetIndexes().Single(); + Assert.Same(owned, index.DeclaringEntityType); + Assert.Equal(nameof(CustomerDetails.CustomerId), index.Properties.Single().Name); + Assert.Equal( + new[] { "CustomerAlternateKey", nameof(CustomerDetails.CustomerId), nameof(CustomerDetails.Id) }, + owned.GetProperties().Select(p => p.Name)); + } } [ConditionalFact] From fe9a92d206b582ee47ec2fbe7f08b9c56a5400d3 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 21 Sep 2021 04:05:33 +0000 Subject: [PATCH 165/346] Update dependencies from https://github.com/dotnet/runtime build 20210920.18 (#26118) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 71b4e6cf37b..299d4cf63a4 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 - + https://github.com/dotnet/runtime - 70f8bb2098f8a946888ee81b4e51aa71d573b407 + 90e6b31097ce7de6a3a532f3d51885265ad6e646 diff --git a/eng/Versions.props b/eng/Versions.props index 0e54613ee08..32229197d2f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -14,17 +14,17 @@ False - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 - 6.0.0-rc.2.21467.25 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.18 3.7.0 From 398dba2b6860cb7d9745e310a90e4416a64010a5 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 21 Sep 2021 04:11:32 +0000 Subject: [PATCH 166/346] Update dependencies from https://github.com/dotnet/runtime build 20210920.16 (#26119) [release/6.0-rc2] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index cc45fef5c1a..8369ae02a3e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e - + https://github.com/dotnet/runtime - c8741bc2c5902b1597944ed155a1aa185924fafb + d0603006399b2a806b4f848f4e8986d3b2306b5e diff --git a/eng/Versions.props b/eng/Versions.props index 1947f4213dd..fdac6512a78 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 - 6.0.0-rc.2.21470.14 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.16 3.7.0 From 7381df3ad840da435f32fc75335d818439c10884 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 21 Sep 2021 06:51:40 +0000 Subject: [PATCH 167/346] Update dependencies from https://github.com/dotnet/runtime build 20210920.23 (#26120) [release/6.0-rc2] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 8369ae02a3e..dad64aa2865 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 - + https://github.com/dotnet/runtime - d0603006399b2a806b4f848f4e8986d3b2306b5e + 826f81a11ad17f415668fe1cb934bdaf00d36ea2 diff --git a/eng/Versions.props b/eng/Versions.props index fdac6512a78..0af80eb3315 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -15,17 +15,17 @@ False - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 - 6.0.0-rc.2.21470.16 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 + 6.0.0-rc.2.21470.23 3.7.0 From 13a1cdde4d4a024df689a2b289fc50f2d6796923 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 21 Sep 2021 06:51:55 +0000 Subject: [PATCH 168/346] Update dependencies from https://github.com/dotnet/runtime build 20210920.22 (#26121) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 299d4cf63a4..4b4a57522df 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 - + https://github.com/dotnet/runtime - 90e6b31097ce7de6a3a532f3d51885265ad6e646 + da9d3777afe61bbcfd16ff70ca150433370b4139 diff --git a/eng/Versions.props b/eng/Versions.props index 32229197d2f..9e663f6f795 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -14,17 +14,17 @@ False - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 - 6.0.0-rtm.21470.18 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 + 6.0.0-rtm.21470.22 3.7.0 From b8e147f6094560391786337ab8991723cdb2fe94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Sep 2021 11:27:52 -0700 Subject: [PATCH 169/346] Bump Microsoft.Azure.Cosmos from 3.20.1 to 3.21.0 Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/EFCore.Cosmos/EFCore.Cosmos.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EFCore.Cosmos/EFCore.Cosmos.csproj b/src/EFCore.Cosmos/EFCore.Cosmos.csproj index 3ce935402d2..02606147b58 100644 --- a/src/EFCore.Cosmos/EFCore.Cosmos.csproj +++ b/src/EFCore.Cosmos/EFCore.Cosmos.csproj @@ -20,7 +20,7 @@ - + From afaeff0867d3c92196a9495530a6bbbc12733528 Mon Sep 17 00:00:00 2001 From: Maurycy Markowski Date: Thu, 16 Sep 2021 14:33:29 -0700 Subject: [PATCH 170/346] Fix to #24490 - Update exception message when correlated collection cannot be projected Updating the message and resource string name to reflect the changes in behavior after we've improved this scenario. Fixes #24490 --- .../Properties/RelationalStrings.Designer.cs | 6 ++--- .../Properties/RelationalStrings.resx | 4 +-- .../Query/SqlExpressions/SelectExpression.cs | 2 +- ...ctionsSharedTypeQueryRelationalTestBase.cs | 2 +- ...sSplitSharedTypeQueryRelationalTestBase.cs | 2 +- .../GearsOfWarQueryRelationalTestBase.cs | 4 +-- ...NorthwindGroupByQueryRelationalTestBase.cs | 4 +-- ...dKeylessEntitiesQueryRelationalTestBase.cs | 8 +++--- .../NorthwindSelectQueryRelationalTestBase.cs | 2 +- ...indSetOperationsQueryRelationalTestBase.cs | 2 +- .../Query/UdfDbFunctionTestBase.cs | 26 ++++++++++++++----- .../Query/UdfDbFunctionSqlServerTests.cs | 8 ++++++ 12 files changed, 46 insertions(+), 24 deletions(-) diff --git a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs index 34c87273ba9..270916b9031 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs +++ b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs @@ -690,10 +690,10 @@ public static string InsertDataOperationValuesCountMismatch(object? valuesCount, valuesCount, columnsCount, table); /// - /// Unable to translate a collection subquery in a projection since the parent query doesn't project the key columns of all tables required to generate results on the client side. This can happen when trying to correlate on keyless entity or when using 'Distinct' or 'GroupBy' operations without projecting all of the key columns. + /// Unable to translate a collection subquery in a projection since either parent or the subquery doesn't project necessary information required to uniquely identify it and correctly generate results on the client side. This can happen when trying to correlate on keyless entity type. This can also happen for some cases of projection before 'Distinct' or some shapes of grouping key in case of 'GroupBy'. These should either contain all key properties of the entity that the operation is applied on, or only contain simple property access expressions. /// - public static string InsufficientInformationToIdentifyOuterElementOfCollectionJoin - => GetString("InsufficientInformationToIdentifyOuterElementOfCollectionJoin"); + public static string InsufficientInformationToIdentifyElementOfCollectionJoin + => GetString("InsufficientInformationToIdentifyElementOfCollectionJoin"); /// /// The specified 'CommandTimeout' value '{value}' is not valid. It must be a positive number. diff --git a/src/EFCore.Relational/Properties/RelationalStrings.resx b/src/EFCore.Relational/Properties/RelationalStrings.resx index 30ceccf692e..6f78a08c9c3 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.resx +++ b/src/EFCore.Relational/Properties/RelationalStrings.resx @@ -375,8 +375,8 @@ The number of values ({valuesCount}) doesn't match the number of columns ({columnsCount}) for the data insertion operation on '{table}'. Provide the same number of values and columns. - - Unable to translate a collection subquery in a projection since the parent query doesn't project the key columns of all tables required to generate results on the client side. This can happen when trying to correlate on keyless entity or when using 'Distinct' or 'GroupBy' operations without projecting all of the key columns. + + Unable to translate a collection subquery in a projection since either parent or the subquery doesn't project necessary information required to uniquely identify it and correctly generate results on the client side. This can happen when trying to correlate on keyless entity type. This can also happen for some cases of projection before 'Distinct' or some shapes of grouping key in case of 'GroupBy'. These should either contain all key properties of the entity that the operation is applied on, or only contain simple property access expressions. The specified 'CommandTimeout' value '{value}' is not valid. It must be a positive number. diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 69eb170f938..311da77d97a 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -591,7 +591,7 @@ static Expression RemoveConvert(Expression expression) if (_identifier.Count == 0 || innerSelectExpression._identifier.Count == 0) { - throw new InvalidOperationException(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin); + throw new InvalidOperationException(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin); } var innerShaperExpression = shapedQueryExpression.ShaperExpression; diff --git a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase.cs index 6afd89e1590..7f9b430ea29 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase.cs @@ -19,7 +19,7 @@ protected ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase(TFixtur public override async Task SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(bool async) { Assert.Equal( - RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, + RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, (await Assert.ThrowsAsync( () => base.SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(async))).Message); } diff --git a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase.cs index 5a2658dcdcd..cb89fda497b 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase.cs @@ -21,7 +21,7 @@ protected ComplexNavigationsCollectionsSplitSharedTypeQueryRelationalTestBase(TF public override async Task SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(bool async) { Assert.Equal( - RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, + RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, (await Assert.ThrowsAsync( () => base.SelectMany_with_navigation_and_Distinct_projecting_columns_including_join_key(async))).Message); } diff --git a/test/EFCore.Relational.Specification.Tests/Query/GearsOfWarQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/GearsOfWarQueryRelationalTestBase.cs index 51195848cbf..c1e98bcce79 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/GearsOfWarQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/GearsOfWarQueryRelationalTestBase.cs @@ -24,7 +24,7 @@ public override async Task Correlated_collection_with_groupby_with_complex_group var message = (await Assert.ThrowsAsync( () => base.Correlated_collection_with_groupby_with_complex_grouping_key_not_projecting_identifier_column_with_group_aggregate_in_final_projection(async))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } public override async Task Correlated_collection_with_distinct_not_projecting_identifier_column_also_projecting_complex_expressions(bool async) @@ -32,7 +32,7 @@ public override async Task Correlated_collection_with_distinct_not_projecting_id var message = (await Assert.ThrowsAsync( () => base.Correlated_collection_with_distinct_not_projecting_identifier_column_also_projecting_complex_expressions(async))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } public override async Task Client_eval_followed_by_aggregate_operation(bool async) diff --git a/test/EFCore.Relational.Specification.Tests/Query/NorthwindGroupByQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NorthwindGroupByQueryRelationalTestBase.cs index f9724eee19a..bd1b77da362 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NorthwindGroupByQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NorthwindGroupByQueryRelationalTestBase.cs @@ -24,7 +24,7 @@ public override async Task Complex_query_with_groupBy_in_subquery4(bool async) var message = (await Assert.ThrowsAsync( () => base.Complex_query_with_groupBy_in_subquery4(async))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } public override async Task Select_correlated_collection_after_GroupBy_aggregate_when_identifier_changes_to_complex(bool async) @@ -32,7 +32,7 @@ public override async Task Select_correlated_collection_after_GroupBy_aggregate_ var message = (await Assert.ThrowsAsync( () => base.Select_correlated_collection_after_GroupBy_aggregate_when_identifier_changes_to_complex(async))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } protected virtual bool CanExecuteQueryString diff --git a/test/EFCore.Relational.Specification.Tests/Query/NorthwindKeylessEntitiesQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NorthwindKeylessEntitiesQueryRelationalTestBase.cs index df02b4129be..b1cb0a4d159 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NorthwindKeylessEntitiesQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NorthwindKeylessEntitiesQueryRelationalTestBase.cs @@ -37,7 +37,7 @@ public virtual async Task Projecting_collection_correlated_with_keyless_entity_t OrderDetailIds = ss.Set().Where(c => c.City == cq.City).ToList() }).OrderBy(x => x.City).Take(2)))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } [ConditionalTheory] @@ -53,7 +53,7 @@ public virtual async Task Collection_of_entities_projecting_correlated_collectio Collection = ss.Set().Where(cq => cq.City == c.City).ToList(), })))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } [ConditionalTheory] @@ -63,7 +63,7 @@ public override async Task KeylessEntity_with_included_navs_multi_level(bool asy var message = (await Assert.ThrowsAsync( () => base.KeylessEntity_with_included_navs_multi_level(async))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } [ConditionalTheory] @@ -73,7 +73,7 @@ public override async Task KeylessEntity_with_defining_query_and_correlated_coll var message = (await Assert.ThrowsAsync( () => base.KeylessEntity_with_defining_query_and_correlated_collection(async))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } protected override QueryAsserter CreateQueryAsserter(TFixture fixture) diff --git a/test/EFCore.Relational.Specification.Tests/Query/NorthwindSelectQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NorthwindSelectQueryRelationalTestBase.cs index 429af5c9e4c..2e64a195be9 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NorthwindSelectQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NorthwindSelectQueryRelationalTestBase.cs @@ -22,7 +22,7 @@ public override async Task Correlated_collection_after_groupby_with_complex_proj var message = (await Assert.ThrowsAsync( () => base.Correlated_collection_after_groupby_with_complex_projection_not_containing_original_identifier(async))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } public override Task Select_bool_closure_with_order_by_property_with_cast_to_nullable(bool async) diff --git a/test/EFCore.Relational.Specification.Tests/Query/NorthwindSetOperationsQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NorthwindSetOperationsQueryRelationalTestBase.cs index 48183a9094d..e6d80432b68 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NorthwindSetOperationsQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NorthwindSetOperationsQueryRelationalTestBase.cs @@ -22,7 +22,7 @@ public override async Task Collection_projection_after_set_operation_fails_if_di var message = (await Assert.ThrowsAsync( () => base.Collection_projection_after_set_operation_fails_if_distinct(async))).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } public override async Task Collection_projection_before_set_operation_fails(bool async) diff --git a/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs index 0a376a0d207..723de52f7ba 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs @@ -1423,7 +1423,7 @@ public virtual void QF_Anonymous_Collection_No_PK_Throws() }; Assert.Equal( - RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, + RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, Assert.Throws(() => query.ToList()).Message); } } @@ -1544,7 +1544,21 @@ public virtual void QF_Select_Direct_In_Anonymous() Prods = context.GetTopTwoSellingProducts().ToList(), }).ToList()).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); + } + } + + [ConditionalFact(Skip = "issue #26078")] + public virtual void QF_Select_Direct_In_Anonymous_distinct() + { + using (var context = CreateContext()) + { + var query = (from c in context.Customers + select new + { + c.Id, + Prods = context.GetTopTwoSellingProducts().Distinct().ToList(), + }).ToList(); } } @@ -1638,7 +1652,7 @@ public virtual void QF_Select_Correlated_Subquery_In_Anonymous_Nested() }).ToList() }).ToList()).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } } @@ -1656,7 +1670,7 @@ public virtual void QF_Select_Correlated_Subquery_In_Anonymous_MultipleCollectio Prods = context.GetTopTwoSellingProducts().Where(p => p.AmountSold == 249).Select(p => p.ProductId).ToList() }).ToList()).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } } @@ -1673,7 +1687,7 @@ public virtual void QF_Select_NonCorrelated_Subquery_In_Anonymous() Prods = context.GetTopTwoSellingProducts().Select(p => p.ProductId).ToList(), }).ToList()).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } } @@ -1691,7 +1705,7 @@ public virtual void QF_Select_NonCorrelated_Subquery_In_Anonymous_Parameter() Prods = context.GetTopTwoSellingProducts().Where(p => p.AmountSold == amount).Select(p => p.ProductId).ToList(), }).ToList()).Message; - Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin, message); + Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message); } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs b/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs index d28120994e1..ce6d785dde4 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs @@ -533,6 +533,14 @@ CROSS APPLY [dbo].[GetCustomerOrderCountByYear]([c].[Id]) AS [g] ORDER BY [g].[Year]"); } + public override void QF_Select_Direct_In_Anonymous_distinct() + { + base.QF_Select_Direct_In_Anonymous_distinct(); + + AssertSql( + @""); + } + public override void QF_Select_Correlated_Direct_With_Function_Query_Parameter_Correlated_In_Anonymous() { base.QF_Select_Correlated_Direct_With_Function_Query_Parameter_Correlated_In_Anonymous(); From 57b852977b661959d89c8ee7d248122b3c064718 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 22 Sep 2021 03:21:09 +0000 Subject: [PATCH 171/346] Update dependencies from https://github.com/dotnet/runtime build 20210921.19 (#26131) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4b4a57522df..c320ea80e5a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 - + https://github.com/dotnet/runtime - da9d3777afe61bbcfd16ff70ca150433370b4139 + 036cb862a4e99b1fa035f654debad7091646fbe4 diff --git a/eng/Versions.props b/eng/Versions.props index 9e663f6f795..bd00b878571 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -14,17 +14,17 @@ False - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 - 6.0.0-rtm.21470.22 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 + 6.0.0-rtm.21471.19 3.7.0 From 897e63f22c9178ac838b61ff319449a8ab149c04 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 22 Sep 2021 15:05:17 +0000 Subject: [PATCH 172/346] Update dependencies from https://github.com/dotnet/arcade build 20210921.4 (#26139) [release/5.0] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 8 ++++---- global.json | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index be6848f5aed..3e343f462b3 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -51,13 +51,13 @@ - + https://github.com/dotnet/arcade - 2e26f9ebee3ac27803aa5f2df50192a46393d108 + f2ebec887288367b18d3299cce38ae3365215555 - + https://github.com/dotnet/arcade - 2e26f9ebee3ac27803aa5f2df50192a46393d108 + f2ebec887288367b18d3299cce38ae3365215555 diff --git a/global.json b/global.json index 413ebbd0f29..5b05f942413 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "tools": { - "dotnet": "5.0.207", + "dotnet": "5.0.401", "runtimes": { "dotnet": [ "3.1.19" @@ -11,12 +11,12 @@ } }, "sdk": { - "version": "5.0.207", + "version": "5.0.401", "allowPrerelease": true, "rollForward": "latestMajor" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.21427.7", - "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.21427.7" + "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.21471.4", + "Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.21471.4" } } From 3b67c3d9198cc540767b4d4eb6f5543b89b4dcb8 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Wed, 22 Sep 2021 09:45:18 -0700 Subject: [PATCH 173/346] Use the correct value when the discriminator is part of the key. Optimize the discriminator value in the runtime model Fixes #18126 --- .../CSharpRuntimeModelCodeGenerator.cs | 10 ++++++++++ .../Internal/ValueGenerationManager.cs | 5 +---- .../CSharpRuntimeAnnotationCodeGenerator.cs | 1 - .../Conventions/RuntimeModelConvention.cs | 4 ++-- src/EFCore/Metadata/RuntimeEntityType.cs | 10 +++++++++- src/EFCore/Metadata/RuntimeModel.cs | 7 +++++-- .../DiscriminatorValueGeneratorFactory.cs | 2 +- .../Internal/DiscriminatorValueGenerator.cs | 17 +++-------------- .../CSharpRuntimeModelCodeGeneratorTest.cs | 16 ++++++++-------- .../CompositeKeyEndToEndTestBase.cs | 19 +++++++++++++++---- 10 files changed, 54 insertions(+), 37 deletions(-) diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs index 667564d3f5e..9a40b8923e0 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs @@ -658,6 +658,16 @@ private void Create(IEntityType entityType, CSharpRuntimeAnnotationCodeGenerator .Append(_code.Literal(true)); } + var discriminatorValue = entityType.GetDiscriminatorValue(); + if (discriminatorValue != null) + { + AddNamespace(discriminatorValue.GetType(), parameters.Namespaces); + + mainBuilder.AppendLine(",") + .Append("discriminatorValue: ") + .Append(_code.UnknownLiteral(discriminatorValue)); + } + mainBuilder .AppendLine(");") .AppendLine() diff --git a/src/EFCore/ChangeTracking/Internal/ValueGenerationManager.cs b/src/EFCore/ChangeTracking/Internal/ValueGenerationManager.cs index 84d07c99394..8a608bae0ee 100644 --- a/src/EFCore/ChangeTracking/Internal/ValueGenerationManager.cs +++ b/src/EFCore/ChangeTracking/Internal/ValueGenerationManager.cs @@ -160,10 +160,7 @@ public virtual async Task GenerateAsync( } private ValueGenerator GetValueGenerator(InternalEntityEntry entry, IProperty property) - => _valueGeneratorSelector.Select( - property, property.IsKey() - ? property.DeclaringEntityType - : entry.EntityType); + => _valueGeneratorSelector.Select(property, property.DeclaringEntityType); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore/Design/Internal/CSharpRuntimeAnnotationCodeGenerator.cs b/src/EFCore/Design/Internal/CSharpRuntimeAnnotationCodeGenerator.cs index b33c6138732..287ac6b30c9 100644 --- a/src/EFCore/Design/Internal/CSharpRuntimeAnnotationCodeGenerator.cs +++ b/src/EFCore/Design/Internal/CSharpRuntimeAnnotationCodeGenerator.cs @@ -67,7 +67,6 @@ public virtual void Generate(IEntityType entityType, CSharpRuntimeAnnotationCode foreach (var annotation in annotations) { if (CoreAnnotationNames.AllNames.Contains(annotation.Key) - && annotation.Key != CoreAnnotationNames.DiscriminatorValue && annotation.Key != CoreAnnotationNames.DiscriminatorMappingComplete) { annotations.Remove(annotation.Key); diff --git a/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs b/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs index 1ce792486c9..03355f9bfd3 100644 --- a/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs +++ b/src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs @@ -223,7 +223,8 @@ private RuntimeEntityType Create(IEntityType entityType, RuntimeModel model) entityType.GetDiscriminatorPropertyName(), entityType.GetChangeTrackingStrategy(), entityType.FindIndexerPropertyInfo(), - entityType.IsPropertyBag); + entityType.IsPropertyBag, + entityType.GetDiscriminatorValue()); private ParameterBinding Create(ParameterBinding parameterBinding, RuntimeEntityType entityType) => parameterBinding.With(parameterBinding.ConsumedProperties.Select(property => @@ -256,7 +257,6 @@ protected virtual void ProcessEntityTypeAnnotations( if (CoreAnnotationNames.AllNames.Contains(annotation.Key) && annotation.Key != CoreAnnotationNames.QueryFilter && annotation.Key != CoreAnnotationNames.DefiningQuery - && annotation.Key != CoreAnnotationNames.DiscriminatorValue && annotation.Key != CoreAnnotationNames.DiscriminatorMappingComplete) { annotations.Remove(annotation.Key); diff --git a/src/EFCore/Metadata/RuntimeEntityType.cs b/src/EFCore/Metadata/RuntimeEntityType.cs index 638df57a49b..47fba81093a 100644 --- a/src/EFCore/Metadata/RuntimeEntityType.cs +++ b/src/EFCore/Metadata/RuntimeEntityType.cs @@ -59,6 +59,7 @@ private readonly SortedDictionary _serviceProper private InstantiationBinding? _serviceOnlyConstructorBinding; private readonly PropertyInfo? _indexerPropertyInfo; private readonly bool _isPropertyBag; + private readonly object? _discriminatorValue; // Warning: Never access these fields directly as access needs to be thread-safe private PropertyCounts? _counts; @@ -89,7 +90,8 @@ public RuntimeEntityType( string? discriminatorProperty, ChangeTrackingStrategy changeTrackingStrategy, PropertyInfo? indexerPropertyInfo, - bool propertyBag) + bool propertyBag, + object? discriminatorValue) { Name = name; _clrType = type; @@ -104,6 +106,7 @@ public RuntimeEntityType( _indexerPropertyInfo = indexerPropertyInfo; _isPropertyBag = propertyBag; SetAnnotation(CoreAnnotationNames.DiscriminatorProperty, discriminatorProperty); + _discriminatorValue = discriminatorValue; _properties = new SortedDictionary(new PropertyNameComparer(this)); } @@ -860,6 +863,11 @@ ChangeTrackingStrategy IReadOnlyEntityType.GetChangeTrackingStrategy() return (string?)this[CoreAnnotationNames.DiscriminatorProperty]; } + /// + [DebuggerStepThrough] + object? IReadOnlyEntityType.GetDiscriminatorValue() + => _discriminatorValue; + /// bool IReadOnlyTypeBase.HasSharedClrType { diff --git a/src/EFCore/Metadata/RuntimeModel.cs b/src/EFCore/Metadata/RuntimeModel.cs index d018b88ee30..9e021887431 100644 --- a/src/EFCore/Metadata/RuntimeModel.cs +++ b/src/EFCore/Metadata/RuntimeModel.cs @@ -69,6 +69,7 @@ public virtual void SetSkipDetectChanges(bool skipDetectChanges) /// A value indicating whether this entity type has an indexer which is able to contain arbitrary properties /// and a method that can be used to determine whether a given indexer property contains a value. /// + /// the discriminator value for this entity type. /// The new entity type. public virtual RuntimeEntityType AddEntityType( string name, @@ -78,7 +79,8 @@ public virtual RuntimeEntityType AddEntityType( string? discriminatorProperty = null, ChangeTrackingStrategy changeTrackingStrategy = ChangeTrackingStrategy.Snapshot, PropertyInfo? indexerPropertyInfo = null, - bool propertyBag = false) + bool propertyBag = false, + object? discriminatorValue = null) { var entityType = new RuntimeEntityType( name, @@ -89,7 +91,8 @@ public virtual RuntimeEntityType AddEntityType( discriminatorProperty, changeTrackingStrategy, indexerPropertyInfo, - propertyBag); + propertyBag, + discriminatorValue); if (sharedClrType) { diff --git a/src/EFCore/ValueGeneration/DiscriminatorValueGeneratorFactory.cs b/src/EFCore/ValueGeneration/DiscriminatorValueGeneratorFactory.cs index 5a28fe25502..a040064025a 100644 --- a/src/EFCore/ValueGeneration/DiscriminatorValueGeneratorFactory.cs +++ b/src/EFCore/ValueGeneration/DiscriminatorValueGeneratorFactory.cs @@ -17,6 +17,6 @@ public class DiscriminatorValueGeneratorFactory : ValueGeneratorFactory { /// public override ValueGenerator Create(IProperty property, IEntityType entityType) - => new DiscriminatorValueGenerator(entityType.GetDiscriminatorValue()!); + => new DiscriminatorValueGenerator(); } } diff --git a/src/EFCore/ValueGeneration/Internal/DiscriminatorValueGenerator.cs b/src/EFCore/ValueGeneration/Internal/DiscriminatorValueGenerator.cs index 041c74ca20d..05a99ab71dc 100644 --- a/src/EFCore/ValueGeneration/Internal/DiscriminatorValueGenerator.cs +++ b/src/EFCore/ValueGeneration/Internal/DiscriminatorValueGenerator.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace Microsoft.EntityFrameworkCore.ValueGeneration.Internal { @@ -13,19 +15,6 @@ namespace Microsoft.EntityFrameworkCore.ValueGeneration.Internal /// public class DiscriminatorValueGenerator : ValueGenerator { - private readonly object _discriminator; - - /// - /// 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 DiscriminatorValueGenerator(object discriminator) - { - _discriminator = discriminator; - } - /// /// 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 @@ -33,7 +22,7 @@ public DiscriminatorValueGenerator(object discriminator) /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected override object NextValue(EntityEntry entry) - => _discriminator; + => entry.GetInfrastructure().EntityType.GetDiscriminatorValue()!; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs index c93b47dedc1..d0fb98f0198 100644 --- a/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs +++ b/test/EFCore.Design.Tests/Scaffolding/Internal/CSharpRuntimeModelCodeGeneratorTest.cs @@ -652,7 +652,8 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas ""Microsoft.EntityFrameworkCore.TestModels.AspNetIdentity.IdentityUser"", typeof(IdentityUser), baseEntityType, - discriminatorProperty: ""Discriminator""); + discriminatorProperty: ""Discriminator"", + discriminatorValue: ""IdentityUser""); var id = runtimeEntityType.AddProperty( ""Id"", @@ -769,7 +770,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { - runtimeEntityType.AddAnnotation(""DiscriminatorValue"", ""IdentityUser""); Customize(runtimeEntityType); } @@ -801,14 +801,14 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas ""Microsoft.EntityFrameworkCore.Scaffolding.Internal.IdentityUser"", typeof(IdentityUser), baseEntityType, - discriminatorProperty: ""Discriminator""); + discriminatorProperty: ""Discriminator"", + discriminatorValue: ""DerivedIdentityUser""); return runtimeEntityType; } public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { - runtimeEntityType.AddAnnotation(""DiscriminatorValue"", ""DerivedIdentityUser""); Customize(runtimeEntityType); } @@ -958,7 +958,8 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? ba ""Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGeneratorTest+DependentBase"", typeof(CSharpRuntimeModelCodeGeneratorTest.DependentBase), baseEntityType, - discriminatorProperty: ""EnumDiscriminator""); + discriminatorProperty: ""EnumDiscriminator"", + discriminatorValue: CSharpMigrationsGeneratorTest.Enum1.One); var principalId = runtimeEntityType.AddProperty( ""PrincipalId"", @@ -1040,7 +1041,6 @@ public static RuntimeForeignKey CreateForeignKey2(RuntimeEntityType declaringEnt public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { - runtimeEntityType.AddAnnotation(""DiscriminatorValue"", CSharpMigrationsGeneratorTest.Enum1.One); runtimeEntityType.AddAnnotation(""Relational:FunctionName"", null); runtimeEntityType.AddAnnotation(""Relational:Schema"", null); runtimeEntityType.AddAnnotation(""Relational:SqlQuery"", null); @@ -1480,7 +1480,8 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? ba ""Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGeneratorTest+DependentDerived"", typeof(CSharpRuntimeModelCodeGeneratorTest.DependentDerived), baseEntityType, - discriminatorProperty: ""EnumDiscriminator""); + discriminatorProperty: ""EnumDiscriminator"", + discriminatorValue: CSharpMigrationsGeneratorTest.Enum1.Two); var data = runtimeEntityType.AddProperty( ""Data"", @@ -1505,7 +1506,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType? ba public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { - runtimeEntityType.AddAnnotation(""DiscriminatorValue"", CSharpMigrationsGeneratorTest.Enum1.Two); runtimeEntityType.AddAnnotation(""Relational:FunctionName"", null); runtimeEntityType.AddAnnotation(""Relational:Schema"", null); runtimeEntityType.AddAnnotation(""Relational:SqlQuery"", null); diff --git a/test/EFCore.Specification.Tests/CompositeKeyEndToEndTestBase.cs b/test/EFCore.Specification.Tests/CompositeKeyEndToEndTestBase.cs index 207f26e61ea..3df0fadb08a 100644 --- a/test/EFCore.Specification.Tests/CompositeKeyEndToEndTestBase.cs +++ b/test/EFCore.Specification.Tests/CompositeKeyEndToEndTestBase.cs @@ -26,13 +26,16 @@ public virtual async Task Can_use_two_non_generated_integers_as_composite_key_en using (var context = CreateContext()) { - context.Add( + var pegasus = context.Add( new Pegasus { Id1 = ticks, Id2 = ticks + 1, Name = "Rainbow Dash" }); + + Assert.Equal("Pegasus", pegasus.Entity.Discriminator); + await context.SaveChangesAsync(); } @@ -40,6 +43,7 @@ public virtual async Task Can_use_two_non_generated_integers_as_composite_key_en { var pegasus = context.Pegasuses.Single(e => e.Id1 == ticks && e.Id2 == ticks + 1); + Assert.Equal("Pegasus", pegasus.Discriminator); pegasus.Name = "Rainbow Crash"; await context.SaveChangesAsync(); @@ -212,13 +216,15 @@ public BronieContext(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity( + modelBuilder.Entity( b => { b.HasKey( - e => new { e.Id1, e.Id2 }); + e => new { e.Id1, e.Id2, e.Discriminator }); }); + modelBuilder.Entity(); + modelBuilder.Entity( b => { @@ -243,10 +249,15 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) } } - protected class Pegasus + protected abstract class Flyer { + public string Discriminator { get; set; } public long Id1 { get; set; } public long Id2 { get; set; } + } + + protected class Pegasus : Flyer + { public string Name { get; set; } } From 2b2f3a3747d7d37db2db2a514800156356f5b856 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Wed, 22 Sep 2021 10:43:21 -0700 Subject: [PATCH 174/346] Preserve extension registration order Fixes #26071 --- src/EFCore/DbContextOptions.cs | 62 ++++++++++++++----- src/EFCore/DbContextOptions`.cs | 16 ++++- .../LoggingTestBase.cs | 4 +- test/EFCore.Tests/ServiceProviderCacheTest.cs | 57 +++++++++++++++++ 4 files changed, 120 insertions(+), 19 deletions(-) diff --git a/src/EFCore/DbContextOptions.cs b/src/EFCore/DbContextOptions.cs index 9a6be25581d..d61afcdfba9 100644 --- a/src/EFCore/DbContextOptions.cs +++ b/src/EFCore/DbContextOptions.cs @@ -22,27 +22,56 @@ namespace Microsoft.EntityFrameworkCore /// public abstract class DbContextOptions : IDbContextOptions { + private readonly ImmutableSortedDictionary _extensionsMap; + + /// + /// 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] + protected DbContextOptions() + { + _extensionsMap = ImmutableSortedDictionary.Create(TypeFullNameComparer.Instance); + } + /// - /// Initializes a new instance of the class. You normally override - /// or use a - /// to create instances of this class and it is not designed to be directly constructed in your application code. + /// 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 extensions that store the configured options. + [EntityFrameworkInternal] protected DbContextOptions( IReadOnlyDictionary extensions) { Check.NotNull(extensions, nameof(extensions)); - _extensionsMap = extensions as ImmutableSortedDictionary - ?? ImmutableSortedDictionary.Create(TypeFullNameComparer.Instance) - .AddRange(extensions); + _extensionsMap = ImmutableSortedDictionary.Create(TypeFullNameComparer.Instance) + .AddRange(extensions.Select((p, i) => new KeyValuePair(p.Key, (p.Value, i)))); + } + + /// + /// 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] + protected DbContextOptions( + ImmutableSortedDictionary extensions) + { + Check.NotNull(extensions, nameof(extensions)); + + _extensionsMap = extensions; } /// /// Gets the extensions that store the configured options. /// public virtual IEnumerable Extensions - => ExtensionsMap.Values; + => _extensionsMap.Values.OrderBy(v => v.Ordinal).Select(v => v.Extension); /// /// Gets the extension of the specified type. Returns if no extension of the specified type is configured. @@ -51,7 +80,7 @@ public virtual IEnumerable Extensions /// The extension, or if none was found. public virtual TExtension? FindExtension() where TExtension : class, IDbContextOptionsExtension - => ExtensionsMap.TryGetValue(typeof(TExtension), out var extension) ? (TExtension)extension : null; + => _extensionsMap.TryGetValue(typeof(TExtension), out var value) ? (TExtension)value.Extension : null; /// /// Gets the extension of the specified type. Throws if no extension of the specified type is configured. @@ -80,12 +109,14 @@ public virtual TExtension GetExtension() public abstract DbContextOptions WithExtension(TExtension extension) where TExtension : class, IDbContextOptionsExtension; - private readonly ImmutableSortedDictionary _extensionsMap; - /// - /// Gets the extensions that store the configured options. + /// 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. /// - protected virtual IImmutableDictionary ExtensionsMap + [EntityFrameworkInternal] + protected virtual ImmutableSortedDictionary ExtensionsMap => _extensionsMap; /// @@ -121,7 +152,8 @@ public override bool Equals(object? obj) protected virtual bool Equals(DbContextOptions other) => _extensionsMap.Count == other._extensionsMap.Count && _extensionsMap.Zip(other._extensionsMap) - .All(p => p.First.Value.Info.ShouldUseSameServiceProvider(p.Second.Value.Info)); + .All(p => p.First.Value.Ordinal == p.Second.Value.Ordinal + && p.First.Value.Extension.Info.ShouldUseSameServiceProvider(p.Second.Value.Extension.Info)); /// public override int GetHashCode() @@ -131,7 +163,7 @@ public override int GetHashCode() foreach (var dbContextOptionsExtension in _extensionsMap) { hashCode.Add(dbContextOptionsExtension.Key); - hashCode.Add(dbContextOptionsExtension.Value.Info.GetServiceProviderHashCode()); + hashCode.Add(dbContextOptionsExtension.Value.Extension.Info.GetServiceProviderHashCode()); } return hashCode.ToHashCode(); diff --git a/src/EFCore/DbContextOptions`.cs b/src/EFCore/DbContextOptions`.cs index 07759d3bf9a..e0053a0bc9e 100644 --- a/src/EFCore/DbContextOptions`.cs +++ b/src/EFCore/DbContextOptions`.cs @@ -28,7 +28,6 @@ public class DbContextOptions : DbContextOptions /// to create instances of this class and it is not designed to be directly constructed in your application code. /// public DbContextOptions() - : this(ImmutableSortedDictionary.Create(TypeFullNameComparer.Instance)) { } @@ -44,12 +43,25 @@ public DbContextOptions( { } + private DbContextOptions( + ImmutableSortedDictionary extensions) + : base(extensions) + { + } + /// public override DbContextOptions WithExtension(TExtension extension) { Check.NotNull(extension, nameof(extension)); - return new DbContextOptions(ExtensionsMap.SetItem(extension.GetType(), extension)); + var type = extension.GetType(); + var ordinal = ExtensionsMap.Count; + if (ExtensionsMap.TryGetValue(type, out var existingValue)) + { + ordinal = existingValue.Ordinal; + } + + return new DbContextOptions(ExtensionsMap.SetItem(type, (extension, ordinal))); } /// diff --git a/test/EFCore.Specification.Tests/LoggingTestBase.cs b/test/EFCore.Specification.Tests/LoggingTestBase.cs index 11915e94154..dba0543d0b1 100644 --- a/test/EFCore.Specification.Tests/LoggingTestBase.cs +++ b/test/EFCore.Specification.Tests/LoggingTestBase.cs @@ -26,7 +26,7 @@ public void Logs_context_initialization_default_options() public void Logs_context_initialization_no_tracking() { Assert.Equal( - ExpectedMessage(DefaultOptions + "NoTracking"), + ExpectedMessage("NoTracking " + DefaultOptions), ActualMessage(s => CreateOptionsBuilder(s).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking))); } @@ -34,7 +34,7 @@ public void Logs_context_initialization_no_tracking() public void Logs_context_initialization_sensitive_data_logging() { Assert.Equal( - ExpectedMessage(DefaultOptions + "SensitiveDataLoggingEnabled"), + ExpectedMessage("SensitiveDataLoggingEnabled " + DefaultOptions), ActualMessage(s => CreateOptionsBuilder(s).EnableSensitiveDataLogging())); } diff --git a/test/EFCore.Tests/ServiceProviderCacheTest.cs b/test/EFCore.Tests/ServiceProviderCacheTest.cs index 2d7c1bfe56c..c1e7e6a290f 100644 --- a/test/EFCore.Tests/ServiceProviderCacheTest.cs +++ b/test/EFCore.Tests/ServiceProviderCacheTest.cs @@ -65,6 +65,39 @@ public void Returns_different_provider_for_different_type_of_configured_extensio loggerFactory.Log[1].Message); } + [ConditionalFact] + public void Returns_different_provider_for_extensions_configured_in_different_order() + { + var loggerFactory = new ListLoggerFactory(); + + var config1Log = new List(); + var config1Builder = new DbContextOptionsBuilder(); + ((IDbContextOptionsBuilderInfrastructure)config1Builder) + .AddOrUpdateExtension(new FakeDbContextOptionsExtension1(config1Log)); + ((IDbContextOptionsBuilderInfrastructure)config1Builder) + .AddOrUpdateExtension(new FakeDbContextOptionsExtension2(config1Log)); + config1Builder.UseLoggerFactory(loggerFactory); + config1Builder.UseInMemoryDatabase(Guid.NewGuid().ToString()); + + var config2Log = new List(); + var config2Builder = new DbContextOptionsBuilder(); + ((IDbContextOptionsBuilderInfrastructure)config2Builder) + .AddOrUpdateExtension(new FakeDbContextOptionsExtension2(config2Log)); + ((IDbContextOptionsBuilderInfrastructure)config2Builder) + .AddOrUpdateExtension(new FakeDbContextOptionsExtension1(config2Log)); + config2Builder.UseLoggerFactory(loggerFactory); + config2Builder.UseInMemoryDatabase(Guid.NewGuid().ToString()); + + var cache = new ServiceProviderCache(); + + Assert.NotSame(cache.GetOrAdd(config1Builder.Options, true), cache.GetOrAdd(config2Builder.Options, true)); + + Assert.Equal(2, loggerFactory.Log.Count); + + Assert.Equal(new[] { nameof(FakeDbContextOptionsExtension1), nameof(FakeDbContextOptionsExtension2) }, config1Log); + Assert.Equal(new[] { nameof(FakeDbContextOptionsExtension2), nameof(FakeDbContextOptionsExtension1) }, config2Log); + } + [ConditionalFact] public void Returns_same_provider_for_same_type_of_configured_extensions_and_replaced_service_types() { @@ -226,14 +259,26 @@ private static DbContextOptions CreateOptions(ILoggerFactory loggerF private class FakeDbContextOptionsExtension1 : IDbContextOptionsExtension { private DbContextOptionsExtensionInfo _info; + private readonly List _log; public string Something { get; set; } public DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this); + public FakeDbContextOptionsExtension1() + : this(new List()) + { + } + + public FakeDbContextOptionsExtension1(List log) + { + _log = log; + } + public virtual void ApplyServices(IServiceCollection services) { + _log.Add(GetType().ShortDisplayName()); } public virtual void Validate(IDbContextOptions options) @@ -269,12 +314,24 @@ public override void PopulateDebugInfo(IDictionary debugInfo) private class FakeDbContextOptionsExtension2 : IDbContextOptionsExtension { private DbContextOptionsExtensionInfo _info; + private readonly List _log; public DbContextOptionsExtensionInfo Info => _info ??= new ExtensionInfo(this); + public FakeDbContextOptionsExtension2() + : this(new List()) + { + } + + public FakeDbContextOptionsExtension2(List log) + { + _log = log; + } + public virtual void ApplyServices(IServiceCollection services) { + _log.Add(GetType().ShortDisplayName()); } public virtual void Validate(IDbContextOptions options) From 1c74909ce6d36e3a436b0f11322f598136672260 Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Mon, 20 Sep 2021 14:45:10 -0700 Subject: [PATCH 175/346] Microsoft.Data.Sqlite: Also try the .NET 5+ ApplicationData API Fixes #24213 --- .../Utilities/ApplicationDataHelper.cs | 1 + .../Utilities/BundleInitializer.cs | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.Sqlite.Core/Utilities/ApplicationDataHelper.cs b/src/Microsoft.Data.Sqlite.Core/Utilities/ApplicationDataHelper.cs index 0e6e824110a..2f58adb011b 100644 --- a/src/Microsoft.Data.Sqlite.Core/Utilities/ApplicationDataHelper.cs +++ b/src/Microsoft.Data.Sqlite.Core/Utilities/ApplicationDataHelper.cs @@ -26,6 +26,7 @@ public static string? LocalFolderPath try { return Type.GetType("Windows.Storage.ApplicationData, Windows, ContentType=WindowsRuntime") + ?? Type.GetType("Windows.Storage.ApplicationData, Microsoft.Windows.SDK.NET") ?.GetRuntimeProperty("Current")!.GetValue(null); } catch diff --git a/src/Microsoft.Data.Sqlite.Core/Utilities/BundleInitializer.cs b/src/Microsoft.Data.Sqlite.Core/Utilities/BundleInitializer.cs index 399ebb4edb9..d9d7001a353 100644 --- a/src/Microsoft.Data.Sqlite.Core/Utilities/BundleInitializer.cs +++ b/src/Microsoft.Data.Sqlite.Core/Utilities/BundleInitializer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; using System.Reflection; using static SQLitePCL.raw; @@ -34,12 +35,12 @@ public static void Initialize() var rc = sqlite3_win32_set_directory( SQLITE_WIN32_DATA_DIRECTORY_TYPE, ApplicationDataHelper.LocalFolderPath); - SqliteException.ThrowExceptionForRC(rc, db: null); + Debug.Assert(rc == SQLITE_OK); rc = sqlite3_win32_set_directory( SQLITE_WIN32_TEMP_DIRECTORY_TYPE, ApplicationDataHelper.TemporaryFolderPath); - SqliteException.ThrowExceptionForRC(rc, db: null); + Debug.Assert(rc == SQLITE_OK); } } } From 43f379f7f909cbf3fe6c43886aa988b178c6f4be Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Wed, 22 Sep 2021 11:29:30 -0700 Subject: [PATCH 176/346] Improve exception message for a shadow skip navigation Fixes #23362 --- src/EFCore/Infrastructure/ModelValidator.cs | 10 ++++++++ .../Builders/CollectionNavigationBuilder`.cs | 9 ++++++++ src/EFCore/Properties/CoreStrings.Designer.cs | 16 +++++++++---- src/EFCore/Properties/CoreStrings.resx | 5 +++- .../ModelBuilding/ManyToManyTestBase.cs | 23 +++++++++++++++++++ ...delBuilderGenericRelationshipStringTest.cs | 6 +++++ 6 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index e8b7eccba1f..7d852de2869 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -130,6 +130,16 @@ protected virtual void ValidateRelationships( CoreStrings.SkipNavigationNoInverse( skipNavigation.Name, skipNavigation.DeclaringEntityType.DisplayName())); } + + if (skipNavigation.IsShadowProperty()) + { + throw new InvalidOperationException( + CoreStrings.ShadowManyToManyNavigation( + skipNavigation.DeclaringEntityType.DisplayName(), + skipNavigation.Name, + skipNavigation.Inverse.DeclaringEntityType.DisplayName(), + skipNavigation.Inverse.Name)); + } } } } diff --git a/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs b/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs index 5e473fb4ab5..2e4043be2a2 100644 --- a/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs +++ b/src/EFCore/Metadata/Builders/CollectionNavigationBuilder`.cs @@ -95,6 +95,15 @@ public virtual ReferenceCollectionBuilder WithOne( /// An object to further configure the relationship. public new virtual CollectionCollectionBuilder WithMany(string navigationName) { + if (Builder != null + && Builder.Metadata.PrincipalToDependent == null) + { + throw new InvalidOperationException( + CoreStrings.MissingInverseManyToManyNavigation( + Builder.Metadata.PrincipalEntityType.DisplayName(), + Builder.Metadata.DeclaringEntityType.DisplayName())); + } + var leftName = Builder?.Metadata.PrincipalToDependent!.Name; var collectionCollectionBuilder = new CollectionCollectionBuilder( diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index c7234d5386f..6f039555697 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -352,7 +352,7 @@ public static string ClashingNonOwnedDerivedEntityType(object? entityType, objec entityType, derivedType); /// - /// The entity type '{entityType}' cannot be configured as owned because it has already been configured as a non-owned. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. See https://aka.ms/efcore-docs-owned for more information. + /// The entity type '{entityType}' cannot be configured as owned because it has already been configured as a non-owned. If you want to override previous configuration first remove the entity type from the model by calling 'Ignore'. See https://aka.ms/efcore-docs-owned for more information. /// public static string ClashingNonOwnedEntityType(object? entityType) => string.Format( @@ -1546,11 +1546,11 @@ public static string LiteralGenerationNotSupported(object? type) type); /// - /// The navigation '{entityType}.{navigation}' cannot be used for both sides of a many-to-many relationship. Many-to-many relationships must use different navigation properties for either end of the relationship. + /// The navigation '{entityType}.{navigation}' cannot be used for both sides of a many-to-many relationship. Many-to-many relationships must use two distinct navigation properties. /// public static string ManyToManyOneNav(object? entityType, object? navigation) => string.Format( - GetString("ManyToManyOneNav", "entityType", "navigation"), + GetString("ManyToManyOneNav", nameof(entityType), nameof(navigation)), entityType, navigation); /// @@ -1562,7 +1562,7 @@ public static string MissingBackingField(object? field, object? property, object field, property, entityType); /// - /// Unable to set up a many-to-many relationship between the entity types '{principalEntityType}' and '{declaringEntityType}' because one of the navigations was not specified. Provide a navigation in the 'HasMany' call in 'OnModelCreating'. + /// Unable to set up a many-to-many relationship between the entity types '{principalEntityType}' and '{declaringEntityType}' because one of the navigations was not specified. Provide a navigation in the 'HasMany' call in 'OnModelCreating'. Consider adding a private property for this. /// public static string MissingInverseManyToManyNavigation(object? principalEntityType, object? declaringEntityType) => string.Format( @@ -2603,6 +2603,14 @@ public static string ShadowEntity(object? entityType) GetString("ShadowEntity", nameof(entityType)), entityType); + /// + /// Unable to set up a many-to-many relationship between '{leftEntityType}.{leftNavigation}' and '{rightEntityType}.{rightNavigation}' because one or both of the navigations don't have a corresponding CLR property. Consider adding a corresponding private property to the entity CLR type. + /// + public static string ShadowManyToManyNavigation(object? leftEntityType, object? leftNavigation, object? rightEntityType, object? rightNavigation) + => string.Format( + GetString("ShadowManyToManyNavigation", nameof(leftEntityType), nameof(leftNavigation), nameof(rightEntityType), nameof(rightNavigation)), + leftEntityType, leftNavigation, rightEntityType, rightNavigation); + /// /// The shared-type entity type '{entityType}' cannot have a base type. /// diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index d5573b70723..bdc146ee962 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -1025,7 +1025,7 @@ The specified field '{field}' could not be found for property '{2_entityType}.{1_property}'. - Unable to set up a many-to-many relationship between the entity types '{principalEntityType}' and '{declaringEntityType}' because one of the navigations was not specified. Provide a navigation in the 'HasMany' call in 'OnModelCreating'. + Unable to set up a many-to-many relationship between the entity types '{principalEntityType}' and '{declaringEntityType}' because one of the navigations was not specified. Provide a navigation in the 'HasMany' call in 'OnModelCreating'. Consider adding a private property for this. Runtime metadata changes are not allowed when the model hasn't been marked as read-only. @@ -1437,6 +1437,9 @@ The entity type '{entityType}' is in shadow state. A valid model requires all entity types to have a corresponding CLR type. Obsolete + + Unable to set up a many-to-many relationship between '{leftEntityType}.{leftNavigation}' and '{rightEntityType}.{rightNavigation}' because one or both of the navigations don't have a corresponding CLR property. Consider adding a corresponding private property to the entity CLR type. + The shared-type entity type '{entityType}' cannot have a base type. diff --git a/test/EFCore.Tests/ModelBuilding/ManyToManyTestBase.cs b/test/EFCore.Tests/ModelBuilding/ManyToManyTestBase.cs index b1597475458..6ffd57cafdc 100644 --- a/test/EFCore.Tests/ModelBuilding/ManyToManyTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/ManyToManyTestBase.cs @@ -467,6 +467,29 @@ public virtual void Throws_for_many_to_many_with_only_one_navigation_configured( .WithMany(d => d.ManyToManyPrincipals)).Message); } + [ConditionalFact] + public virtual void Throws_for_many_to_many_with_a_shadow_navigation() + { + var modelBuilder = CreateModelBuilder(); + + modelBuilder.Ignore(); + modelBuilder.Ignore(); + modelBuilder.Entity().Ignore(d => d.ManyToManyPrincipals); + + modelBuilder.Entity() + .HasMany(d => d.Dependents) + .WithMany("Shadow"); + + Assert.Equal( + CoreStrings.ShadowManyToManyNavigation( + nameof(NavDependent), + "Shadow", + nameof(ManyToManyNavPrincipal), + nameof(ManyToManyNavPrincipal.Dependents)), + Assert.Throws( + () => modelBuilder.FinalizeModel()).Message); + } + [ConditionalFact] public virtual void Throws_for_self_ref_with_same_navigation() { diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipStringTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipStringTest.cs index 87d09250734..f417c6a83f1 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipStringTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipStringTest.cs @@ -28,6 +28,12 @@ protected override TestModelBuilder CreateTestModelBuilder(TestHelpers testHelpe => new GenericStringTestModelBuilder(testHelpers, configure); } + public class GenericManyToManyString : ManyToManyTestBase + { + protected override TestModelBuilder CreateTestModelBuilder(TestHelpers testHelpers, Action? configure) + => new GenericStringTestModelBuilder(testHelpers, configure); + } + public class GenericOneToOneString : OneToOneTestBase { protected override TestModelBuilder CreateTestModelBuilder(TestHelpers testHelpers, Action? configure) From e0dbe5ae4e0eac1af2ca4928084db9d73bea4a7c Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 22 Sep 2021 21:46:07 +0300 Subject: [PATCH 177/346] Fix snapshot generation with HiLo (#26136) Fixes #26134 --- .../SqlServerAnnotationCodeGenerator.cs | 6 ++- .../Migrations/ModelSnapshotSqlServerTest.cs | 40 +++++++++++++++++++ .../SqlServerAnnotationCodeGeneratorTest.cs | 5 +++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs index 4b2d1734034..a34ec2eb1e1 100644 --- a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs +++ b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs @@ -64,6 +64,10 @@ private static readonly MethodInfo _propertyUseIdentityColumnsMethodInfo = typeof(SqlServerPropertyBuilderExtensions).GetRequiredRuntimeMethod( nameof(SqlServerPropertyBuilderExtensions.UseIdentityColumn), typeof(PropertyBuilder), typeof(long), typeof(int)); + private static readonly MethodInfo _propertyUseHiLoMethodInfo + = typeof(SqlServerPropertyBuilderExtensions).GetRequiredRuntimeMethod( + nameof(SqlServerPropertyBuilderExtensions.UseHiLo), typeof(PropertyBuilder), typeof(string), typeof(string)); + private static readonly MethodInfo _indexIsClusteredMethodInfo = typeof(SqlServerIndexBuilderExtensions).GetRequiredRuntimeMethod( nameof(SqlServerIndexBuilderExtensions.IsClustered), typeof(IndexBuilder), typeof(bool)); @@ -374,7 +378,7 @@ protected override bool IsHandledByConvention(IModel model, IAnnotation annotati var name = GetAndRemove(annotations, SqlServerAnnotationNames.HiLoSequenceName); var schema = GetAndRemove(annotations, SqlServerAnnotationNames.HiLoSequenceSchema); return new( - _modelUseHiLoMethodInfo, + onModel ? _modelUseHiLoMethodInfo : _propertyUseHiLoMethodInfo, (name, schema) switch { (null, null) => Array.Empty(), diff --git a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs index 326217e2319..df48756c696 100644 --- a/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs +++ b/test/EFCore.Design.Tests/Migrations/ModelSnapshotSqlServerTest.cs @@ -309,6 +309,46 @@ public virtual void Model_annotations_are_stored_in_snapshot() }); } + [ConditionalFact] + public virtual void Model_Fluent_APIs_are_properly_generated() + { + Test( + builder => + { + builder.UseHiLo(); + builder.Entity(); + builder.Ignore(); + }, + AddBoilerPlate( + @" + modelBuilder.HasAnnotation(""Relational:MaxIdentifierLength"", 128); + + SqlServerModelBuilderExtensions.UseHiLo(modelBuilder, ""EntityFrameworkHiLoSequence""); + + modelBuilder.HasSequence(""EntityFrameworkHiLoSequence"") + .IncrementsBy(10); + + modelBuilder.Entity(""Microsoft.EntityFrameworkCore.Migrations.ModelSnapshotSqlServerTest+EntityWithOneProperty"", b => + { + b.Property(""Id"") + .ValueGeneratedOnAdd() + .HasColumnType(""int""); + + SqlServerPropertyBuilderExtensions.UseHiLo(b.Property(""Id"")); + + b.HasKey(""Id""); + + b.ToTable(""EntityWithOneProperty""); + });"), + o => + { + Assert.Equal(SqlServerValueGenerationStrategy.SequenceHiLo, o.GetValueGenerationStrategy()); + Assert.Equal( + SqlServerValueGenerationStrategy.SequenceHiLo, + o.GetEntityTypes().Single().GetProperty("Id").GetValueGenerationStrategy()); + }); + } + [ConditionalFact] public virtual void Model_default_schema_annotation_is_stored_in_snapshot_as_fluent_api() { diff --git a/test/EFCore.SqlServer.Tests/Design/Internal/SqlServerAnnotationCodeGeneratorTest.cs b/test/EFCore.SqlServer.Tests/Design/Internal/SqlServerAnnotationCodeGeneratorTest.cs index a9254179ed5..80a4d039abc 100644 --- a/test/EFCore.SqlServer.Tests/Design/Internal/SqlServerAnnotationCodeGeneratorTest.cs +++ b/test/EFCore.SqlServer.Tests/Design/Internal/SqlServerAnnotationCodeGeneratorTest.cs @@ -169,6 +169,7 @@ public void GenerateFluentApi_IModel_works_with_identity() var result = generator.GenerateFluentApiCalls((IModel)modelBuilder.Model, annotations).Single(); Assert.Equal("UseIdentityColumns", result.Method); + Assert.Equal("SqlServerModelBuilderExtensions", result.DeclaringType); Assert.Collection( result.Arguments, @@ -188,6 +189,7 @@ public void GenerateFluentApi_IProperty_works_with_identity() var result = generator.GenerateFluentApiCalls((IProperty)property, annotations).Single(); Assert.Equal("UseIdentityColumn", result.Method); + Assert.Equal("SqlServerPropertyBuilderExtensions", result.DeclaringType); Assert.Collection( result.Arguments, @@ -207,6 +209,7 @@ public void GenerateFluentApi_IProperty_works_with_identity_default_seed_increme var result = generator.GenerateFluentApiCalls((IProperty)property, annotations).Single(); Assert.Equal("UseIdentityColumn", result.Method); + Assert.Equal("SqlServerPropertyBuilderExtensions", result.DeclaringType); Assert.Collection( result.Arguments, @@ -225,6 +228,7 @@ public void GenerateFluentApi_IModel_works_with_HiLo() var result = generator.GenerateFluentApiCalls((IModel)modelBuilder.Model, annotations).Single(); Assert.Equal("UseHiLo", result.Method); + Assert.Equal("SqlServerModelBuilderExtensions", result.DeclaringType); Assert.Collection( result.Arguments, @@ -244,6 +248,7 @@ public void GenerateFluentApi_IProperty_works_with_HiLo() var result = generator.GenerateFluentApiCalls((IProperty)property, annotations).Single(); Assert.Equal("UseHiLo", result.Method); + Assert.Equal("SqlServerPropertyBuilderExtensions", result.DeclaringType); Assert.Collection( result.Arguments, From 8f531d42d3b96c7762ec3b18388466cfd8f8f3fc Mon Sep 17 00:00:00 2001 From: DotNet Bot Date: Wed, 22 Sep 2021 21:34:56 +0000 Subject: [PATCH 178/346] [internal/release/3.1] Update dependencies from dnceng/internal/dotnet-extensions - Coherency Updates: - Microsoft.NETCore.App.Internal: from 3.1.20-servicing.21470.22 to 3.1.20-servicing.21471.1 (parent: Microsoft.Extensions.Logging) --- NuGet.config | 9 ++- eng/Version.Details.xml | 144 ++++++++++++++++++++-------------------- eng/Versions.props | 4 +- 3 files changed, 80 insertions(+), 77 deletions(-) diff --git a/NuGet.config b/NuGet.config index de6f64bc8de..6611dfcd037 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,10 +4,11 @@ - + + - + @@ -22,12 +23,14 @@ - + + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c785f41f3b1..0d92a8cf955 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,21 +1,21 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-corefx @@ -33,85 +33,85 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 3acd9b0cd16596bad450c82be08780875a73c05c - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e @@ -124,149 +124,149 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e - + https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-extensions - e22d8efb08e7e07c353e5eb6b2dac381e90e0239 + 513f727d177a19d28871458dcbc261f18761d37e https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 0900090e30756addbd3f545d69db659deb06c3b2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-core-setup 0900090e30756addbd3f545d69db659deb06c3b2 diff --git a/eng/Versions.props b/eng/Versions.props index 2dfa01e30da..ca7262552d3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 3.1.20 3.1.20 3.1.20 - 3.1.20-servicing.21470.9 + 3.1.20-servicing.21472.3 3.1.20 @@ -56,7 +56,7 @@ 3.1.6 3.1.0 3.1.20 - 3.1.20-servicing.21470.22 + 3.1.20-servicing.21471.1 2.1.0 From 2a9ffbbd6a7be38cef5dcfebc90ce21928690223 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Wed, 22 Sep 2021 16:12:56 -0700 Subject: [PATCH 179/346] Allow HasKey to override HasNoKey Fixes #24789 --- src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs | 5 +---- .../Metadata/Internal/InternalEntityTypeBuilderTest.cs | 5 +---- test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs | 3 ++- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs index a1220fdc53a..2253ef053b6 100644 --- a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs @@ -226,10 +226,7 @@ public virtual bool CanSetPrimaryKey( return null; } - if (Metadata.GetIsKeylessConfigurationSource() != ConfigurationSource.Explicit) - { - Metadata.SetIsKeyless(false, configurationSource.Value); - } + Metadata.SetIsKeyless(false, configurationSource.Value); var containingForeignKeys = actualProperties .SelectMany(p => p.GetContainingForeignKeys().Where(k => k.DeclaringEntityType != Metadata)) diff --git a/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs b/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs index d633ae4af57..c51191360ec 100644 --- a/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs +++ b/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs @@ -1332,10 +1332,7 @@ public void HasKey_can_override_lower_or_equal_source_HasNoKey() Assert.Equal(ConfigurationSource.Explicit, entityType.GetIsKeylessConfigurationSource()); Assert.Empty(entityType.GetKeys()); - Assert.Equal( - CoreStrings.KeylessTypeWithKey("{'CustomerId'}", nameof(Order)), - Assert.Throws( - () => entityBuilder.HasKey(new[] { Order.CustomerIdProperty.Name }, ConfigurationSource.Explicit)).Message); + Assert.NotNull(entityBuilder.HasKey(new[] { Order.CustomerIdProperty.Name }, ConfigurationSource.Explicit)); } [ConditionalFact] diff --git a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs index dc4a56c94d6..7ce85a89d5e 100644 --- a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs @@ -125,13 +125,14 @@ public virtual void Can_set_entity_key_from_property_name_when_no_clr_property() } [ConditionalFact] - public virtual void Can_set_entity_key_from_clr_property_when_property_ignored() + public virtual void Can_set_entity_key_from_clr_property_when_property_ignored_on_keyless() { var modelBuilder = CreateModelBuilder(); modelBuilder.Entity( b => { + b.HasNoKey(); b.Ignore(Customer.IdProperty.Name); b.HasKey(e => e.Id); }); From 2e2f4392225b00a881d7120a6173a8ccd0f01684 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 23 Sep 2021 00:38:40 +0000 Subject: [PATCH 180/346] Update dependencies from https://github.com/dotnet/runtime build 20210922.13 (#26151) [release/6.0] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 44 ++++++++++++++++++++--------------------- eng/Versions.props | 22 ++++++++++----------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c320ea80e5a..35242719b5f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,49 +1,49 @@ - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a - + https://github.com/dotnet/runtime - 036cb862a4e99b1fa035f654debad7091646fbe4 + 491ed9a112559872c31ae40da8f6d9977ba4ce3a diff --git a/eng/Versions.props b/eng/Versions.props index bd00b878571..2e5aa1c947b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -14,17 +14,17 @@ False - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 - 6.0.0-rtm.21471.19 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 + 6.0.0-rtm.21472.13 3.7.0 From af389b2d192dd8bc910cd583de2a46caaeaa90f6 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Wed, 22 Sep 2021 23:46:33 -0700 Subject: [PATCH 181/346] Throw a better exception for relationships to keyless entity types Fixes #24373 --- .../Internal/InternalEntityTypeBuilder.cs | 12 ++++++++---- .../Internal/InternalForeignKeyBuilder.cs | 15 +++++++++++++++ .../DataAnnotationTestBase.cs | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs index 2253ef053b6..39e04b67b61 100644 --- a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs @@ -2828,13 +2828,18 @@ private static InternalIndexBuilder DetachIndex(Index indexToDetach) Metadata, null, navigationToTarget, !setTargetAsPrincipal, configurationSource, required); } + if (setTargetAsPrincipal == null + && targetEntityType.IsKeyless) + { + setTargetAsPrincipal = false; + } + if (configurationSource == ConfigurationSource.Explicit && setTargetAsPrincipal.HasValue) { if (setTargetAsPrincipal.Value) { - if (targetEntityType.IsKeyless - && targetEntityType.GetIsKeylessConfigurationSource() == ConfigurationSource.Explicit) + if (targetEntityType.IsKeyless) { throw new InvalidOperationException(CoreStrings.PrincipalKeylessType( targetEntityType.DisplayName(), @@ -2850,8 +2855,7 @@ private static InternalIndexBuilder DetachIndex(Index indexToDetach) } else { - if (Metadata.IsKeyless - && Metadata.GetIsKeylessConfigurationSource() == ConfigurationSource.Explicit) + if (Metadata.IsKeyless) { throw new InvalidOperationException(CoreStrings.PrincipalKeylessType( Metadata.DisplayName(), diff --git a/src/EFCore/Metadata/Internal/InternalForeignKeyBuilder.cs b/src/EFCore/Metadata/Internal/InternalForeignKeyBuilder.cs index d4d409d435a..94c2fd2419e 100644 --- a/src/EFCore/Metadata/Internal/InternalForeignKeyBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalForeignKeyBuilder.cs @@ -2274,6 +2274,21 @@ private bool CanSetPrincipalKey( Check.NotNull(principalEntityTypeBuilder, nameof(principalEntityTypeBuilder)); Check.NotNull(dependentEntityTypeBuilder, nameof(dependentEntityTypeBuilder)); + if (configurationSource == ConfigurationSource.Explicit + && principalEntityTypeBuilder.Metadata.IsKeyless) + { + throw new InvalidOperationException(CoreStrings.PrincipalKeylessType( + principalEntityTypeBuilder.Metadata.DisplayName(), + principalEntityTypeBuilder.Metadata.DisplayName() + + (navigationToDependent?.Name == null + ? "" + : "." + navigationToDependent.Value.Name), + dependentEntityTypeBuilder.Metadata.DisplayName() + + (navigationToPrincipal?.Name == null + ? "" + : "." + navigationToPrincipal.Value.Name))); + } + Check.DebugAssert( navigationToPrincipal?.Name == null || navigationToPrincipal.Value.MemberInfo != null diff --git a/test/EFCore.Specification.Tests/DataAnnotationTestBase.cs b/test/EFCore.Specification.Tests/DataAnnotationTestBase.cs index bb74dc589fc..47a595d67fc 100644 --- a/test/EFCore.Specification.Tests/DataAnnotationTestBase.cs +++ b/test/EFCore.Specification.Tests/DataAnnotationTestBase.cs @@ -816,6 +816,21 @@ public virtual void Key_fluent_api_and_keyless_attribute_do_not_cause_warning() Assert.Empty(Fixture.ListLoggerFactory.Log); } + [ConditionalFact] + public virtual void Fluent_API_relationship_throws_for_Keyless_attribute() + { + var modelBuilder = CreateModelBuilder(); + var entity = modelBuilder.Entity(); + + Assert.Equal(CoreStrings.PrincipalKeylessType( + nameof(KeyFluentApiAndKeylessAttribute), nameof(KeyFluentApiAndKeylessAttribute), nameof(CompositeKeyAttribute)), + Assert.Throws(() => + modelBuilder.Entity() + .HasOne() + .WithOne() + .HasForeignKey("fk")).Message); + } + private class CompositeKeyAttribute { [Key] From 23767aa9650b6c959bb4116717f054a2ccf4b16d Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Wed, 22 Sep 2021 23:47:17 -0700 Subject: [PATCH 182/346] Set ValueGenerated.OnUpdateSometimes when more than two properties share the same colum Fixes #25388 --- .../Conventions/SharedTableConvention.cs | 6 +- .../SqlServerModelBuilderGenericTest.cs | 57 ++++++++++++++----- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs b/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs index 793639c3e63..b6bab1be5c0 100644 --- a/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs @@ -215,8 +215,10 @@ private static void TryUniquifyColumnNames( { if (property.GetAfterSaveBehavior() == PropertySaveBehavior.Save && otherProperty.GetAfterSaveBehavior() == PropertySaveBehavior.Save - && property.ValueGenerated == ValueGenerated.Never - && otherProperty.ValueGenerated == ValueGenerated.Never) + && (property.ValueGenerated == ValueGenerated.Never + || property.ValueGenerated == ValueGenerated.OnUpdateSometimes) + && (otherProperty.ValueGenerated == ValueGenerated.Never + || otherProperty.ValueGenerated == ValueGenerated.OnUpdateSometimes)) { // Handle this with a default value convention #9329 property.Builder.ValueGenerated(ValueGenerated.OnUpdateSometimes); diff --git a/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs b/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs index 2d7812e620d..c53b5400060 100644 --- a/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs +++ b/test/EFCore.SqlServer.Tests/ModelBuilding/SqlServerModelBuilderGenericTest.cs @@ -510,15 +510,25 @@ public class SqlServerGenericOwnedTypes : GenericOwnedTypes public virtual void Owned_types_use_table_splitting_by_default() { var modelBuilder = CreateModelBuilder(); - var model = modelBuilder.Model; - modelBuilder.Entity().OwnsOne(b => b.AlternateLabel) - .Ignore(l => l.Book) - .OwnsOne(l => l.AnotherBookLabel) - .Ignore(l => l.Book) - .OwnsOne(s => s.SpecialBookLabel) - .Ignore(l => l.Book) - .Ignore(l => l.BookLabel); + modelBuilder.Entity().OwnsOne(b => b.AlternateLabel, + b => + { + b.Ignore(l => l.Book); + b.OwnsOne(l => l.AnotherBookLabel, + ab => + { + ab.Property(l => l.BookId).HasColumnName("BookId2"); + ab.Ignore(l => l.Book); + ab.OwnsOne(s => s.SpecialBookLabel, + s => + { + s.Property(l => l.BookId).HasColumnName("BookId2"); + s.Ignore(l => l.Book); + s.Ignore(l => l.BookLabel); + }); + }); + }); modelBuilder.Entity().OwnsOne(b => b.Label) .Ignore(l => l.Book) @@ -534,12 +544,25 @@ public virtual void Owned_types_use_table_splitting_by_default() .Ignore(l => l.Book) .Ignore(l => l.BookLabel); - modelBuilder.Entity().OwnsOne(b => b.AlternateLabel) - .OwnsOne(l => l.SpecialBookLabel) - .Ignore(l => l.Book) - .OwnsOne(s => s.AnotherBookLabel) - .Ignore(l => l.Book); + modelBuilder.Entity().OwnsOne(b => b.AlternateLabel, + b => + { + b.Ignore(l => l.Book); + b.OwnsOne(l => l.SpecialBookLabel, + ab => + { + ab.Property(l => l.BookId).HasColumnName("BookId2"); + ab.Ignore(l => l.Book); + ab.OwnsOne(s => s.AnotherBookLabel, + s => + { + s.Property(l => l.BookId).HasColumnName("BookId2"); + s.Ignore(l => l.Book); + }); + }); + }); + IModel model = (IModel)modelBuilder.Model; var book = model.FindEntityType(typeof(Book)); var bookOwnership1 = book.FindNavigation(nameof(Book.Label)).ForeignKey; var bookOwnership2 = book.FindNavigation(nameof(Book.AlternateLabel)).ForeignKey; @@ -580,7 +603,7 @@ public virtual void Owned_types_use_table_splitting_by_default() modelBuilder.Entity().OwnsOne(b => b.Label).ToTable("Label"); modelBuilder.Entity().OwnsOne(b => b.AlternateLabel).ToTable("AlternateLabel"); - modelBuilder.FinalizeModel(); + model = modelBuilder.FinalizeModel(); Assert.Equal( nameof(BookLabel.Id), @@ -590,6 +613,12 @@ public virtual void Owned_types_use_table_splitting_by_default() nameof(BookLabel.AnotherBookLabel) + "_" + nameof(BookLabel.Id), bookLabel2Ownership1.DeclaringEntityType.FindProperty(nameof(BookLabel.Id)) .GetColumnName(StoreObjectIdentifier.Table("AlternateLabel", null))); + + var alternateTable = model.GetRelationalModel().FindTable("AlternateLabel", null); + var bookId = alternateTable.FindColumn("BookId2"); + + Assert.Equal(4, bookId.PropertyMappings.Count()); + Assert.All(bookId.PropertyMappings, m => Assert.Equal(ValueGenerated.OnUpdateSometimes, m.Property.ValueGenerated)); } [ConditionalFact] From 5e382f17f00cf11e2b90193035bf259567a78470 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Thu, 23 Sep 2021 15:55:57 +0100 Subject: [PATCH 183/346] [6.0] Code cleanup on EFCore project (#26100) --- All.sln.DotSettings | 70 ++++- src/EFCore/ChangeTracking/ChangeTracker.cs | 16 +- src/EFCore/ChangeTracking/CollectionEntry.cs | 2 +- src/EFCore/ChangeTracking/EntityEntry.cs | 14 +- .../ChangeTracking/EntityEntryGraphNode.cs | 1 - .../ChangeTracking/GeometryValueComparer.cs | 2 +- .../IEntityEntryGraphIterator.cs | 2 +- .../CompositePrincipalKeyValueFactory.cs | 1 + .../Internal/CompositeValueFactory.cs | 3 +- .../ChangeTracking/Internal/DependentsMap.cs | 1 - .../Internal/EntityGraphAttacher.cs | 2 +- .../Internal/EntityReferenceMap.cs | 13 +- .../Internal/EntryPropertyValues.cs | 3 +- .../Internal/IdentityMapFactoryFactory.cs | 4 +- .../Internal/InternalEntityEntry.cs | 10 +- .../ChangeTracking/Internal/KeyPropagator.cs | 4 +- .../Internal/NavigationFixer.cs | 43 +-- .../Internal/RelationshipsSnapshot.cs | 2 +- ...leFullyNullableDependentKeyValueFactory.cs | 1 - ...mpleNonNullableDependentKeyValueFactory.cs | 1 - ...llablePrincipalDependentKeyValueFactory.cs | 1 - .../SimplePrincipalKeyValueFactory.cs | 3 +- .../ChangeTracking/Internal/Snapshot.cs | 80 +++--- .../Internal/SnapshotFactoryFactory.cs | 4 +- .../ChangeTracking/Internal/StateManager.cs | 10 +- .../Internal/ValueGenerationManager.cs | 6 +- src/EFCore/ChangeTracking/NavigationEntry.cs | 2 +- src/EFCore/ChangeTracking/PropertyValues.cs | 3 +- src/EFCore/ChangeTracking/ReferenceEntry.cs | 2 +- src/EFCore/ChangeTracking/ValueComparer.cs | 13 +- src/EFCore/ChangeTracking/ValueComparer`.cs | 2 +- src/EFCore/DbContext.cs | 10 +- src/EFCore/DbContextOptions.cs | 5 +- src/EFCore/DbContextOptionsBuilder.cs | 18 +- src/EFCore/DbContextOptionsBuilder`.cs | 2 +- src/EFCore/DbContextOptions`.cs | 5 +- src/EFCore/DbSet.cs | 8 +- .../EntityFrameworkDesignServicesBuilder.cs | 5 +- src/EFCore/Design/ICSharpHelper.cs | 6 +- ...untimeAnnotationCodeGeneratorParameters.cs | 2 +- .../Diagnostics/CollectionChangedEventData.cs | 3 +- src/EFCore/Diagnostics/CoreEventId.cs | 3 +- .../Diagnostics/CoreLoggerExtensions.cs | 17 +- src/EFCore/Diagnostics/EntityTypeEventData.cs | 1 - .../Diagnostics/ISaveChangesInterceptor.cs | 6 +- .../Diagnostics/PropertyChangedEventData.cs | 3 +- .../Diagnostics/PropertyValueEventData.cs | 3 +- .../Diagnostics/ReferenceChangedEventData.cs | 3 +- .../Diagnostics/SaveChangesInterceptor.cs | 6 +- .../SkipCollectionChangedEventData.cs | 3 +- .../Diagnostics/WarningsConfiguration.cs | 2 +- src/EFCore/EF.cs | 4 +- .../ConventionEntityTypeExtensions.cs | 4 +- .../EntityFrameworkQueryableExtensions.cs | 176 ++++++------ ...ityFrameworkServiceCollectionExtensions.cs | 21 +- src/EFCore/Extensions/EntityTypeExtensions.cs | 8 +- .../Internal/ExpressionExtensions.cs | 4 +- .../Extensions/Internal/TypeExtensions.cs | 13 +- src/EFCore/Infrastructure/AnnotatableBase.cs | 14 +- .../Infrastructure/AnnotatableBuilder.cs | 6 +- src/EFCore/Infrastructure/DatabaseFacade.cs | 14 +- .../DbContextOptionsExtensionInfo.cs | 2 +- .../EntityFrameworkEventSource.cs | 45 +-- .../EntityFrameworkServicesBuilder.cs | 12 +- .../Infrastructure/ExpressionExtensions.cs | 3 +- .../IModelRuntimeInitializer.cs | 4 +- .../Infrastructure/IReadOnlyAnnotatable.cs | 2 +- .../Infrastructure/IResettableService.cs | 2 +- .../Infrastructure/IndentedStringBuilder.cs | 2 +- .../Internal/ConcurrencyDetector.cs | 1 - .../Internal/CurrentDbContext.cs | 1 - .../Infrastructure/ModelRuntimeInitializer.cs | 18 +- src/EFCore/Infrastructure/ModelSource.cs | 3 +- src/EFCore/Infrastructure/ModelValidator.cs | 19 +- src/EFCore/Internal/DbContextServices.cs | 4 +- src/EFCore/Internal/EntityFinder.cs | 8 +- src/EFCore/Internal/IDbContextDependencies.cs | 1 - src/EFCore/Internal/InternalDbSet.cs | 11 +- src/EFCore/Internal/ServiceProviderCache.cs | 3 +- .../Builders/CollectionCollectionBuilder.cs | 19 +- .../Builders/CollectionCollectionBuilder`.cs | 19 +- .../IConventionPropertyBaseBuilder.cs | 1 - .../Builders/IConventionPropertyBuilder.cs | 8 +- .../IConventionSkipNavigationBuilder.cs | 4 +- src/EFCore/Metadata/Builders/IndexBuilder.cs | 2 +- .../Builders/OwnedNavigationBuilder.cs | 5 +- .../Builders/OwnedNavigationBuilder`.cs | 3 +- .../PropertiesConfigurationBuilder.cs | 12 +- .../PropertiesConfigurationBuilder`.cs | 12 +- .../Metadata/Builders/PropertyBuilder.cs | 22 +- .../Metadata/Builders/PropertyBuilder`.cs | 20 +- .../Builders/ReferenceCollectionBuilder`.cs | 2 +- .../Builders/ReferenceNavigationBuilder`.cs | 2 +- .../TypeMappingConfigurationBuilder.cs | 4 +- .../TypeMappingConfigurationBuilder`.cs | 4 +- .../BaseTypeDiscoveryConvention.cs | 5 +- .../Metadata/Conventions/ConventionSet.cs | 2 +- .../DerivedTypeDiscoveryConvention.cs | 12 +- ...figurationEntityTypeAttributeConvention.cs | 17 +- .../ForeignKeyAttributeConvention.cs | 12 +- .../ForeignKeyPropertyDiscoveryConvention.cs | 6 +- .../IForeignKeyNullNavigationSetConvention.cs | 6 +- .../InversePropertyAttributeConvention.cs | 15 +- .../ManyToManyJoinEntityTypeConvention.cs | 17 +- .../NavigationAttributeConventionBase.cs | 2 +- .../NotMappedMemberAttributeConvention.cs | 2 +- .../PropertyDiscoveryConvention.cs | 1 - .../QueryFilterRewritingConvention.cs | 9 +- .../RelationshipDiscoveryConvention.cs | 64 +++-- .../RequiredNavigationAttributeConvention.cs | 1 - .../Conventions/RuntimeModelConvention.cs | 101 ++++--- .../Conventions/ValueGenerationConvention.cs | 2 +- src/EFCore/Metadata/FactoryMethodBinding.cs | 4 +- src/EFCore/Metadata/IConventionEntityType.cs | 11 +- src/EFCore/Metadata/IConventionModel.cs | 5 +- src/EFCore/Metadata/IConventionProperty.cs | 4 +- .../Metadata/IConventionPropertyBase.cs | 1 - src/EFCore/Metadata/IConventionTypeBase.cs | 3 +- src/EFCore/Metadata/IEntityType.cs | 9 +- src/EFCore/Metadata/IModel.cs | 4 +- src/EFCore/Metadata/IMutableEntityType.cs | 5 +- src/EFCore/Metadata/IMutableProperty.cs | 4 +- src/EFCore/Metadata/IMutablePropertyBase.cs | 1 - src/EFCore/Metadata/IPropertyBase.cs | 2 +- src/EFCore/Metadata/IReadOnlyEntityType.cs | 18 +- src/EFCore/Metadata/IReadOnlyModel.cs | 8 +- .../Metadata/IReadOnlyNavigationBase.cs | 3 +- src/EFCore/Metadata/IReadOnlyPropertyBase.cs | 3 +- src/EFCore/Metadata/IReadOnlyTypeBase.cs | 14 +- .../Internal/ClrPropertySetterFactory.cs | 2 +- .../Metadata/Internal/DesignTimeModel.cs | 3 +- src/EFCore/Metadata/Internal/EntityType.cs | 169 +++++++----- .../Metadata/Internal/EntityTypeExtensions.cs | 5 +- src/EFCore/Metadata/Internal/ForeignKey.cs | 13 +- .../Metadata/Internal/ForeignKeyExtensions.cs | 6 +- src/EFCore/Metadata/Internal/Index.cs | 40 ++- .../Internal/InternalEntityTypeBuilder.cs | 253 +++++++++-------- .../Internal/InternalForeignKeyBuilder.cs | 101 +++---- .../Metadata/Internal/InternalModelBuilder.cs | 7 +- .../Internal/InternalPropertyBuilder.cs | 48 ++-- .../Internal/InternalSkipNavigationBuilder.cs | 3 +- src/EFCore/Metadata/Internal/Key.cs | 42 +-- .../Metadata/Internal/MemberClassifier.cs | 28 +- src/EFCore/Metadata/Internal/Model.cs | 60 ++-- .../Metadata/Internal/ModelConfiguration.cs | 39 ++- src/EFCore/Metadata/Internal/Navigation.cs | 31 ++- .../Metadata/Internal/NavigationExtensions.cs | 4 +- .../Metadata/Internal/PropertiesSnapshot.cs | 4 +- src/EFCore/Metadata/Internal/Property.cs | 98 ++++--- .../Internal/PropertyAccessorsFactory.cs | 2 +- src/EFCore/Metadata/Internal/PropertyBase.cs | 73 ++--- .../Internal/PropertyConfiguration.cs | 1 + .../Metadata/Internal/PropertyListComparer.cs | 3 +- .../Metadata/Internal/RelationshipSnapshot.cs | 3 +- .../Metadata/Internal/ServiceProperty.cs | 30 +- .../Metadata/Internal/SkipNavigation.cs | 18 +- .../Internal/SkipNavigationExtensions.cs | 4 +- src/EFCore/Metadata/Internal/TypeBase.cs | 15 +- src/EFCore/Metadata/MemberIdentity.cs | 6 +- .../Metadata/ObjectArrayParameterBinding.cs | 16 +- src/EFCore/Metadata/RuntimeEntityType.cs | 257 +++++++++--------- src/EFCore/Metadata/RuntimeForeignKey.cs | 40 +-- src/EFCore/Metadata/RuntimeIndex.cs | 37 +-- src/EFCore/Metadata/RuntimeKey.cs | 32 +-- src/EFCore/Metadata/RuntimeModel.cs | 56 ++-- src/EFCore/Metadata/RuntimeNavigation.cs | 14 +- src/EFCore/Metadata/RuntimeProperty.cs | 90 +++--- src/EFCore/Metadata/RuntimePropertyBase.cs | 37 +-- src/EFCore/Metadata/RuntimeServiceProperty.cs | 16 +- src/EFCore/Metadata/RuntimeSkipNavigation.cs | 18 +- .../RuntimeTypeMappingConfiguration.cs | 24 +- .../Metadata/ServiceParameterBinding.cs | 20 +- src/EFCore/ModelBuilder.cs | 3 +- src/EFCore/ModelConfigurationBuilder.cs | 21 +- ...piledQueryCacheKeyGeneratorDependencies.cs | 1 - src/EFCore/Query/EntityShaperExpression.cs | 9 +- .../Query/EvaluatableExpressionFilter.cs | 5 +- src/EFCore/Query/ExpressionPrinter.cs | 6 +- ...INavigationExpansionExtensibilityHelper.cs | 6 +- .../Query/Internal/CompiledQueryBase.cs | 10 +- .../Internal/EntityMaterializerSource.cs | 20 +- ...ingExpressionVisitor.ExpressionVisitors.cs | 36 ++- ...nExpandingExpressionVisitor.Expressions.cs | 16 +- .../NavigationExpandingExpressionVisitor.cs | 73 +++-- .../NullCheckRemovingExpressionVisitor.cs | 2 +- .../QueryOptimizingExpressionVisitor.cs | 31 ++- ...yableMethodNormalizingExpressionVisitor.cs | 6 +- ...SubqueryMemberPushdownExpressionVisitor.cs | 62 ++--- .../NavigationExpansionExtensibilityHelper.cs | 6 +- src/EFCore/Query/QueryCompilationContext.cs | 7 +- .../QueryCompilationContextDependencies.cs | 7 +- src/EFCore/Query/QueryContext.cs | 14 +- src/EFCore/Query/QueryContextDependencies.cs | 1 - src/EFCore/Query/QueryRootExpression.cs | 4 +- .../Query/QueryTranslationPreprocessor.cs | 10 +- ...yableMethodTranslatingExpressionVisitor.cs | 7 +- src/EFCore/Query/QueryableMethods.cs | 179 +++++++----- .../ShapedQueryCompilingExpressionVisitor.cs | 2 +- src/EFCore/Storage/CoreTypeMapping.cs | 6 +- src/EFCore/Storage/Database.cs | 2 +- src/EFCore/Storage/ExecutionStrategy.cs | 20 +- .../Storage/ExecutionStrategyExtensions.cs | 132 ++++----- src/EFCore/Storage/IDatabase.cs | 2 +- src/EFCore/Storage/IDatabaseCreator.cs | 6 +- src/EFCore/Storage/IDbContextTransaction.cs | 14 +- .../Storage/IDbContextTransactionManager.cs | 6 +- src/EFCore/Storage/IExecutionStrategy.cs | 2 +- .../Storage/ITransactionEnlistmentManager.cs | 3 +- .../Internal/DatabaseFacadeDependencies.cs | 1 - .../Internal/ExecutionStrategyFactory.cs | 3 +- .../Storage/NonRetryingExecutionStrategy.cs | 2 +- src/EFCore/Storage/TypeMappingSource.cs | 83 +++--- .../DateTimeOffsetToBinaryConverter.cs | 2 +- .../IPAddressToStringConverter.cs | 2 +- .../Internal/StringCharConverter.cs | 2 +- .../Internal/StringDateTimeConverter.cs | 2 +- .../Internal/StringDateTimeOffsetConverter.cs | 2 +- .../Internal/StringEnumConverter.cs | 2 +- .../Internal/StringGuidConverter.cs | 2 +- .../Internal/StringNumberConverter.cs | 2 +- .../Internal/StringTimeSpanConverter.cs | 2 +- .../Internal/StringUriConverter.cs | 2 +- .../PhysicalAddressToStringConverter.cs | 2 +- .../StringToNumberConverter.cs | 1 + .../ValueConversion/ValueConverterSelector.cs | 22 +- src/EFCore/Update/Internal/UpdateAdapter.cs | 3 +- src/EFCore/Update/UpdateEntryExtensions.cs | 32 +-- .../ValueGeneration/HiLoValueGenerator.cs | 4 +- .../HiLoValueGeneratorState.cs | 5 +- src/EFCore/ValueGeneration/ValueGenerator.cs | 4 +- .../ValueGeneration/ValueGeneratorSelector.cs | 1 - src/EFCore/ValueGeneration/ValueGenerator`.cs | 4 +- src/Shared/Check.cs | 8 +- src/Shared/EnumerableMethods.cs | 165 +++++++---- src/Shared/Multigraph.cs | 14 +- src/Shared/NonCapturingLazyInitializer.cs | 3 +- src/Shared/SharedTypeExtensions.cs | 11 +- 237 files changed, 2375 insertions(+), 1867 deletions(-) diff --git a/All.sln.DotSettings b/All.sln.DotSettings index ce72e4db697..cc0f9910226 100644 --- a/All.sln.DotSettings +++ b/All.sln.DotSettings @@ -32,7 +32,74 @@ WARNING True - <?xml version="1.0" encoding="utf-16"?><Profile name="EntityFramework"><HtmlReformatCode>True</HtmlReformatCode><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSUseVar><BehavourStyle>CAN_CHANGE_TO_IMPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_IMPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_IMPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><XMLReformatCode>True</XMLReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSharpFormatDocComments>True</CSharpFormatDocComments><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="True" ArrangeArgumentsStyle="False" /></Profile> + <?xml version="1.0" encoding="utf-16"?><Profile name="EntityFramework"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSUseVar><BehavourStyle>CAN_CHANGE_TO_IMPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_IMPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_IMPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><XMLReformatCode>True</XMLReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSharpFormatDocComments>True</CSharpFormatDocComments><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="True" ArrangeArgumentsStyle="False" /><IDEA_SETTINGS>&lt;profile version="1.0"&gt; + &lt;option name="myName" value="EntityFramework" /&gt; + &lt;inspection_tool class="ES6ShorthandObjectProperty" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="JSArrowFunctionBracesCanBeRemoved" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="JSPrimitiveTypeWrapperUsage" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="JSRemoveUnnecessaryParentheses" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="JSUnnecessarySemicolon" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="TypeScriptExplicitMemberType" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryContinueJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryLabelJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryLabelOnBreakStatementJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryLabelOnContinueStatementJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="UnnecessaryReturnJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; + &lt;inspection_tool class="WrongPropertyKeyValueDelimiter" enabled="false" level="WEAK WARNING" enabled_by_default="false" /&gt; +&lt;/profile&gt;</IDEA_SETTINGS><RIDER_SETTINGS>&lt;profile&gt; + &lt;Language id="CSS"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;Rearrange&gt;false&lt;/Rearrange&gt; + &lt;/Language&gt; + &lt;Language id="EditorConfig"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="HTML"&gt; + &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;Rearrange&gt;false&lt;/Rearrange&gt; + &lt;/Language&gt; + &lt;Language id="HTTP Request"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="Handlebars"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="Ini"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="JSON"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="Jade"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="JavaScript"&gt; + &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;Rearrange&gt;false&lt;/Rearrange&gt; + &lt;/Language&gt; + &lt;Language id="Markdown"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="Properties"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="RELAX-NG"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="SQL"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;/Language&gt; + &lt;Language id="XML"&gt; + &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;Rearrange&gt;false&lt;/Rearrange&gt; + &lt;/Language&gt; + &lt;Language id="yaml"&gt; + &lt;Reformat&gt;false&lt;/Reformat&gt; + &lt;/Language&gt; +&lt;/profile&gt;</RIDER_SETTINGS></Profile> EntityFramework EntityFramework @@ -75,6 +142,7 @@ 2 NEVER False + ALWAYS NEVER NEVER False diff --git a/src/EFCore/ChangeTracking/ChangeTracker.cs b/src/EFCore/ChangeTracking/ChangeTracker.cs index ed70c049c9f..725d39f74b4 100644 --- a/src/EFCore/ChangeTracking/ChangeTracker.cs +++ b/src/EFCore/ChangeTracking/ChangeTracker.cs @@ -279,16 +279,16 @@ public virtual void TrackGraph( rootEntity, callback, n => - { - if (n.Entry.State != EntityState.Detached) { - return false; - } + if (n.Entry.State != EntityState.Detached) + { + return false; + } - n.NodeState!(n); + n.NodeState!(n); - return n.Entry.State != EntityState.Detached; - }); + return n.Entry.State != EntityState.Detached; + }); /// /// @@ -457,7 +457,7 @@ public virtual void Clear() public virtual DebugView DebugView => new( () => this.ToDebugString(ChangeTrackerDebugStringOptions.ShortDefault), - () => this.ToDebugString(ChangeTrackerDebugStringOptions.LongDefault)); + () => this.ToDebugString()); #region Hidden System.Object members diff --git a/src/EFCore/ChangeTracking/CollectionEntry.cs b/src/EFCore/ChangeTracking/CollectionEntry.cs index d716ea534b6..411f476bd36 100644 --- a/src/EFCore/ChangeTracking/CollectionEntry.cs +++ b/src/EFCore/ChangeTracking/CollectionEntry.cs @@ -248,7 +248,7 @@ public override void Load() /// /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous save operation. - /// If the is canceled. + /// If the is canceled. public override Task LoadAsync(CancellationToken cancellationToken = default) { EnsureInitialized(); diff --git a/src/EFCore/ChangeTracking/EntityEntry.cs b/src/EFCore/ChangeTracking/EntityEntry.cs index 2e553d46139..bc78e0ecc84 100644 --- a/src/EFCore/ChangeTracking/EntityEntry.cs +++ b/src/EFCore/ChangeTracking/EntityEntry.cs @@ -162,7 +162,7 @@ public virtual MemberEntry Member(string propertyName) if (navigation != null) { return navigation.IsCollection - ? (MemberEntry)new CollectionEntry(InternalEntry, propertyName) + ? new CollectionEntry(InternalEntry, propertyName) : new ReferenceEntry(InternalEntry, propertyName); } @@ -201,7 +201,7 @@ public virtual NavigationEntry Navigation(string propertyName) if (navigation != null) { return navigation.IsCollection - ? (NavigationEntry)new CollectionEntry(InternalEntry, propertyName) + ? new CollectionEntry(InternalEntry, propertyName) : new ReferenceEntry(InternalEntry, propertyName); } @@ -399,7 +399,7 @@ public virtual PropertyValues OriginalValues /// /// /// Queries the database for copies of the values of the tracked entity as they currently - /// exist in the database. If the entity is not found in the database, then is returned. + /// exist in the database. If the entity is not found in the database, then is returned. /// /// /// Note that changing the values in the returned dictionary will not update the values @@ -409,7 +409,7 @@ public virtual PropertyValues OriginalValues /// /// See Accessing tracked entities in EF Core for more information. /// - /// The store values, or if the entity does not exist in the database. + /// The store values, or if the entity does not exist in the database. public virtual PropertyValues? GetDatabaseValues() { var values = Finder.GetDatabaseValues(InternalEntry); @@ -439,7 +439,7 @@ public virtual PropertyValues OriginalValues /// A task that represents the asynchronous operation. The task result contains the store values, /// or if the entity does not exist in the database. /// - /// If the is canceled. + /// If the is canceled. public virtual async Task GetDatabaseValuesAsync(CancellationToken cancellationToken = default) { var values = await Finder.GetDatabaseValuesAsync(InternalEntry, cancellationToken).ConfigureAwait(false); @@ -482,7 +482,7 @@ public virtual void Reload() /// /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. - /// If the is canceled. + /// If the is canceled. public virtual async Task ReloadAsync(CancellationToken cancellationToken = default) => Reload(await GetDatabaseValuesAsync(cancellationToken).ConfigureAwait(false)); @@ -530,7 +530,7 @@ public override string ToString() public virtual DebugView DebugView => new( () => InternalEntry.ToDebugString(ChangeTrackerDebugStringOptions.ShortDefault), - () => InternalEntry.ToDebugString(ChangeTrackerDebugStringOptions.LongDefault)); + () => InternalEntry.ToDebugString()); #region Hidden System.Object members diff --git a/src/EFCore/ChangeTracking/EntityEntryGraphNode.cs b/src/EFCore/ChangeTracking/EntityEntryGraphNode.cs index fa513a1ce36..69547e90f8d 100644 --- a/src/EFCore/ChangeTracking/EntityEntryGraphNode.cs +++ b/src/EFCore/ChangeTracking/EntityEntryGraphNode.cs @@ -7,7 +7,6 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Utilities; - namespace Microsoft.EntityFrameworkCore.ChangeTracking { /// diff --git a/src/EFCore/ChangeTracking/GeometryValueComparer.cs b/src/EFCore/ChangeTracking/GeometryValueComparer.cs index 924714897da..371914e9bcd 100644 --- a/src/EFCore/ChangeTracking/GeometryValueComparer.cs +++ b/src/EFCore/ChangeTracking/GeometryValueComparer.cs @@ -52,7 +52,7 @@ public GeometryValueComparer() Expression.IsFalse(yNull), Expression.Call( x, - typeof(TGeometry).GetRequiredRuntimeMethod("EqualsExact", new[] { typeof(TGeometry) }), + typeof(TGeometry).GetRequiredRuntimeMethod("EqualsExact", typeof(TGeometry)), y))))), left, right); diff --git a/src/EFCore/ChangeTracking/IEntityEntryGraphIterator.cs b/src/EFCore/ChangeTracking/IEntityEntryGraphIterator.cs index 228432bd5c5..e548da6df69 100644 --- a/src/EFCore/ChangeTracking/IEntityEntryGraphIterator.cs +++ b/src/EFCore/ChangeTracking/IEntityEntryGraphIterator.cs @@ -41,7 +41,7 @@ void TraverseGraph( /// A to observe while waiting for the task to complete. /// The type of the state object. /// A task that represents the asynchronous operation. - /// If the is canceled. + /// If the is canceled. Task TraverseGraphAsync( EntityEntryGraphNode node, Func, CancellationToken, Task> handleNode, diff --git a/src/EFCore/ChangeTracking/Internal/CompositePrincipalKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/CompositePrincipalKeyValueFactory.cs index f938ef59447..accf0b19bb8 100644 --- a/src/EFCore/ChangeTracking/Internal/CompositePrincipalKeyValueFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/CompositePrincipalKeyValueFactory.cs @@ -117,6 +117,7 @@ private object[] CreateFromEntry( { return default!; } + values[index++] = value; } diff --git a/src/EFCore/ChangeTracking/Internal/CompositeValueFactory.cs b/src/EFCore/ChangeTracking/Internal/CompositeValueFactory.cs index 9a107689918..918d00bdaaf 100644 --- a/src/EFCore/ChangeTracking/Internal/CompositeValueFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/CompositeValueFactory.cs @@ -10,7 +10,6 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Update; - namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal { /// @@ -153,7 +152,7 @@ protected static IEqualityComparer CreateEqualityComparer(IReadOnlyLis return comparers.All(c => c != null) ? new CompositeCustomComparer(comparers!) : properties.Any(p => typeof(IStructuralEquatable).IsAssignableFrom(p.ClrType)) - ? (IEqualityComparer)new StructuralCompositeComparer() + ? new StructuralCompositeComparer() : new CompositeComparer(); } diff --git a/src/EFCore/ChangeTracking/Internal/DependentsMap.cs b/src/EFCore/ChangeTracking/Internal/DependentsMap.cs index 084ee408f0c..f810bc2252f 100644 --- a/src/EFCore/ChangeTracking/Internal/DependentsMap.cs +++ b/src/EFCore/ChangeTracking/Internal/DependentsMap.cs @@ -7,7 +7,6 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Update; - namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal { /// diff --git a/src/EFCore/ChangeTracking/Internal/EntityGraphAttacher.cs b/src/EFCore/ChangeTracking/Internal/EntityGraphAttacher.cs index b52caacce51..d2303c1cf1d 100644 --- a/src/EFCore/ChangeTracking/Internal/EntityGraphAttacher.cs +++ b/src/EFCore/ChangeTracking/Internal/EntityGraphAttacher.cs @@ -150,7 +150,7 @@ await internalEntityEntry.SetEntityStateAsync( ? (isGenerated ? storeGenTargetState : targetState) : EntityState.Added, // Key can only be not-set if it is store-generated acceptChanges: true, - forceStateWhenUnknownKey: force ? (EntityState?)targetState : null, + forceStateWhenUnknownKey: force ? targetState : null, cancellationToken: cancellationToken) .ConfigureAwait(false); diff --git a/src/EFCore/ChangeTracking/Internal/EntityReferenceMap.cs b/src/EFCore/ChangeTracking/Internal/EntityReferenceMap.cs index 0e6e5dba116..102b4e54973 100644 --- a/src/EFCore/ChangeTracking/Internal/EntityReferenceMap.cs +++ b/src/EFCore/ChangeTracking/Internal/EntityReferenceMap.cs @@ -10,7 +10,6 @@ using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; - namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal { /// @@ -178,7 +177,11 @@ public virtual bool TryGet( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual int GetCountForState( - bool added, bool modified, bool deleted, bool unchanged, bool countDeletedSharedIdentity) + bool added, + bool modified, + bool deleted, + bool unchanged, + bool countDeletedSharedIdentity) { var count = 0; @@ -226,7 +229,11 @@ public virtual int GetCountForState( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual IEnumerable GetEntriesForState( - bool added, bool modified, bool deleted, bool unchanged, bool returnDeletedSharedIdentity) + bool added, + bool modified, + bool deleted, + bool unchanged, + bool returnDeletedSharedIdentity) { // Perf sensitive diff --git a/src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs b/src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs index 3746d0702ca..58d2ad4daf8 100644 --- a/src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs +++ b/src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs @@ -113,7 +113,8 @@ public override void SetValues(PropertyValues propertyValues) /// public override IReadOnlyList Properties { - [DebuggerStepThrough] get => _properties ??= EntityType.GetProperties().ToList(); + [DebuggerStepThrough] + get => _properties ??= EntityType.GetProperties().ToList(); } /// diff --git a/src/EFCore/ChangeTracking/Internal/IdentityMapFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/IdentityMapFactoryFactory.cs index 0321e9b1291..17cb83c2ca6 100644 --- a/src/EFCore/ChangeTracking/Internal/IdentityMapFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/IdentityMapFactoryFactory.cs @@ -35,8 +35,8 @@ private static Func CreateFactory(IKey key) var factory = key.GetPrincipalKeyValueFactory(); return typeof(TKey).IsNullableType() - ? (Func)(sensitiveLoggingEnabled => - new NullableKeyIdentityMap(key, factory, sensitiveLoggingEnabled)) + ? sensitiveLoggingEnabled => + new NullableKeyIdentityMap(key, factory, sensitiveLoggingEnabled) : sensitiveLoggingEnabled => new IdentityMap(key, factory, sensitiveLoggingEnabled); } } diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index 4abf0c7f8fa..815a782cdd2 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; @@ -681,7 +680,7 @@ private CurrentValueType GetValueType( return CurrentValueType.Normal; } - @equals ??= ValuesEqualFunc(property); + equals ??= ValuesEqualFunc(property); var defaultValue = property.ClrType.GetDefaultValue(); var value = ReadPropertyValue(property); if (!equals(value, defaultValue)) @@ -1030,7 +1029,7 @@ public void SetOriginalValue( // If setting the original value results in the current value being different from the // original value, then mark the property as modified. if ((EntityState == EntityState.Unchanged - || (EntityState == EntityState.Modified && !IsModified(property))) + || (EntityState == EntityState.Modified && !IsModified(property))) && !_stateData.IsPropertyFlagged(property.GetIndex(), PropertyFlag.Unknown)) { ((StateManager as StateManager)?.ChangeDetector as ChangeDetector)?.DetectValueChange(this, property); @@ -1352,6 +1351,7 @@ private void SetProperty( { SetOriginalValue(propertyBase, value); } + _stateData.FlagProperty(propertyIndex, PropertyFlag.Unknown, isFlagged: false); } } @@ -1377,7 +1377,7 @@ private void SetProperty( /// public void HandleNullForeignKey( IProperty property, - bool setModified = false, + bool setModified = false, bool isCascadeDelete = false) { if (EntityState != EntityState.Deleted @@ -1946,7 +1946,7 @@ public override string ToString() public DebugView DebugView => new( () => this.ToDebugString(ChangeTrackerDebugStringOptions.ShortDefault), - () => this.ToDebugString(ChangeTrackerDebugStringOptions.LongDefault)); + () => this.ToDebugString()); IUpdateEntry? IUpdateEntry.SharedIdentityEntry => SharedIdentityEntry; diff --git a/src/EFCore/ChangeTracking/Internal/KeyPropagator.cs b/src/EFCore/ChangeTracking/Internal/KeyPropagator.cs index 489cab1fd64..67414c2d9b9 100644 --- a/src/EFCore/ChangeTracking/Internal/KeyPropagator.cs +++ b/src/EFCore/ChangeTracking/Internal/KeyPropagator.cs @@ -64,7 +64,7 @@ public KeyPropagator( generationProperty == property ? entry.EntityType : generationProperty?.DeclaringEntityType); - + if (valueGenerator != null) { var value = valueGenerator.Next(new EntityEntry(entry)); @@ -112,7 +112,7 @@ public KeyPropagator( generationProperty == property ? entry.EntityType : generationProperty?.DeclaringEntityType); - + if (valueGenerator != null) { var value = await valueGenerator.NextAsync(new EntityEntry(entry), cancellationToken) diff --git a/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs b/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs index bb1d66c3f91..37271183dd1 100644 --- a/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs +++ b/src/EFCore/ChangeTracking/Internal/NavigationFixer.cs @@ -340,8 +340,8 @@ public virtual void NavigationCollectionChanged( if (navigationBase is ISkipNavigation skipNavigation) { - FindOrCreateJoinEntry(( - entry, newTargetEntry, skipNavigation, FromQuery: false, SetModified: true)); + FindOrCreateJoinEntry( + (entry, newTargetEntry, skipNavigation, FromQuery: false, SetModified: true)); Check.DebugAssert( skipNavigation.Inverse.IsCollection, @@ -757,7 +757,7 @@ private void InitialFixup( { var toDependent = foreignKey.PrincipalToDependent; if (CanOverrideCurrentValue(entry, toDependent, dependentEntry, fromQuery) - && !IsAmbiguous(dependentEntry)) + && !IsAmbiguous(dependentEntry)) { SetNavigation(entry, toDependent, dependentEntry, fromQuery); SetNavigation(dependentEntry, foreignKey.DependentToPrincipal, entry, fromQuery); @@ -917,10 +917,10 @@ private void InitialFixup( private static bool IsAmbiguous(InternalEntityEntry dependentEntry) => (dependentEntry.EntityState == EntityState.Detached - || dependentEntry.EntityState == EntityState.Deleted) + || dependentEntry.EntityState == EntityState.Deleted) && (dependentEntry.SharedIdentityEntry != null || dependentEntry.EntityType.HasSharedClrType - && dependentEntry.StateManager.TryGetEntry(dependentEntry.Entity, throwOnNonUniqueness: false) != dependentEntry); + && dependentEntry.StateManager.TryGetEntry(dependentEntry.Entity, throwOnNonUniqueness: false) != dependentEntry); private void DelayedFixup( InternalEntityEntry entry, @@ -990,16 +990,19 @@ private void FixupSkipNavigations(InternalEntityEntry entry, IForeignKey foreign private void FindOrCreateJoinEntry( (InternalEntityEntry Entry, - InternalEntityEntry OtherEntry, - ISkipNavigation SkipNavigation, - bool FromQuery, - bool SetModified) arguments) + InternalEntityEntry OtherEntry, + ISkipNavigation SkipNavigation, + bool FromQuery, + bool SetModified) arguments) { var joinEntry = FindJoinEntry(arguments.Entry, arguments.OtherEntry, arguments.SkipNavigation); if (joinEntry != null) { - SetForeignKeyProperties(joinEntry, arguments.Entry, arguments.SkipNavigation.ForeignKey, arguments.SetModified, arguments.FromQuery); - SetForeignKeyProperties(joinEntry, arguments.OtherEntry, arguments.SkipNavigation.Inverse.ForeignKey, arguments.SetModified, arguments.FromQuery); + SetForeignKeyProperties( + joinEntry, arguments.Entry, arguments.SkipNavigation.ForeignKey, arguments.SetModified, arguments.FromQuery); + SetForeignKeyProperties( + joinEntry, arguments.OtherEntry, arguments.SkipNavigation.Inverse.ForeignKey, arguments.SetModified, + arguments.FromQuery); } else if (!_inAttachGraph) { @@ -1009,8 +1012,11 @@ private void FindOrCreateJoinEntry( joinEntry = arguments.Entry.StateManager.GetOrCreateEntry(joinEntity, joinEntityType); - SetForeignKeyProperties(joinEntry, arguments.Entry, arguments.SkipNavigation.ForeignKey, arguments.SetModified, arguments.FromQuery); - SetForeignKeyProperties(joinEntry, arguments.OtherEntry, arguments.SkipNavigation.Inverse.ForeignKey, arguments.SetModified, arguments.FromQuery); + SetForeignKeyProperties( + joinEntry, arguments.Entry, arguments.SkipNavigation.ForeignKey, arguments.SetModified, arguments.FromQuery); + SetForeignKeyProperties( + joinEntry, arguments.OtherEntry, arguments.SkipNavigation.Inverse.ForeignKey, arguments.SetModified, + arguments.FromQuery); joinEntry.SetEntityState( arguments.SetModified @@ -1022,7 +1028,7 @@ private void FindOrCreateJoinEntry( else { _danglingJoinEntities ??= new List(); - + _danglingJoinEntities.Add(() => FindOrCreateJoinEntry(arguments)); } } @@ -1332,14 +1338,19 @@ private void ConditionallyNullForeignKeyProperties( break; case EntityState.Unchanged: case EntityState.Modified: - dependentEntry.SetEntityState(dependentEntry.SharedIdentityEntry != null ? EntityState.Detached : EntityState.Deleted); + dependentEntry.SetEntityState( + dependentEntry.SharedIdentityEntry != null ? EntityState.Detached : EntityState.Deleted); DeleteFixup(dependentEntry); break; } } } - private static bool CanOverrideCurrentValue(InternalEntityEntry entry, INavigationBase? navigation, InternalEntityEntry value, bool fromQuery) + private static bool CanOverrideCurrentValue( + InternalEntityEntry entry, + INavigationBase? navigation, + InternalEntityEntry value, + bool fromQuery) { if (fromQuery) { diff --git a/src/EFCore/ChangeTracking/Internal/RelationshipsSnapshot.cs b/src/EFCore/ChangeTracking/Internal/RelationshipsSnapshot.cs index fc56d8e1bd0..33cdd8ff5c9 100644 --- a/src/EFCore/ChangeTracking/Internal/RelationshipsSnapshot.cs +++ b/src/EFCore/ChangeTracking/Internal/RelationshipsSnapshot.cs @@ -41,7 +41,7 @@ public void SetValue(IPropertyBase propertyBase, object? value) Check.DebugAssert(!IsEmpty, "relationship snapshot is empty"); Check.DebugAssert( - propertyBase is not INavigation { IsCollection : true }, + propertyBase is not INavigation { IsCollection: true }, $"property {propertyBase} is is not reference navigation"); _values[propertyBase.GetRelationshipIndex()] = SnapshotValue(propertyBase, value); diff --git a/src/EFCore/ChangeTracking/Internal/SimpleFullyNullableDependentKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/SimpleFullyNullableDependentKeyValueFactory.cs index 0567dcb4fee..681abeba243 100644 --- a/src/EFCore/ChangeTracking/Internal/SimpleFullyNullableDependentKeyValueFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SimpleFullyNullableDependentKeyValueFactory.cs @@ -9,7 +9,6 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Update; - namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal { /// diff --git a/src/EFCore/ChangeTracking/Internal/SimpleNonNullableDependentKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/SimpleNonNullableDependentKeyValueFactory.cs index 3138698091f..592ad2a5130 100644 --- a/src/EFCore/ChangeTracking/Internal/SimpleNonNullableDependentKeyValueFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SimpleNonNullableDependentKeyValueFactory.cs @@ -9,7 +9,6 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Update; - namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal { /// diff --git a/src/EFCore/ChangeTracking/Internal/SimpleNullablePrincipalDependentKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/SimpleNullablePrincipalDependentKeyValueFactory.cs index b1a535e310f..f815cf36468 100644 --- a/src/EFCore/ChangeTracking/Internal/SimpleNullablePrincipalDependentKeyValueFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SimpleNullablePrincipalDependentKeyValueFactory.cs @@ -9,7 +9,6 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Update; - namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal { // The methods here box, but this is only used when the primary key is nullable, but the FK is non-nullable, diff --git a/src/EFCore/ChangeTracking/Internal/SimplePrincipalKeyValueFactory.cs b/src/EFCore/ChangeTracking/Internal/SimplePrincipalKeyValueFactory.cs index 839b54dd400..cc157b16e37 100644 --- a/src/EFCore/ChangeTracking/Internal/SimplePrincipalKeyValueFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SimplePrincipalKeyValueFactory.cs @@ -10,7 +10,6 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Update; - namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal { /// @@ -41,7 +40,7 @@ public SimplePrincipalKeyValueFactory(IProperty property) = comparer != null ? new NoNullsCustomEqualityComparer(comparer) : typeof(IStructuralEquatable).IsAssignableFrom(typeof(TKey)) - ? (IEqualityComparer)new NoNullsStructuralEqualityComparer() + ? new NoNullsStructuralEqualityComparer() : EqualityComparer.Default; } diff --git a/src/EFCore/ChangeTracking/Internal/Snapshot.cs b/src/EFCore/ChangeTracking/Internal/Snapshot.cs index f27cb1cf853..db3bed98721 100644 --- a/src/EFCore/ChangeTracking/Internal/Snapshot.cs +++ b/src/EFCore/ChangeTracking/Internal/Snapshot.cs @@ -89,39 +89,39 @@ public static Delegate[] CreateReaders() /// public static Type CreateSnapshotType(Type[] types) => types.Length switch - { - 1 => typeof(Snapshot<>).MakeGenericType(types), - 2 => typeof(Snapshot<,>).MakeGenericType(types), - 3 => typeof(Snapshot<,,>).MakeGenericType(types), - 4 => typeof(Snapshot<,,,>).MakeGenericType(types), - 5 => typeof(Snapshot<,,,,>).MakeGenericType(types), - 6 => typeof(Snapshot<,,,,,>).MakeGenericType(types), - 7 => typeof(Snapshot<,,,,,,>).MakeGenericType(types), - 8 => typeof(Snapshot<,,,,,,,>).MakeGenericType(types), - 9 => typeof(Snapshot<,,,,,,,,>).MakeGenericType(types), - 10 => typeof(Snapshot<,,,,,,,,,>).MakeGenericType(types), - 11 => typeof(Snapshot<,,,,,,,,,,>).MakeGenericType(types), - 12 => typeof(Snapshot<,,,,,,,,,,,>).MakeGenericType(types), - 13 => typeof(Snapshot<,,,,,,,,,,,,>).MakeGenericType(types), - 14 => typeof(Snapshot<,,,,,,,,,,,,,>).MakeGenericType(types), - 15 => typeof(Snapshot<,,,,,,,,,,,,,,>).MakeGenericType(types), - 16 => typeof(Snapshot<,,,,,,,,,,,,,,,>).MakeGenericType(types), - 17 => typeof(Snapshot<,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 18 => typeof(Snapshot<,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 19 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 20 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 21 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 22 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 23 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 24 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 25 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 26 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 27 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 28 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 29 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - 30 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), - _ => throw new IndexOutOfRangeException(), - }; + { + 1 => typeof(Snapshot<>).MakeGenericType(types), + 2 => typeof(Snapshot<,>).MakeGenericType(types), + 3 => typeof(Snapshot<,,>).MakeGenericType(types), + 4 => typeof(Snapshot<,,,>).MakeGenericType(types), + 5 => typeof(Snapshot<,,,,>).MakeGenericType(types), + 6 => typeof(Snapshot<,,,,,>).MakeGenericType(types), + 7 => typeof(Snapshot<,,,,,,>).MakeGenericType(types), + 8 => typeof(Snapshot<,,,,,,,>).MakeGenericType(types), + 9 => typeof(Snapshot<,,,,,,,,>).MakeGenericType(types), + 10 => typeof(Snapshot<,,,,,,,,,>).MakeGenericType(types), + 11 => typeof(Snapshot<,,,,,,,,,,>).MakeGenericType(types), + 12 => typeof(Snapshot<,,,,,,,,,,,>).MakeGenericType(types), + 13 => typeof(Snapshot<,,,,,,,,,,,,>).MakeGenericType(types), + 14 => typeof(Snapshot<,,,,,,,,,,,,,>).MakeGenericType(types), + 15 => typeof(Snapshot<,,,,,,,,,,,,,,>).MakeGenericType(types), + 16 => typeof(Snapshot<,,,,,,,,,,,,,,,>).MakeGenericType(types), + 17 => typeof(Snapshot<,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 18 => typeof(Snapshot<,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 19 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 20 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 21 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 22 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 23 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 24 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 25 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 26 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 27 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 28 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 29 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + 30 => typeof(Snapshot<,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>).MakeGenericType(types), + _ => throw new IndexOutOfRangeException(), + }; } /// @@ -5049,16 +5049,12 @@ public T GetValue(int index) /// public object? this[int index] { - get => index switch - { - 0 => _value0, - _ => throw new IndexOutOfRangeException(), - }; + get => index == 0 ? _value0 : throw new IndexOutOfRangeException(); set => _value0 = index switch - { - 0 => (T0)value!, - _ => throw new IndexOutOfRangeException(), - }; + { + 0 => (T0)value!, + _ => throw new IndexOutOfRangeException(), + }; } } } diff --git a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs index aca7852abfe..a39f65bb3d5 100644 --- a/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs +++ b/src/EFCore/ChangeTracking/Internal/SnapshotFactoryFactory.cs @@ -33,8 +33,8 @@ public virtual Func CreateEmpty(IEntityType entityType) return GetPropertyCount(entityType) == 0 ? (() => Snapshot.Empty) : Expression.Lambda>( - // TODO-Nullable: This whole code path is null unsafe. We are passing null parameter but later using parameter - // as if always exists. + // TODO-Nullable: This whole code path is null unsafe. We are passing null parameter but later using parameter + // as if always exists. CreateConstructorExpression(entityType, null!)) .Compile(); } diff --git a/src/EFCore/ChangeTracking/Internal/StateManager.cs b/src/EFCore/ChangeTracking/Internal/StateManager.cs index 9225ffa4668..948068ef400 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManager.cs @@ -82,6 +82,7 @@ public StateManager(StateManagerDependencies dependencies) UpdateLogger = dependencies.UpdateLogger; _changeTrackingLogger = dependencies.ChangeTrackingLogger; } + /// /// 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 @@ -731,7 +732,7 @@ public virtual void BeginAttachGraph() /// public virtual void CompleteAttachGraph() => Dependencies.NavigationFixer.CompleteAttachGraph(); - + /// /// 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 @@ -1175,9 +1176,10 @@ protected virtual async Task SaveChangesAsync( public virtual int SaveChanges(bool acceptAllChangesOnSuccess) => !Context.Database.AutoTransactionsEnabled ? SaveChanges(this, acceptAllChangesOnSuccess) - : Dependencies.ExecutionStrategy.Execute((StateManager: this, AcceptAllChangesOnSuccess: acceptAllChangesOnSuccess), - static (_, t) => SaveChanges(t.StateManager, t.AcceptAllChangesOnSuccess), - null); + : Dependencies.ExecutionStrategy.Execute( + (StateManager: this, AcceptAllChangesOnSuccess: acceptAllChangesOnSuccess), + static (_, t) => SaveChanges(t.StateManager, t.AcceptAllChangesOnSuccess), + null); private static int SaveChanges(StateManager stateManager, bool acceptAllChangesOnSuccess) { diff --git a/src/EFCore/ChangeTracking/Internal/ValueGenerationManager.cs b/src/EFCore/ChangeTracking/Internal/ValueGenerationManager.cs index 84d07c99394..168f90dbe4b 100644 --- a/src/EFCore/ChangeTracking/Internal/ValueGenerationManager.cs +++ b/src/EFCore/ChangeTracking/Internal/ValueGenerationManager.cs @@ -191,9 +191,9 @@ private static void SetGeneratedValue(InternalEntityEntry entry, IProperty prope } private static void MarkKeyUnknown( - InternalEntityEntry entry, - bool includePrimaryKey, - IProperty property, + InternalEntityEntry entry, + bool includePrimaryKey, + IProperty property, ValueGenerator valueGenerator) { if (includePrimaryKey diff --git a/src/EFCore/ChangeTracking/NavigationEntry.cs b/src/EFCore/ChangeTracking/NavigationEntry.cs index 831e236a85f..cbec6fae20f 100644 --- a/src/EFCore/ChangeTracking/NavigationEntry.cs +++ b/src/EFCore/ChangeTracking/NavigationEntry.cs @@ -127,7 +127,7 @@ private static INavigationBase GetNavigation(InternalEntityEntry internalEntry, /// /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. - /// If the is canceled. + /// If the is canceled. public abstract Task LoadAsync(CancellationToken cancellationToken = default); /// diff --git a/src/EFCore/ChangeTracking/PropertyValues.cs b/src/EFCore/ChangeTracking/PropertyValues.cs index 34d0b07d1d2..921dc7a8b94 100644 --- a/src/EFCore/ChangeTracking/PropertyValues.cs +++ b/src/EFCore/ChangeTracking/PropertyValues.cs @@ -143,7 +143,8 @@ public virtual void SetValues(IDictionary values) /// public virtual IEntityType EntityType { - [DebuggerStepThrough] get => InternalEntry.EntityType; + [DebuggerStepThrough] + get => InternalEntry.EntityType; } /// diff --git a/src/EFCore/ChangeTracking/ReferenceEntry.cs b/src/EFCore/ChangeTracking/ReferenceEntry.cs index d877302961d..c7d6bc93459 100644 --- a/src/EFCore/ChangeTracking/ReferenceEntry.cs +++ b/src/EFCore/ChangeTracking/ReferenceEntry.cs @@ -122,7 +122,7 @@ public override void Load() /// /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. - /// If the is canceled. + /// If the is canceled. public override Task LoadAsync(CancellationToken cancellationToken = default) => IsLoaded ? Task.CompletedTask diff --git a/src/EFCore/ChangeTracking/ValueComparer.cs b/src/EFCore/ChangeTracking/ValueComparer.cs index 9d0fce6103e..d336fc5a05c 100644 --- a/src/EFCore/ChangeTracking/ValueComparer.cs +++ b/src/EFCore/ChangeTracking/ValueComparer.cs @@ -5,7 +5,6 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Query; @@ -33,22 +32,22 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking public abstract class ValueComparer : IEqualityComparer, IEqualityComparer { private static readonly MethodInfo _doubleEqualsMethodInfo - = typeof(double).GetRequiredRuntimeMethod(nameof(double.Equals), new[] { typeof(double) }); + = typeof(double).GetRequiredRuntimeMethod(nameof(double.Equals), typeof(double)); private static readonly MethodInfo _floatEqualsMethodInfo - = typeof(float).GetRequiredRuntimeMethod(nameof(float.Equals), new[] { typeof(float) }); + = typeof(float).GetRequiredRuntimeMethod(nameof(float.Equals), typeof(float)); internal static readonly MethodInfo ArrayCopyMethod - = typeof(Array).GetRequiredRuntimeMethod(nameof(Array.Copy), new[] { typeof(Array), typeof(Array), typeof(int) }); + = typeof(Array).GetRequiredRuntimeMethod(nameof(Array.Copy), typeof(Array), typeof(Array), typeof(int)); internal static readonly MethodInfo EqualityComparerHashCodeMethod - = typeof(IEqualityComparer).GetRequiredRuntimeMethod(nameof(IEqualityComparer.GetHashCode), new[] { typeof(object) }); + = typeof(IEqualityComparer).GetRequiredRuntimeMethod(nameof(IEqualityComparer.GetHashCode), typeof(object)); internal static readonly MethodInfo EqualityComparerEqualsMethod - = typeof(IEqualityComparer).GetRequiredRuntimeMethod(nameof(IEqualityComparer.Equals), new[] { typeof(object), typeof(object) }); + = typeof(IEqualityComparer).GetRequiredRuntimeMethod(nameof(IEqualityComparer.Equals), typeof(object), typeof(object)); internal static readonly MethodInfo ObjectEqualsMethod - = typeof(object).GetRequiredRuntimeMethod(nameof(object.Equals), new[] { typeof(object), typeof(object) }); + = typeof(object).GetRequiredRuntimeMethod(nameof(object.Equals), typeof(object), typeof(object)); internal static readonly MethodInfo ObjectGetHashCodeMethod = typeof(object).GetRequiredRuntimeMethod(nameof(object.GetHashCode), Type.EmptyTypes); diff --git a/src/EFCore/ChangeTracking/ValueComparer`.cs b/src/EFCore/ChangeTracking/ValueComparer`.cs index 422d00a7bc0..5f0e6b3bf3a 100644 --- a/src/EFCore/ChangeTracking/ValueComparer`.cs +++ b/src/EFCore/ChangeTracking/ValueComparer`.cs @@ -26,7 +26,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking /// /// /// - /// See EF Core value comparers for more information. + /// See EF Core value comparers for more information. /// /// The type. public class ValueComparer : ValueComparer, IEqualityComparer diff --git a/src/EFCore/DbContext.cs b/src/EFCore/DbContext.cs index c4f45e3df03..e2a7d71cb03 100644 --- a/src/EFCore/DbContext.cs +++ b/src/EFCore/DbContext.cs @@ -55,7 +55,7 @@ namespace Microsoft.EntityFrameworkCore /// /// /// See DbContext lifetime, configuration, and initialization, - /// Querying data with EF Core, + /// Querying data with EF Core, /// Changing tracking, and /// Saving data with EF Core for more information. /// @@ -323,7 +323,7 @@ object IDbSetCache.GetOrAddSet(IDbSetSource source, string entityTypeName, Type /// /// /// - /// See Querying data with EF Core and + /// See Querying data with EF Core and /// Changing tracking for more information. /// /// The type of entity for which a set should be returned. @@ -342,7 +342,7 @@ public virtual DbSet Set() /// /// /// - /// See Querying data with EF Core, + /// See Querying data with EF Core, /// Changing tracking, and /// Shared entity types for more information. /// @@ -487,7 +487,7 @@ protected internal virtual void OnConfiguring(DbContextOptionsBuilder optionsBui /// /// Override this method to set defaults and configure conventions before they run. This method is invoked before - /// . + /// . /// /// /// If a model is explicitly set on the options for this context (via ) @@ -2141,6 +2141,7 @@ public virtual IQueryable FromExpression(Expression