diff --git a/Dapper.SqlBuilder/Dapper.SqlBuilder.csproj b/Dapper.SqlBuilder/Dapper.SqlBuilder.csproj
index c101afcaa..a455a5941 100644
--- a/Dapper.SqlBuilder/Dapper.SqlBuilder.csproj
+++ b/Dapper.SqlBuilder/Dapper.SqlBuilder.csproj
@@ -19,7 +19,8 @@
-
+
+
diff --git a/Dapper.SqlBuilder/SqlBuilder.cs b/Dapper.SqlBuilder/SqlBuilder.cs
index 5726fdc6e..cb45d0582 100644
--- a/Dapper.SqlBuilder/SqlBuilder.cs
+++ b/Dapper.SqlBuilder/SqlBuilder.cs
@@ -10,7 +10,7 @@ public class SqlBuilder
private readonly Dictionary _data = new Dictionary();
private int _seq;
- private class Clause
+ private sealed class Clause
{
public Clause(string sql, object? parameters, bool isInclusive)
{
@@ -23,7 +23,7 @@ public Clause(string sql, object? parameters, bool isInclusive)
public bool IsInclusive { get; }
}
- private class Clauses : List
+ private sealed class Clauses : List
{
private readonly string _joiner, _prefix, _postfix;
@@ -36,11 +36,9 @@ public Clauses(string joiner, string prefix = "", string postfix = "")
public string ResolveClauses(DynamicParameters p)
{
- foreach (var item in this)
- {
- p.AddDynamicParams(item.Parameters);
- }
- return this.Any(a => a.IsInclusive)
+ ForEach(item => p.AddDynamicParams(item.Parameters));
+
+ return Exists(a => a.IsInclusive)
? _prefix +
string.Join(_joiner,
this.Where(a => !a.IsInclusive)
diff --git a/Dapper.StrongName/Dapper.StrongName.csproj b/Dapper.StrongName/Dapper.StrongName.csproj
index 2aae43d73..705385fd6 100644
--- a/Dapper.StrongName/Dapper.StrongName.csproj
+++ b/Dapper.StrongName/Dapper.StrongName.csproj
@@ -19,10 +19,12 @@
+
+
diff --git a/Dapper.sln b/Dapper.sln.old
similarity index 98%
rename from Dapper.sln
rename to Dapper.sln.old
index 04fcc008d..e324cc009 100644
--- a/Dapper.sln
+++ b/Dapper.sln.old
@@ -1,121 +1,121 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.7.33906.173
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A34907DF-958A-4E4C-8491-84CF303FD13E}"
- ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
- appveyor.yml = appveyor.yml
- Build.csproj = Build.csproj
- build.ps1 = build.ps1
- Dapper.png = Dapper.png
- Directory.Build.props = Directory.Build.props
- Directory.Packages.props = Directory.Packages.props
- global.json = global.json
- docs\index.md = docs\index.md
- License.txt = License.txt
- .github\workflows\main.yml = .github\workflows\main.yml
- NonCLA.md = NonCLA.md
- nuget.config = nuget.config
- Readme.md = Readme.md
- version.json = version.json
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper", "Dapper\Dapper.csproj", "{FAC24C3F-68F9-4247-A4B9-21D487E99275}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.StrongName", "Dapper.StrongName\Dapper.StrongName.csproj", "{549C51A1-222B-4E12-96F1-3AEFF45A7709}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Tests", "tests\Dapper.Tests\Dapper.Tests.csproj", "{052C0817-DB26-4925-8929-8C5E42D148D5}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.EntityFramework", "Dapper.EntityFramework\Dapper.EntityFramework.csproj", "{BE401F7B-8611-4A1E-AEAA-5CB700128C16}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.SqlBuilder", "Dapper.SqlBuilder\Dapper.SqlBuilder.csproj", "{196928F0-7052-4585-90E8-817BD720F5E3}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Rainbow", "Dapper.Rainbow\Dapper.Rainbow.csproj", "{8A74F0B6-188F-45D2-8A4B-51E4F211805A}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{568BD46C-1C65-4D44-870C-12CD72563262}"
- ProjectSection(SolutionItems) = preProject
- tests\Directory.Build.props = tests\Directory.Build.props
- tests\Directory.Build.targets = tests\Directory.Build.targets
- tests\docker-compose.yml = tests\docker-compose.yml
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.EntityFramework.StrongName", "Dapper.EntityFramework.StrongName\Dapper.EntityFramework.StrongName.csproj", "{39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Tests.Performance", "benchmarks\Dapper.Tests.Performance\Dapper.Tests.Performance.csproj", "{F017075A-2969-4A8E-8971-26F154EB420F}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.ProviderTools", "Dapper.ProviderTools\Dapper.ProviderTools.csproj", "{B06DB435-0C74-4BD3-BC97-52AF7CF9916B}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{9D960D4D-80A2-4DAC-B386-8F4235EC73E6}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "docs", "docs\docs.csproj", "{C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {FAC24C3F-68F9-4247-A4B9-21D487E99275}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FAC24C3F-68F9-4247-A4B9-21D487E99275}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FAC24C3F-68F9-4247-A4B9-21D487E99275}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FAC24C3F-68F9-4247-A4B9-21D487E99275}.Release|Any CPU.Build.0 = Release|Any CPU
- {549C51A1-222B-4E12-96F1-3AEFF45A7709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {549C51A1-222B-4E12-96F1-3AEFF45A7709}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {549C51A1-222B-4E12-96F1-3AEFF45A7709}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {549C51A1-222B-4E12-96F1-3AEFF45A7709}.Release|Any CPU.Build.0 = Release|Any CPU
- {052C0817-DB26-4925-8929-8C5E42D148D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {052C0817-DB26-4925-8929-8C5E42D148D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {052C0817-DB26-4925-8929-8C5E42D148D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {052C0817-DB26-4925-8929-8C5E42D148D5}.Release|Any CPU.Build.0 = Release|Any CPU
- {BE401F7B-8611-4A1E-AEAA-5CB700128C16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {BE401F7B-8611-4A1E-AEAA-5CB700128C16}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {BE401F7B-8611-4A1E-AEAA-5CB700128C16}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BE401F7B-8611-4A1E-AEAA-5CB700128C16}.Release|Any CPU.Build.0 = Release|Any CPU
- {196928F0-7052-4585-90E8-817BD720F5E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {196928F0-7052-4585-90E8-817BD720F5E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {196928F0-7052-4585-90E8-817BD720F5E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {196928F0-7052-4585-90E8-817BD720F5E3}.Release|Any CPU.Build.0 = Release|Any CPU
- {8A74F0B6-188F-45D2-8A4B-51E4F211805A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {8A74F0B6-188F-45D2-8A4B-51E4F211805A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {8A74F0B6-188F-45D2-8A4B-51E4F211805A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {8A74F0B6-188F-45D2-8A4B-51E4F211805A}.Release|Any CPU.Build.0 = Release|Any CPU
- {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}.Release|Any CPU.Build.0 = Release|Any CPU
- {F017075A-2969-4A8E-8971-26F154EB420F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F017075A-2969-4A8E-8971-26F154EB420F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F017075A-2969-4A8E-8971-26F154EB420F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F017075A-2969-4A8E-8971-26F154EB420F}.Release|Any CPU.Build.0 = Release|Any CPU
- {B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Release|Any CPU.Build.0 = Release|Any CPU
- {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {FAC24C3F-68F9-4247-A4B9-21D487E99275} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
- {549C51A1-222B-4E12-96F1-3AEFF45A7709} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
- {052C0817-DB26-4925-8929-8C5E42D148D5} = {568BD46C-1C65-4D44-870C-12CD72563262}
- {BE401F7B-8611-4A1E-AEAA-5CB700128C16} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
- {196928F0-7052-4585-90E8-817BD720F5E3} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
- {8A74F0B6-188F-45D2-8A4B-51E4F211805A} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
- {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
- {F017075A-2969-4A8E-8971-26F154EB420F} = {568BD46C-1C65-4D44-870C-12CD72563262}
- {B06DB435-0C74-4BD3-BC97-52AF7CF9916B} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
- {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F} = {9D960D4D-80A2-4DAC-B386-8F4235EC73E6}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {928A4226-96F3-409A-8A83-9E7444488710}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.7.33906.173
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A34907DF-958A-4E4C-8491-84CF303FD13E}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ appveyor.yml = appveyor.yml
+ Build.csproj = Build.csproj
+ build.ps1 = build.ps1
+ Dapper.png = Dapper.png
+ Directory.Build.props = Directory.Build.props
+ Directory.Packages.props = Directory.Packages.props
+ global.json = global.json
+ docs\index.md = docs\index.md
+ License.txt = License.txt
+ .github\workflows\main.yml = .github\workflows\main.yml
+ NonCLA.md = NonCLA.md
+ nuget.config = nuget.config
+ Readme.md = Readme.md
+ version.json = version.json
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper", "Dapper\Dapper.csproj", "{FAC24C3F-68F9-4247-A4B9-21D487E99275}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.StrongName", "Dapper.StrongName\Dapper.StrongName.csproj", "{549C51A1-222B-4E12-96F1-3AEFF45A7709}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Tests", "tests\Dapper.Tests\Dapper.Tests.csproj", "{052C0817-DB26-4925-8929-8C5E42D148D5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.EntityFramework", "Dapper.EntityFramework\Dapper.EntityFramework.csproj", "{BE401F7B-8611-4A1E-AEAA-5CB700128C16}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.SqlBuilder", "Dapper.SqlBuilder\Dapper.SqlBuilder.csproj", "{196928F0-7052-4585-90E8-817BD720F5E3}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Rainbow", "Dapper.Rainbow\Dapper.Rainbow.csproj", "{8A74F0B6-188F-45D2-8A4B-51E4F211805A}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{568BD46C-1C65-4D44-870C-12CD72563262}"
+ ProjectSection(SolutionItems) = preProject
+ tests\Directory.Build.props = tests\Directory.Build.props
+ tests\Directory.Build.targets = tests\Directory.Build.targets
+ tests\docker-compose.yml = tests\docker-compose.yml
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.EntityFramework.StrongName", "Dapper.EntityFramework.StrongName\Dapper.EntityFramework.StrongName.csproj", "{39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Tests.Performance", "benchmarks\Dapper.Tests.Performance\Dapper.Tests.Performance.csproj", "{F017075A-2969-4A8E-8971-26F154EB420F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.ProviderTools", "Dapper.ProviderTools\Dapper.ProviderTools.csproj", "{B06DB435-0C74-4BD3-BC97-52AF7CF9916B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{9D960D4D-80A2-4DAC-B386-8F4235EC73E6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "docs", "docs\docs.csproj", "{C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FAC24C3F-68F9-4247-A4B9-21D487E99275}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FAC24C3F-68F9-4247-A4B9-21D487E99275}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FAC24C3F-68F9-4247-A4B9-21D487E99275}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FAC24C3F-68F9-4247-A4B9-21D487E99275}.Release|Any CPU.Build.0 = Release|Any CPU
+ {549C51A1-222B-4E12-96F1-3AEFF45A7709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {549C51A1-222B-4E12-96F1-3AEFF45A7709}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {549C51A1-222B-4E12-96F1-3AEFF45A7709}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {549C51A1-222B-4E12-96F1-3AEFF45A7709}.Release|Any CPU.Build.0 = Release|Any CPU
+ {052C0817-DB26-4925-8929-8C5E42D148D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {052C0817-DB26-4925-8929-8C5E42D148D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {052C0817-DB26-4925-8929-8C5E42D148D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {052C0817-DB26-4925-8929-8C5E42D148D5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BE401F7B-8611-4A1E-AEAA-5CB700128C16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BE401F7B-8611-4A1E-AEAA-5CB700128C16}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BE401F7B-8611-4A1E-AEAA-5CB700128C16}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BE401F7B-8611-4A1E-AEAA-5CB700128C16}.Release|Any CPU.Build.0 = Release|Any CPU
+ {196928F0-7052-4585-90E8-817BD720F5E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {196928F0-7052-4585-90E8-817BD720F5E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {196928F0-7052-4585-90E8-817BD720F5E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {196928F0-7052-4585-90E8-817BD720F5E3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8A74F0B6-188F-45D2-8A4B-51E4F211805A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8A74F0B6-188F-45D2-8A4B-51E4F211805A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8A74F0B6-188F-45D2-8A4B-51E4F211805A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8A74F0B6-188F-45D2-8A4B-51E4F211805A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F017075A-2969-4A8E-8971-26F154EB420F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F017075A-2969-4A8E-8971-26F154EB420F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F017075A-2969-4A8E-8971-26F154EB420F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F017075A-2969-4A8E-8971-26F154EB420F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B06DB435-0C74-4BD3-BC97-52AF7CF9916B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {FAC24C3F-68F9-4247-A4B9-21D487E99275} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
+ {549C51A1-222B-4E12-96F1-3AEFF45A7709} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
+ {052C0817-DB26-4925-8929-8C5E42D148D5} = {568BD46C-1C65-4D44-870C-12CD72563262}
+ {BE401F7B-8611-4A1E-AEAA-5CB700128C16} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
+ {196928F0-7052-4585-90E8-817BD720F5E3} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
+ {8A74F0B6-188F-45D2-8A4B-51E4F211805A} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
+ {39D3EEB6-9C05-4F4A-8C01-7B209742A7EB} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
+ {F017075A-2969-4A8E-8971-26F154EB420F} = {568BD46C-1C65-4D44-870C-12CD72563262}
+ {B06DB435-0C74-4BD3-BC97-52AF7CF9916B} = {4E956F6B-6BD8-46F5-BC85-49292FF8F9AB}
+ {C2F722AC-B2D4-4E97-AF8E-C036B3D9211F} = {9D960D4D-80A2-4DAC-B386-8F4235EC73E6}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {928A4226-96F3-409A-8A83-9E7444488710}
+ EndGlobalSection
+EndGlobal
diff --git a/Dapper.slnx b/Dapper.slnx
new file mode 100644
index 000000000..674239170
--- /dev/null
+++ b/Dapper.slnx
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Dapper/Dapper.csproj b/Dapper/Dapper.csproj
index 98d8f11eb..d9518dc45 100644
--- a/Dapper/Dapper.csproj
+++ b/Dapper/Dapper.csproj
@@ -26,10 +26,12 @@
+
+
diff --git a/Dapper/DefaultTypeMap.cs b/Dapper/DefaultTypeMap.cs
index 98029741a..c2f691883 100644
--- a/Dapper/DefaultTypeMap.cs
+++ b/Dapper/DefaultTypeMap.cs
@@ -10,7 +10,7 @@ namespace Dapper
///
public sealed class DefaultTypeMap : SqlMapper.ITypeMap
{
- private readonly List _fields;
+ private readonly FieldInfo[] _fields;
private readonly Type _type;
///
@@ -42,7 +42,7 @@ internal static MethodInfo GetPropertySetterOrThrow(PropertyInfo propertyInfo, T
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
Type.DefaultBinder,
propertyInfo.PropertyType,
- propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray(),
+ Array.ConvertAll(propertyInfo.GetIndexParameters(), p => p.ParameterType),
null)!.GetSetMethod(true);
}
@@ -54,9 +54,9 @@ internal static List GetSettableProps(Type t)
.ToList();
}
- internal static List GetSettableFields(Type t)
+ private static FieldInfo[] GetSettableFields(Type t)
{
- return t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).ToList();
+ return t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
}
///
@@ -156,20 +156,20 @@ public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor,
// preference order is:
// exact match over underscore match, exact case over wrong case, backing fields over regular fields, match-inc-underscores over match-exc-underscores
- var field = _fields.Find(p => string.Equals(p.Name, columnName, StringComparison.Ordinal))
- ?? _fields.Find(p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal))
- ?? _fields.Find(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase))
- ?? _fields.Find(p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase));
+ var field = Array.Find(_fields, p => string.Equals(p.Name, columnName, StringComparison.Ordinal))
+ ?? Array.Find(_fields, p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal))
+ ?? Array.Find(_fields, p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase))
+ ?? Array.Find(_fields, p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase));
if (field is null && MatchNamesWithUnderscores)
{
var effectiveColumnName = columnName.Replace("_", "");
backingFieldName = "<" + effectiveColumnName + ">k__BackingField";
- field = _fields.Find(p => string.Equals(p.Name, effectiveColumnName, StringComparison.Ordinal))
- ?? _fields.Find(p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal))
- ?? _fields.Find(p => string.Equals(p.Name, effectiveColumnName, StringComparison.OrdinalIgnoreCase))
- ?? _fields.Find(p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase));
+ field = Array.Find(_fields, p => string.Equals(p.Name, effectiveColumnName, StringComparison.Ordinal))
+ ?? Array.Find(_fields, p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal))
+ ?? Array.Find(_fields, p => string.Equals(p.Name, effectiveColumnName, StringComparison.OrdinalIgnoreCase))
+ ?? Array.Find(_fields, p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase));
}
if (field is not null)
diff --git a/Dapper/DynamicParameters.cs b/Dapper/DynamicParameters.cs
index f6708b5ce..1feb4d020 100644
--- a/Dapper/DynamicParameters.cs
+++ b/Dapper/DynamicParameters.cs
@@ -62,10 +62,7 @@ public void AddDynamicParams(object? param)
if (subDynamic.templates is not null)
{
templates ??= new List
/// The type to cache.
/// The value type of the cache.
- internal class Link where TKey : class
+ internal sealed class Link where TKey : class
{
public static void Clear(ref Link? head) => Interlocked.Exchange(ref head, null);
public static bool TryGet(Link? link, TKey key, [NotNullWhen(true)] out TValue? value)
diff --git a/Dapper/SqlMapper.Settings.cs b/Dapper/SqlMapper.Settings.cs
index cbbc3c687..c19835c11 100644
--- a/Dapper/SqlMapper.Settings.cs
+++ b/Dapper/SqlMapper.Settings.cs
@@ -65,7 +65,7 @@ static Settings()
public static void SetDefaults()
{
CommandTimeout = null;
- ApplyNullValues = PadListExpansions = UseIncrementalPseudoPositionalParameterNames = false;
+ ApplyNullValues = PadListExpansions = UseIncrementalPseudoPositionalParameterNames = PreferTypeHandlersForEnums = false;
AllowedCommandBehaviors = DefaultAllowedCommandBehaviors;
FetchSize = InListStringSplitCount = -1;
}
@@ -129,6 +129,13 @@ public static long FetchSize
///
public static bool SupportLegacyParameterTokens { get; set; } = true;
+ ///
+ /// When true, Dapper checks for a registered TypeHandler for enum types before
+ /// falling back to the default behavior of sending enums as their underlying integer type.
+ /// This enables custom enum serialization (e.g. storing enums as strings), while preserving existing behavior.
+ ///
+ public static bool PreferTypeHandlersForEnums { get; set; }
+
private static long s_FetchSize = -1;
}
}
diff --git a/Dapper/SqlMapper.TypeDeserializerCache.cs b/Dapper/SqlMapper.TypeDeserializerCache.cs
index 2c2f646db..3a34cd292 100644
--- a/Dapper/SqlMapper.TypeDeserializerCache.cs
+++ b/Dapper/SqlMapper.TypeDeserializerCache.cs
@@ -8,7 +8,7 @@ namespace Dapper
{
public static partial class SqlMapper
{
- private class TypeDeserializerCache
+ private sealed class TypeDeserializerCache
{
private TypeDeserializerCache(Type type)
{
diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs
index d23e949a5..2fa0e72b7 100644
--- a/Dapper/SqlMapper.cs
+++ b/Dapper/SqlMapper.cs
@@ -29,7 +29,7 @@ namespace Dapper
///
public static partial class SqlMapper
{
- private class PropertyInfoByNameComparer : IComparer
+ private sealed class PropertyInfoByNameComparer : IComparer
{
public int Compare(PropertyInfo? x, PropertyInfo? y) => string.CompareOrdinal(x?.Name, y?.Name);
}
@@ -465,6 +465,10 @@ public static void SetDbType(IDataParameter parameter, object value)
if (nullUnderlyingType is not null) type = nullUnderlyingType;
if (type.IsEnum && !typeMap.ContainsKey(type))
{
+ if (Settings.PreferTypeHandlersForEnums && typeHandlers.TryGetValue(type, out handler))
+ {
+ return DbType.Object;
+ }
type = Enum.GetUnderlyingType(type);
}
if (typeMap.TryGetValue(type, out var mapEntry))
@@ -2666,7 +2670,11 @@ private static bool IsValueTuple(Type? type) => (type?.IsValueType == true
{
il.Emit(OpCodes.Ldloc, typedParameterLocal); // stack is now [parameters] [typed-param]
il.Emit(callOpCode, prop.GetGetMethod()!); // stack is [parameters] [custom]
- if (!prop.PropertyType.IsValueType)
+ if (prop.PropertyType.IsValueType)
+ {
+ il.Emit(OpCodes.Box, prop.PropertyType); // stack is [parameters] [boxed-custom]
+ }
+ else
{
// throw if null
var notNull = il.DefineLabel();
@@ -2678,7 +2686,7 @@ private static bool IsValueTuple(Type? type) => (type?.IsValueType == true
}
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [custom] [command]
il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [custom] [command] [name]
- il.EmitCall(OpCodes.Callvirt, prop.PropertyType.GetMethod(nameof(ICustomQueryParameter.AddParameter))!, null); // stack is now [parameters]
+ il.EmitCall(OpCodes.Callvirt, typeof(ICustomQueryParameter).GetMethod(nameof(ICustomQueryParameter.AddParameter))!, null); // stack is now [parameters]
continue;
}
#pragma warning disable 618
@@ -2751,7 +2759,12 @@ private static bool IsValueTuple(Type? type) => (type?.IsValueType == true
if ((nullType ?? propType).IsEnum)
{
- if (nullType is not null)
+ if (handler is not null)
+ {
+ // TypeHandler registered - box as the enum type, handler does conversion
+ checkForNull = nullType is not null;
+ }
+ else if (nullType is not null)
{
// Nullable; we want to box as the underlying type; that's just *hard*; for
// simplicity, box as Nullable and call SanitizeParameterValue
@@ -3097,7 +3110,16 @@ private static Func GetSimpleValueDeserializer(Type type,
#pragma warning restore 618
if (effectiveType.IsEnum)
- { // assume the value is returned as the correct type (int/byte/etc), but box back to the typed enum
+ {
+ if (Settings.PreferTypeHandlersForEnums && typeHandlers.TryGetValue(type, out var enumHandler))
+ {
+ return r =>
+ {
+ var val = r.GetValue(index);
+ return val is DBNull ? null! : enumHandler.Parse(type, val)!;
+ };
+ }
+ // assume the value is returned as the correct type (int/byte/etc), but box back to the typed enum
return r =>
{
var val = r.GetValue(index);
@@ -3160,6 +3182,10 @@ private static T Parse(object? value)
type = Nullable.GetUnderlyingType(type) ?? type;
if (type.IsEnum)
{
+ if (Settings.PreferTypeHandlersForEnums && typeHandlers.TryGetValue(type, out ITypeHandler? enumHandler))
+ {
+ return (T)enumHandler.Parse(type, value)!;
+ }
if (value is float || value is double || value is decimal)
{
value = Convert.ChangeType(value, Enum.GetUnderlyingType(type), CultureInfo.InvariantCulture);
@@ -3530,9 +3556,9 @@ private static void GenerateDeserializerFromMap(Type type, DbDataReader reader,
il.Emit(OpCodes.Ldloc, returnValueLocal); // [target]
}
- var members = (specializedConstructor is not null
- ? names.Select(n => typeMap.GetConstructorParameter(specializedConstructor, n))
- : names.Select(n => typeMap.GetMember(n))).ToList();
+ var members = Array.ConvertAll(names, specializedConstructor is not null
+ ? n => typeMap.GetConstructorParameter(specializedConstructor, n)
+ : n => typeMap.GetMember(n));
// stack is now [target]
bool first = true;
@@ -3738,22 +3764,31 @@ private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int ind
if (unboxType.IsEnum)
{
- Type numericType = Enum.GetUnderlyingType(unboxType);
- if (colType == typeof(string))
+ if (Settings.PreferTypeHandlersForEnums && typeHandlers.ContainsKey(unboxType))
{
- stringEnumLocal ??= il.DeclareLocal(typeof(string));
- il.Emit(OpCodes.Castclass, typeof(string)); // stack is now [...][string]
- il.Emit(OpCodes.Stloc, stringEnumLocal); // stack is now [...]
- il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [...][enum-type-token]
- il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle))!, null);// stack is now [...][enum-type]
- il.Emit(OpCodes.Ldloc, stringEnumLocal); // stack is now [...][enum-type][string]
- il.Emit(OpCodes.Ldc_I4_1); // stack is now [...][enum-type][string][true]
- il.EmitCall(OpCodes.Call, enumParse, null); // stack is now [...][enum-as-object]
- il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [...][typed-value]
+#pragma warning disable 618
+ il.EmitCall(OpCodes.Call, typeof(TypeHandlerCache<>).MakeGenericType(unboxType).GetMethod(nameof(TypeHandlerCache.Parse))!, null); // stack is now [...][typed-value]
+#pragma warning restore 618
}
else
{
- FlexibleConvertBoxedFromHeadOfStack(il, colType, unboxType, numericType);
+ Type numericType = Enum.GetUnderlyingType(unboxType);
+ if (colType == typeof(string))
+ {
+ stringEnumLocal ??= il.DeclareLocal(typeof(string));
+ il.Emit(OpCodes.Castclass, typeof(string)); // stack is now [...][string]
+ il.Emit(OpCodes.Stloc, stringEnumLocal); // stack is now [...]
+ il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [...][enum-type-token]
+ il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle))!, null);// stack is now [...][enum-type]
+ il.Emit(OpCodes.Ldloc, stringEnumLocal); // stack is now [...][enum-type][string]
+ il.Emit(OpCodes.Ldc_I4_1); // stack is now [...][enum-type][string][true]
+ il.EmitCall(OpCodes.Call, enumParse, null); // stack is now [...][enum-as-object]
+ il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [...][typed-value]
+ }
+ else
+ {
+ FlexibleConvertBoxedFromHeadOfStack(il, colType, unboxType, numericType);
+ }
}
if (nullUnderlyingType is not null)
diff --git a/Directory.Build.props b/Directory.Build.props
index cb8af4d2d..227e4eed5 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -14,7 +14,7 @@
git
https://github.com/DapperLib/Dapper
false
- $(NOWARN);IDE0056;IDE0057;IDE0079
+ $(NOWARN);IDE0056;IDE0057;IDE0079;DX1001
true
embedded
en-US
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 8787a7767..252f417b9 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -3,50 +3,56 @@
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
+
+
-
+
-
+
-
\ No newline at end of file
+
+
+
+
diff --git a/appveyor.yml b/appveyor.yml
index ae9d477bf..5ec88faaf 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -6,6 +6,11 @@ skip_commits:
files:
- '**/*.md'
+install:
+- ps: |
+ Invoke-WebRequest -Uri 'https://dot.net/v1/dotnet-install.ps1' -UseBasicParsing -OutFile "$env:temp\dotnet-install.ps1"
+ & $env:temp\dotnet-install.ps1 -Architecture x64 -Version '10.0.102' -InstallDir "$env:ProgramFiles\dotnet"
+
environment:
Appveyor: true
# Postgres
diff --git a/benchmarks/Dapper.Tests.Performance/Dapper.Tests.Performance.csproj b/benchmarks/Dapper.Tests.Performance/Dapper.Tests.Performance.csproj
index fa18bd9c5..51c28957a 100644
--- a/benchmarks/Dapper.Tests.Performance/Dapper.Tests.Performance.csproj
+++ b/benchmarks/Dapper.Tests.Performance/Dapper.Tests.Performance.csproj
@@ -3,7 +3,7 @@
Dapper.Tests.Performance
Dapper Core Performance Suite
Exe
- net462;net8.0
+ net472;net10.0
false
$(NoWarn);IDE0063;IDE0034;IDE0059;IDE0060
@@ -14,8 +14,7 @@
-
-
+
@@ -27,22 +26,24 @@
+
+
-
+
-
-
+
+
-
-
-
+
+
+
-
+
@@ -50,20 +51,19 @@
-
+
$(DefineConstants);NET4X
-
+
-
-
+
-
+
diff --git a/benchmarks/Dapper.Tests.Performance/Massive/Massive.cs b/benchmarks/Dapper.Tests.Performance/Massive/Massive.cs
index f452a95cb..f4c1c8192 100644
--- a/benchmarks/Dapper.Tests.Performance/Massive/Massive.cs
+++ b/benchmarks/Dapper.Tests.Performance/Massive/Massive.cs
@@ -322,7 +322,6 @@ public virtual DbCommand CreateUpdateCommand(object o, object key)
var settings = (IDictionary)expando;
var sbKeys = new StringBuilder();
const string stub = "UPDATE {0} SET {1} WHERE {2} = @{3}";
- var args = new List