Merge branch 'release/2.1' into release/2.2

This commit is contained in:
Nate McMaster 2018-10-31 16:15:14 -07:00
Родитель 4f470638e0 f6457bccd2 28a42160c7
Коммит 67511a675f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: A778D9601BD78810
80 изменённых файлов: 15488 добавлений и 1 удалений

Просмотреть файл

@ -101,6 +101,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.SqlServer.NTS", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Sqlite.NTS", "src\EFCore.Sqlite.NTS\EFCore.Sqlite.NTS.csproj", "{1747A095-A464-4445-9F39-A80531FB24FD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.Sqlite.Core", "src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj", "{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.Sqlite", "src\Microsoft.Data.Sqlite\Microsoft.Data.Sqlite.csproj", "{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.Sqlite.Tests", "test\Microsoft.Data.Sqlite.Tests\Microsoft.Data.Sqlite.Tests.csproj", "{51DAD0D5-5564-4FB7-B34C-98814C900DF9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -251,6 +257,18 @@ Global
{1747A095-A464-4445-9F39-A80531FB24FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1747A095-A464-4445-9F39-A80531FB24FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1747A095-A464-4445-9F39-A80531FB24FD}.Release|Any CPU.Build.0 = Release|Any CPU
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}.Debug|Any CPU.Build.0 = Debug|Any CPU
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}.Release|Any CPU.ActiveCfg = Release|Any CPU
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236}.Release|Any CPU.Build.0 = Release|Any CPU
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22}.Release|Any CPU.Build.0 = Release|Any CPU
{51DAD0D5-5564-4FB7-B34C-98814C900DF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51DAD0D5-5564-4FB7-B34C-98814C900DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51DAD0D5-5564-4FB7-B34C-98814C900DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51DAD0D5-5564-4FB7-B34C-98814C900DF9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -295,6 +313,9 @@ Global
{B4E155E5-C0B8-4680-92A0-A0DE745486B1} = {258D5057-81B9-40EC-A872-D21E27452749}
{F53EB45F-84D7-4520-B813-8916C0C756BB} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
{1747A095-A464-4445-9F39-A80531FB24FD} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
{775A9A2B-2EDB-4E2E-8E74-E46E8E8E1236} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
{D766273B-DA6A-4C6C-A9CD-AB57EF1E4F22} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
{51DAD0D5-5564-4FB7-B34C-98814C900DF9} = {258D5057-81B9-40EC-A872-D21E27452749}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {285A5EB4-BCF4-40EB-B9E1-DF6DBCB5E705}

158
Microsoft.Data.Sqlite.sln Normal file
Просмотреть файл

@ -0,0 +1,158 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2005
MinimumVisualStudioVersion = 15.0.26730.03
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9396F8F4-299D-427C-B829-EF9A931DAA3C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.Sqlite.Core", "src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj", "{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{ECB63F46-D037-4EEA-A4CD-BF18B5B9D2C4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.Sqlite.Tests", "test\Microsoft.Data.Sqlite.Tests\Microsoft.Data.Sqlite.Tests.csproj", "{69D2DA13-6774-43A9-A2E3-709594136FF8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Data.Sqlite", "src\Microsoft.Data.Sqlite\Microsoft.Data.Sqlite.csproj", "{298DB9C7-8C81-40A7-B042-20D62C914820}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{964B9063-40FE-4DB2-A80D-3073CAC4E7BA}"
ProjectSection(SolutionItems) = preProject
.appveyor.yml = .appveyor.yml
.gitattributes = .gitattributes
.gitignore = .gitignore
.travis.yml = .travis.yml
build.cmd = build.cmd
build.ps1 = build.ps1
build.sh = build.sh
CONTRIBUTING.md = CONTRIBUTING.md
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
LICENSE.txt = LICENSE.txt
NuGet.config = NuGet.config
NuGetPackageVerifier.json = NuGetPackageVerifier.json
README.md = README.md
version.xml = version.xml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AggregateFunctionSample", "samples\AggregateFunctionSample\AggregateFunctionSample.csproj", "{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncSample", "samples\AsyncSample\AsyncSample.csproj", "{FC71113A-A71D-459C-A7A9-1531D9A037D4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BatchingSample", "samples\BatchingSample\BatchingSample.csproj", "{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BulkInsertSample", "samples\BulkInsertSample\BulkInsertSample.csproj", "{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CollationSample", "samples\CollationSample\CollationSample.csproj", "{A5E96F24-953A-4E71-9081-736E11D8229F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DateAndTimeSample", "samples\DateAndTimeSample\DateAndTimeSample.csproj", "{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DirtyReadSample", "samples\DirtyReadSample\DirtyReadSample.csproj", "{CB405B7D-81E5-48B6-9E24-AC901D0423EE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EncryptionSample", "samples\EncryptionSample\EncryptionSample.csproj", "{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InMemorySample", "samples\InMemorySample\InMemorySample.csproj", "{CA7F7B53-9EE1-4516-874A-88EC717D5264}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropSample", "samples\InteropSample\InteropSample.csproj", "{068B819D-809E-421F-96A1-DAE67CDD79AE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegularExpressionSample", "samples\RegularExpressionSample\RegularExpressionSample.csproj", "{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ResultMetadataSample", "samples\ResultMetadataSample\ResultMetadataSample.csproj", "{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScalarFunctionSample", "samples\ScalarFunctionSample\ScalarFunctionSample.csproj", "{4A78B130-96DB-408F-A601-AFDA94347F06}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D}.Release|Any CPU.Build.0 = Release|Any CPU
{69D2DA13-6774-43A9-A2E3-709594136FF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69D2DA13-6774-43A9-A2E3-709594136FF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69D2DA13-6774-43A9-A2E3-709594136FF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69D2DA13-6774-43A9-A2E3-709594136FF8}.Release|Any CPU.Build.0 = Release|Any CPU
{298DB9C7-8C81-40A7-B042-20D62C914820}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{298DB9C7-8C81-40A7-B042-20D62C914820}.Debug|Any CPU.Build.0 = Debug|Any CPU
{298DB9C7-8C81-40A7-B042-20D62C914820}.Release|Any CPU.ActiveCfg = Release|Any CPU
{298DB9C7-8C81-40A7-B042-20D62C914820}.Release|Any CPU.Build.0 = Release|Any CPU
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E}.Release|Any CPU.Build.0 = Release|Any CPU
{FC71113A-A71D-459C-A7A9-1531D9A037D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC71113A-A71D-459C-A7A9-1531D9A037D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC71113A-A71D-459C-A7A9-1531D9A037D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC71113A-A71D-459C-A7A9-1531D9A037D4}.Release|Any CPU.Build.0 = Release|Any CPU
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201}.Release|Any CPU.Build.0 = Release|Any CPU
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC}.Release|Any CPU.Build.0 = Release|Any CPU
{A5E96F24-953A-4E71-9081-736E11D8229F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5E96F24-953A-4E71-9081-736E11D8229F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5E96F24-953A-4E71-9081-736E11D8229F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5E96F24-953A-4E71-9081-736E11D8229F}.Release|Any CPU.Build.0 = Release|Any CPU
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC}.Release|Any CPU.Build.0 = Release|Any CPU
{CB405B7D-81E5-48B6-9E24-AC901D0423EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB405B7D-81E5-48B6-9E24-AC901D0423EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB405B7D-81E5-48B6-9E24-AC901D0423EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB405B7D-81E5-48B6-9E24-AC901D0423EE}.Release|Any CPU.Build.0 = Release|Any CPU
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}.Debug|Any CPU.Build.0 = Debug|Any CPU
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}.Release|Any CPU.ActiveCfg = Release|Any CPU
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776}.Release|Any CPU.Build.0 = Release|Any CPU
{CA7F7B53-9EE1-4516-874A-88EC717D5264}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA7F7B53-9EE1-4516-874A-88EC717D5264}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA7F7B53-9EE1-4516-874A-88EC717D5264}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA7F7B53-9EE1-4516-874A-88EC717D5264}.Release|Any CPU.Build.0 = Release|Any CPU
{068B819D-809E-421F-96A1-DAE67CDD79AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{068B819D-809E-421F-96A1-DAE67CDD79AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{068B819D-809E-421F-96A1-DAE67CDD79AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{068B819D-809E-421F-96A1-DAE67CDD79AE}.Release|Any CPU.Build.0 = Release|Any CPU
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA}.Release|Any CPU.Build.0 = Release|Any CPU
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E}.Release|Any CPU.Build.0 = Release|Any CPU
{4A78B130-96DB-408F-A601-AFDA94347F06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A78B130-96DB-408F-A601-AFDA94347F06}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A78B130-96DB-408F-A601-AFDA94347F06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A78B130-96DB-408F-A601-AFDA94347F06}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2D5D31C9-4BE6-432E-B3C3-351A7A65353D} = {9396F8F4-299D-427C-B829-EF9A931DAA3C}
{69D2DA13-6774-43A9-A2E3-709594136FF8} = {ECB63F46-D037-4EEA-A4CD-BF18B5B9D2C4}
{298DB9C7-8C81-40A7-B042-20D62C914820} = {9396F8F4-299D-427C-B829-EF9A931DAA3C}
{C6CA9204-D9FF-4DC0-8A46-F41C4D38637E} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{FC71113A-A71D-459C-A7A9-1531D9A037D4} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{7EFA4FBC-33F1-44FF-9E8F-57EC0FE32201} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{7BC06AAD-FAD0-4FDE-BB3E-4A3D56D1FEBC} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{A5E96F24-953A-4E71-9081-736E11D8229F} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{EBC5675D-1FD0-4F77-93D0-F970EB7A29EC} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{CB405B7D-81E5-48B6-9E24-AC901D0423EE} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{67F8FB83-302C-4FBE-A2DC-F4FF5CEC8776} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{CA7F7B53-9EE1-4516-874A-88EC717D5264} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{068B819D-809E-421F-96A1-DAE67CDD79AE} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{C228450F-7EE3-463D-AA64-8AA3CAEDE4CA} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{6A153ED3-5C47-4CFF-8ED5-1B73E8E9667E} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
{4A78B130-96DB-408F-A601-AFDA94347F06} = {D30CC1C7-D46C-4640-8CE6-EC9ED34DEDA5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DF78D8CC-5604-4059-9EFB-291E2629523E}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,86 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantArgumentName/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantArgumentNameForLiteralExpression/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=Sqlite/@EntryIndexedValue">&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;Profile name="Sqlite"&gt;&lt;HtmlReformatCode&gt;True&lt;/HtmlReformatCode&gt;&lt;CSArrangeThisQualifier&gt;True&lt;/CSArrangeThisQualifier&gt;&lt;CSRemoveCodeRedundancies&gt;True&lt;/CSRemoveCodeRedundancies&gt;&lt;CSUseAutoProperty&gt;True&lt;/CSUseAutoProperty&gt;&lt;CSMakeFieldReadonly&gt;True&lt;/CSMakeFieldReadonly&gt;&lt;CSUseVar&gt;&lt;BehavourStyle&gt;CAN_CHANGE_TO_IMPLICIT&lt;/BehavourStyle&gt;&lt;LocalVariableStyle&gt;ALWAYS_IMPLICIT&lt;/LocalVariableStyle&gt;&lt;ForeachVariableStyle&gt;ALWAYS_IMPLICIT&lt;/ForeachVariableStyle&gt;&lt;/CSUseVar&gt;&lt;CSOptimizeUsings&gt;&lt;OptimizeUsings&gt;True&lt;/OptimizeUsings&gt;&lt;EmbraceInRegion&gt;False&lt;/EmbraceInRegion&gt;&lt;RegionName&gt;&lt;/RegionName&gt;&lt;/CSOptimizeUsings&gt;&lt;CSShortenReferences&gt;True&lt;/CSShortenReferences&gt;&lt;CSReformatCode&gt;True&lt;/CSReformatCode&gt;&lt;XMLReformatCode&gt;True&lt;/XMLReformatCode&gt;&lt;CSUpdateFileHeader&gt;True&lt;/CSUpdateFileHeader&gt;&lt;CSharpFormatDocComments&gt;True&lt;/CSharpFormatDocComments&gt;&lt;RemoveCodeRedundancies&gt;True&lt;/RemoveCodeRedundancies&gt;&lt;CSMakeAutoPropertyGetOnly&gt;True&lt;/CSMakeAutoPropertyGetOnly&gt;&lt;CSArrangeQualifiers&gt;True&lt;/CSArrangeQualifiers&gt;&lt;CSEnforceVarKeywordUsageSettings&gt;True&lt;/CSEnforceVarKeywordUsageSettings&gt;&lt;/Profile&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/RecentlyUsedProfile/@EntryValue">Sqlite</s:String>
<s:String x:Key="/Default/CodeStyle/CodeCleanup/SilentCleanupProfile/@EntryValue">Sqlite</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARGUMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_PARAMETER/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE_SHIFTED_2</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_ATTRIBUTE_STYLE/@EntryValue">SEPARATE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_CHOP_COMPOUND_DO_EXPRESSION/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_CHOP_COMPOUND_IF_EXPRESSION/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_CHOP_COMPOUND_WHILE_EXPRESSION/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FIXED_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOR_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOREACH_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_IFELSE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_USING_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_WHILE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_NESTED_USINGS_STMT/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE_SHIFTED_2</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CONSTRUCTOR_INITIALIZER_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_LINQ_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_EMBEDDED_STATEMENT_STYLE/@EntryValue">LINE_BREAK</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_MULTIPLICATIVE_OP/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_TYPEOF_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_BINARY_OPSIGN/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_FIRST_TYPE_PARAMETER_CONSTRAINT/@EntryValue">True</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">140</s:Int64>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LINES/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_MULTIPLE_TYPE_PARAMEER_CONSTRAINTS_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/JavaScriptFormatOther/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/XmlFormatter/WrapBeforeAttr/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/XmlFormatter/WrapInsideText/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/QualifiedUsingAtNestedScope/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Copyright (c) .NET Foundation. All rights reserved.&#xD;
Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.&#xD;
</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Constructor/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Constructor/Options/=XmlDocumentation/@EntryIndexedValue">True</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Equality/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=ChangeEquals/@EntryIndexedValue">Side by side</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=ChangeGetHashCode/@EntryIndexedValue">Side by side</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=EqualityOperators/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=ImplementIEquatable/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Equality/Options/=XmlDocumentation/@EntryIndexedValue">False</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Implementations/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=WrapInRegion/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=XmlDocumentation/@EntryIndexedValue">False</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Overrides/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=WrapInRegion/@EntryIndexedValue">False</s:String>
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=XmlDocumentation/@EntryIndexedValue">False</s:String>
<s:Boolean x:Key="/Default/CodeStyle/IntroduceVariableUseVar/UseVarForIntroduceVariableRefactoring/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=042e7460_002D3ec6_002D4f1c_002D87c3_002Dfc91240d4c90/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static, Instance" AccessRightKinds="Public" Description="Test Methods"&gt;&lt;ElementKinds&gt;&lt;Kind Name="TEST_MEMBER" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="Aa_bb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/VBNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String>
<s:Boolean x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=3F8396C34A1E534D98BAC4E46C6A441A/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=3F8396C34A1E534D98BAC4E46C6A441A/AbsolutePath/@EntryValue">D:\code\Microsoft.Data.Sqlite\Microsoft.Data.Sqlite.sln.DotSettings</s:String>
<s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=3F8396C34A1E534D98BAC4E46C6A441A/RelativePath/@EntryValue"></s:String>
<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File3F8396C34A1E534D98BAC4E46C6A441A/@KeyIndexDefined">True</s:Boolean>
<s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File3F8396C34A1E534D98BAC4E46C6A441A/RelativePriority/@EntryValue">1</s:Double>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsCodeFormatterSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsParsFormattingSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsWrapperSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EXml_002ECodeStyle_002EFormatSettingsUpgrade_002EXmlMoveToCommonFormatterSettingsUpgrade/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

Просмотреть файл

@ -32,15 +32,20 @@
<OracleManagedDataAccessPackageVersion>12.2.1100</OracleManagedDataAccessPackageVersion>
<RemotionLinqPackageVersion>2.2.0</RemotionLinqPackageVersion>
<SQLitePCLRawBundleGreenPackageVersion>1.1.11</SQLitePCLRawBundleGreenPackageVersion>
<SQLitePCLRawBundleSqlcipherPackageVersion>1.1.11</SQLitePCLRawBundleSqlcipherPackageVersion>
<SQLitePCLRawCorePackageVersion>1.1.11</SQLitePCLRawCorePackageVersion>
<StyleCopAnalyzersPackageVersion>1.0.0</StyleCopAnalyzersPackageVersion>
<SystemCollectionsImmutablePackageVersion>1.5.0</SystemCollectionsImmutablePackageVersion>
<SystemComponentModelAnnotationsPackageVersion>4.5.0</SystemComponentModelAnnotationsPackageVersion>
<SystemDataSqlClientPackageVersion>4.6.0-preview3-27001-02</SystemDataSqlClientPackageVersion>
<SystemDiagnosticsDiagnosticSourcePackageVersion>4.5.0</SystemDiagnosticsDiagnosticSourcePackageVersion>
<SystemInteractiveAsyncPackageVersion>3.1.1</SystemInteractiveAsyncPackageVersion>
<SystemInteractiveAsyncPackageVersion>3.2.0</SystemInteractiveAsyncPackageVersion>
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
<XunitAssertPackageVersion>2.3.1</XunitAssertPackageVersion>
<XunitCorePackageVersion>2.3.1</XunitCorePackageVersion>
<XunitExtensibilityExecutionPackageVersion>2.3.1</XunitExtensibilityExecutionPackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
</PropertyGroup>
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />

Просмотреть файл

@ -13,6 +13,7 @@
<ExcludeFromTest Include="$(RepositoryRoot)test\EFCore.SqlServer.FunctionalTests\*.csproj" Condition="'$(OS)' != 'Windows_NT' AND '$(Test__SqlServer__DefaultConnection)' == ''"/>
<ExcludeSolutions Include="$(RepositoryRoot)EFCore.Runtime.sln" />
<ExcludeSolutions Include="$(RepositoryRoot)EFCore.Cosmos.sln" />
<ExcludeSolutions Include="$(RepositoryRoot)Microsoft.Data.Sqlite.sln" />
</ItemGroup>
<PropertyGroup>
<!-- These properties are use by the automation that updates dependencies.props -->

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,70 @@
using System;
using Microsoft.Data.Sqlite;
namespace AggregateFunctionSample
{
class Program
{
static void Main()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var createCommand = connection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE student (
gpa REAL
);
INSERT INTO student
VALUES (4.0),
(3.0),
(3.0),
(2.0),
(2.0),
(2.0),
(2.0),
(1.0),
(1.0),
(0.0);
";
createCommand.ExecuteNonQuery();
connection.CreateAggregate(
"stdev",
new StdDevContext(),
// This is called for each row
(StdDevContext context, double value) =>
{
context.Count++;
var delta = value - context.Mean;
context.Mean += delta / context.Count;
context.Sum += delta * (value - context.Mean);
return context;
},
// This is called to get the final result
context => Math.Sqrt(context.Sum / (context.Count - 1)));
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
@"
SELECT stdev(gpa)
FROM student
";
var stdDev = (double)queryCommand.ExecuteScalar();
Console.WriteLine($"Standard deviation: {stdDev}");
}
struct StdDevContext
{
public int Count { get; set; }
public double Mean { get; set; }
public double Sum { get; set; }
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<LangVersion>7.1</LangVersion>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,57 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Data.Sqlite;
namespace AsyncSample
{
class Program
{
static async Task Main()
{
var connection = new SqliteConnection("Data Source=AsyncSample.db");
connection.Open();
var createCommand = connection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE data (
value BLOB
)
";
createCommand.ExecuteNonQuery();
// SQLite doesn't support asynchronous I/O. Instead, they recommend using a
// write -ahead log (WAL) which improves write performance. This sample
// demonstrates the anti-pattern of using ADO.NET's async methods with
// Microsoft.Data.Sqlite.
var insertCommand = connection.CreateCommand();
insertCommand.CommandText =
@"
INSERT INTO data
VALUES ($value)
";
Console.WriteLine("Generating 100 MB of data...");
var value = new byte[100_000_000];
var random = new Random();
random.NextBytes(value);
insertCommand.Parameters.AddWithValue("$value", value);
Console.WriteLine("Inserting data...");
var stopwatch = Stopwatch.StartNew();
var task = insertCommand.ExecuteNonQueryAsync();
Console.WriteLine($"Blocked for {stopwatch.ElapsedMilliseconds} ms");
stopwatch.Restart();
await task;
Console.WriteLine($"Yielded for {stopwatch.ElapsedMilliseconds} ms");
// Clean up
connection.Close();
File.Delete("AsyncSample.db");
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,68 @@
using System;
using Microsoft.Data.Sqlite;
namespace BatchingSample
{
class Program
{
static void Main()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
// SQLite doesn't support batching natively. Since there's no network involved, it
// wouldn't really help with performance anyway. Batching is implemented in
// Microsoft.Data.Sqlite as a convenience. For better command performance, see
// BulkInsertSample.
var createCommand = connection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE blog (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE post (
id INTEGER PRIMARY KEY,
title TEXT,
blog_id INTEGER NOT NULL,
FOREIGN KEY (blog_id) REFERENCES blog
);
INSERT INTO blog
VALUES (1, 'Brice''s Blog');
INSERT INTO post
VALUES (1, 'Hello, World!', 1),
(2, 'SQLite on .NET Core', 1);
";
createCommand.ExecuteNonQuery();
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
@"
SELECT *
FROM blog;
SELECT *
FROM post;
";
var reader = queryCommand.ExecuteReader();
// Read the first result set
while (reader.Read())
{
Console.WriteLine($"Blog {reader["id"]}: {reader["name"]}");
}
// Read the second result set
reader.NextResult();
while (reader.Read())
{
Console.WriteLine($"Post {reader["id"]} in blog {reader["blog_id"]}: {reader["title"]}");
}
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,61 @@
using System;
using System.Diagnostics;
using Microsoft.Data.Sqlite;
namespace BulkInsertSample
{
class Program
{
static void Main()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var createCommand = connection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE data (
value INTEGER
)
";
createCommand.ExecuteNonQuery();
// There is no special API for inserting data in bulk. For the best performance,
// follow this pattern.
Console.WriteLine("Inserting 150,000 rows...");
var stopwatch = Stopwatch.StartNew();
// Always use a transaction
using (var transaction = connection.BeginTransaction())
{
var insertCommand = connection.CreateCommand();
insertCommand.CommandText =
@"
INSERT INTO data
VALUES ($value)
";
// Re-use the same parameterized SqliteCommand
var valueParameter = insertCommand.CreateParameter();
valueParameter.ParameterName = "$value";
insertCommand.Parameters.Add(valueParameter);
// No need to call Prepare() since it's done lazily during the first execution.
//insertCommand.Prepare();
var random = new Random();
for (int i = 0; i < 150_000; i++)
{
valueParameter.Value = random.Next();
insertCommand.ExecuteNonQuery();
}
transaction.Commit();
}
Console.WriteLine($"Done. (took {stopwatch.ElapsedMilliseconds} ms)");
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,42 @@
using System;
using Microsoft.Data.Sqlite;
namespace CollationSample
{
class Program
{
static void Main()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var createCommand = connection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE greek_letter (
value TEXT
);
INSERT INTO greek_letter
VALUES ('Λ'),
('λ');
";
createCommand.ExecuteNonQuery();
// Without this, the query returns one since the built-in NOCASE collation only
// handles ASCII characters (A-Z)
connection.CreateCollation("NOCASE", (x, y) => string.Compare(x, y, ignoreCase: true));
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
@"
SELECT count()
FROM greek_letter
WHERE value = 'λ' COLLATE NOCASE
";
var count = (long)queryCommand.ExecuteScalar();
Console.WriteLine($"Results: {count}");
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,76 @@
using System;
using Microsoft.Data.Sqlite;
namespace DateAndTimeSample
{
class Program
{
static void Main()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
// SQLite doesn't support primitive DateTime and TimeSpan values. Instead, it
// provides date and time functions to help you perform operations based on strings
// and Julian day values.
var dateTime1 = new DateTime(2017, 10, 20);
var dateTime2 = new DateTime(2017, 10, 16);
var timeSpan1 = new TimeSpan(1, 00, 0);
var timeSpan2 = new TimeSpan(0, 30, 0);
var command = connection.CreateCommand();
command.CommandText =
@"
SELECT
-- Comparisons work as expected
$dateTime1 > $dateTime2,
$timeSpan1 > $timeSpan2,
-- DateTime operations require converting to Julian days
julianday($dateTime1) - julianday($dateTime2),
-- TimeSpan operations require REAL parameters
$realTimeSpan1 - $realTimeSpan2,
-- More examples
julianday($dateTime1) - $realTimeSpan1,
$realTimeSpan1 / $realTimeSpan2,
$realTimeSpan1 / 2.0
";
command.Parameters.AddWithValue("$dateTime1", dateTime1);
command.Parameters.AddWithValue("$dateTime2", dateTime2);
command.Parameters.AddWithValue("$timeSpan1", timeSpan1);
command.Parameters.AddWithValue("$timeSpan2", timeSpan2);
command.Parameters.Add("$realTimeSpan1", SqliteType.Real).Value = timeSpan1;
command.Parameters.Add("$realTimeSpan2", SqliteType.Real).Value = timeSpan2;
using (var reader = command.ExecuteReader())
{
reader.Read();
var dateTimeComparison = reader.GetBoolean(0);
Console.WriteLine($"{dateTime1} > {dateTime2} = {dateTimeComparison}");
var timeSpanComparison = reader.GetBoolean(1);
Console.WriteLine($"{timeSpan1} > {timeSpan2} = {timeSpanComparison}");
var dateTimeDifference = reader.GetTimeSpan(2);
Console.WriteLine($"{dateTime1} - {dateTime2} = {dateTimeDifference}");
var timeSpanDifference = reader.GetTimeSpan(3);
Console.WriteLine($"{timeSpan1} - {timeSpan2} = {timeSpanDifference}");
var dateTimeSubtractTimeSpan = reader.GetDateTime(4);
Console.WriteLine($"{dateTime1} - {timeSpan1} = {dateTimeSubtractTimeSpan}");
var timeSpanDividedByTimeSpan = reader.GetDouble(5);
Console.WriteLine($"{timeSpan1} / {timeSpan2} = {timeSpanDividedByTimeSpan}");
var timeSpanDividedByDivisor = reader.GetTimeSpan(6);
Console.WriteLine($"{timeSpan1} / 2.0 = {timeSpanDividedByDivisor}");
}
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,58 @@
using System;
using System.Data;
using Microsoft.Data.Sqlite;
namespace DirtyReadSample
{
class Program
{
static void Main()
{
// The connections must use a shared cache
const string connectionString = "Data Source=DirtyReadSample;Mode=Memory;Cache=Shared";
var firstConnection = new SqliteConnection(connectionString);
firstConnection.Open();
var createCommand = firstConnection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE data (
value TEXT
);
INSERT INTO data
VALUES ('clean');
";
createCommand.ExecuteNonQuery();
using (firstConnection.BeginTransaction())
{
var updateCommand = firstConnection.CreateCommand();
updateCommand.CommandText =
@"
UPDATE data
SET value = 'dirty'
";
updateCommand.ExecuteNonQuery();
var secondConnection = new SqliteConnection(connectionString);
secondConnection.Open();
// Without ReadUncommitted, the command will time out since the table is locked
// while the transaction on the first connection is active
using (secondConnection.BeginTransaction(IsolationLevel.ReadUncommitted))
{
var queryCommand = secondConnection.CreateCommand();
queryCommand.CommandText =
@"
SELECT *
FROM data
";
var value = (string)queryCommand.ExecuteScalar();
Console.WriteLine($"Value: {value}");
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_sqlcipher" Version="$(SQLitePCLRawBundleSqlcipherPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,88 @@
using System;
using System.IO;
using Microsoft.Data.Sqlite;
namespace EncryptionSample
{
class Program
{
static void Main()
{
const string connectionString = "Data Source=EncryptionSample.db";
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
// Notice which packages are referenced by this project:
// - Microsoft.Data.Sqlite.Core
// - SQLitePCLRaw.bundle_sqlcipher
// Immediately after opening the connection, send PRAGMA key to use encryption
var keyCommand = connection.CreateCommand();
keyCommand.CommandText =
@"
PRAGMA key = 'password';
";
keyCommand.ExecuteNonQuery();
var createCommand = connection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE data (
value TEXT
);
INSERT INTO data
VALUES ('Hello, encryption!');
";
createCommand.ExecuteNonQuery();
}
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
Console.Write("Password (it's 'password'): ");
var password = Console.ReadLine();
// Sanitize the user input using the quote() function
var quoteCommand = connection.CreateCommand();
quoteCommand.CommandText =
@"
SELECT quote($value)
";
quoteCommand.Parameters.AddWithValue("$value", password);
var quotedPassword = (string)quoteCommand.ExecuteScalar();
// PRAGMA statements can't be parameterized. We're forced to concatenate the
// escaped user input
var keyCommand = connection.CreateCommand();
keyCommand.CommandText =
$@"
PRAGMA key = {quotedPassword}
";
keyCommand.ExecuteScalar();
try
{
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
@"
SELECT *
FROM data
";
var data = (string)queryCommand.ExecuteScalar();
Console.WriteLine(data);
}
catch (SqliteException ex) when (ex.SqliteErrorCode == SQLitePCL.raw.SQLITE_NOTADB)
{
Console.WriteLine("Access denied.");
}
}
// Clean up
File.Delete("EncryptionSample.db");
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,58 @@
using System;
using Microsoft.Data.Sqlite;
namespace InMemorySample
{
class Program
{
static void Main()
{
// Using a name and a shared cache allows multiple connections to access the same
// in-memory database
const string connectionString = "Data Source=InMemorySample;Mode=Memory;Cache=Shared";
// The in-memory database only persists while a connection is open to it. To manage
// its lifetime, keep one open connection around for as long as you need it.
var masterConnection = new SqliteConnection(connectionString);
masterConnection.Open();
var createCommand = masterConnection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE data (
value TEXT
)
";
createCommand.ExecuteNonQuery();
using (var firstConnection = new SqliteConnection(connectionString))
{
firstConnection.Open();
var updateCommand = firstConnection.CreateCommand();
updateCommand.CommandText =
@"
INSERT INTO data
VALUES ('Hello, memory!')
";
updateCommand.ExecuteNonQuery();
}
using (var secondConnection = new SqliteConnection(connectionString))
{
secondConnection.Open();
var queryCommand = secondConnection.CreateCommand();
queryCommand.CommandText =
@"
SELECT *
FROM data
";
var value = (string)queryCommand.ExecuteScalar();
Console.WriteLine(value);
}
// After all the connections are closed, the database is deleted.
masterConnection.Close();
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,43 @@
using System;
using Microsoft.Data.Sqlite;
namespace InteropSample
{
class Program
{
static void Main()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
// Get the underlying sqlite3 object
var db = connection.Handle;
SQLitePCL.raw.sqlite3_trace(
db,
(_, statement) => Console.WriteLine(statement),
null);
// You could also use db.ptr to access the native sqlite3 struct to, for example,
// invoke a [DllImport] method.
var command = connection.CreateCommand();
command.CommandText = "SELECT $value";
command.Parameters.AddWithValue("$value", "Trace me!");
using (var reader = command.ExecuteReader())
{
// Get the underlying sqlite3_stmt object
var stmt = reader.Handle;
var steps = SQLitePCL.raw.sqlite3_stmt_status(
stmt,
SQLitePCL.raw.SQLITE_STMTSTATUS_VM_STEP,
resetFlg: 0);
Console.WriteLine($"VM operations: {steps}");
// Likewise, use stmt.ptr to access the native sqlite3_stmt struct.
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,46 @@
using System;
using System.Text.RegularExpressions;
using Microsoft.Data.Sqlite;
namespace RegularExpressionSample
{
class Program
{
static void Main()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var createCommand = connection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE user (
name TEXT,
bio TEXT
);
INSERT INTO user
VALUES ('Arthur', 'I put two spaces after my full stops. Always.'),
('Brice', 'I used to double-space after periods. I stopped.');
";
createCommand.ExecuteNonQuery();
// Registering this function enables the REGEXP operator
connection.CreateFunction(
"regexp",
(string pattern, string input)
=> Regex.IsMatch(input, pattern));
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
@"
SELECT count()
FROM user
WHERE bio REGEXP '\w\. {2,}\w'
";
var count = (long)queryCommand.ExecuteScalar();
Console.WriteLine($"Double-spacers: {count}");
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,81 @@
using System;
using System.Data;
using System.Data.Common;
using Microsoft.Data.Sqlite;
namespace ResultMetadataSample
{
class Program
{
static void Main()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var createCommand = connection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE post (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL UNIQUE,
body TEXT
);
";
createCommand.ExecuteNonQuery();
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
@"
SELECT id AS post_id,
title,
body,
random() AS random
FROM post;
";
var reader = queryCommand.ExecuteReader();
var schemaTable = reader.GetSchemaTable();
foreach (DataRow column in schemaTable.Rows)
{
if ((bool)column[SchemaTableColumn.IsExpression])
{
Console.Write("(expression) ");
}
else
{
Console.Write($"{column[SchemaTableColumn.BaseColumnName]} ");
}
if ((bool)column[SchemaTableColumn.IsAliased])
{
Console.Write($"AS {column[SchemaTableColumn.ColumnName]} ");
}
Console.Write($"{column["DataTypeName"]} ");
if (column[SchemaTableColumn.AllowDBNull] as bool? == false)
{
Console.Write("NOT NULL ");
}
if (column[SchemaTableColumn.IsKey] as bool? == true)
{
Console.Write("PRIMARY KEY ");
}
if (column[SchemaTableOptionalColumn.IsAutoIncrement] as bool? == true)
{
Console.Write("AUTOINCREMENT ");
}
if (column[SchemaTableColumn.IsUnique] as bool? == true)
{
Console.Write("UNIQUE ");
}
Console.WriteLine();
}
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,51 @@
using System;
using Microsoft.Data.Sqlite;
namespace ScalarFunctionSample
{
class Program
{
static void Main()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
var createCommand = connection.CreateCommand();
createCommand.CommandText =
@"
CREATE TABLE cylinder (
name TEXT,
radius REAL,
height REAL
);
INSERT INTO cylinder
VALUES ('1x2', 1.0, 2.0),
('2x1', 2.0, 1.0);
";
createCommand.ExecuteNonQuery();
// SQLite will invoke this managed delegate. Debug it like you would any other code
// by setting breakpoints, etc.
connection.CreateFunction(
"volume",
(double radius, double height)
=> Math.PI * Math.Pow(radius, 2) * height);
var queryCommand = connection.CreateCommand();
queryCommand.CommandText =
@"
SELECT name,
volume(radius, height) AS volume
FROM cylinder
ORDER BY volume DESC
";
var reader = queryCommand.ExecuteReader();
while (reader.Read())
{
Console.WriteLine($"{reader["name"]}: {reader["volume"]}");
}
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -18,10 +18,10 @@
<ItemGroup>
<ProjectReference Include="..\EFCore.Relational\EFCore.Relational.csproj" PrivateAssets="contentfiles;build" />
<ProjectReference Include="..\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="$(MicrosoftDataSqliteCorePackageVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftExtensionsDependencyModelPackageVersion)" />
<PackageReference Include="StyleCop.Analyzers" Version="$(StyleCopAnalyzersPackageVersion)" PrivateAssets="All" />
</ItemGroup>

Просмотреть файл

@ -0,0 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace SQLitePCL
{
internal static class SQLitePCLExtensions
{
public static void Dispose2(this sqlite3 db)
=> raw.sqlite3_close_v2(db);
}
}

Просмотреть файл

@ -0,0 +1,35 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Data.Sqlite
{
internal static class SqliteConnectionExtensions
{
public static int ExecuteNonQuery(
this SqliteConnection connection,
string commandText)
{
using (var command = connection.CreateCommand())
{
command.CommandText = commandText;
return command.ExecuteNonQuery();
}
}
public static T ExecuteScalar<T>(
this SqliteConnection connection,
string commandText)
=> (T)connection.ExecuteScalar(commandText);
private static object ExecuteScalar(this SqliteConnection connection, string commandText)
{
using (var command = connection.CreateCommand())
{
command.CommandText = commandText;
return command.ExecuteScalar();
}
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
namespace System
{
internal static class TypeExtensions
{
public static bool IsNullable(this Type type)
=> !type.IsValueType
|| (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));
public static Type UnwrapEnumType(this Type type)
=> type.GetTypeInfo().IsEnum ? Enum.GetUnderlyingType(type) : type;
public static Type UnwrapNullableType(this Type type)
=> Nullable.GetUnderlyingType(type) ?? type;
}
}

Просмотреть файл

@ -0,0 +1,73 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Microsoft.Data.Sqlite</AssemblyName>
<RootNamespace>$(AssemblyName)</RootNamespace>
<PackageId>Microsoft.Data.Sqlite.Core</PackageId>
<Description>SQLite implementation of the System.Data.Common provider model.
Commonly Used Types:
Microsoft.Data.Sqlite.SqliteCommand
Microsoft.Data.Sqlite.SqliteConnection
Microsoft.Data.Sqlite.SqliteConnectionStringBuilder
Microsoft.Data.Sqlite.SqliteDataReader
Microsoft.Data.Sqlite.SqliteException
Microsoft.Data.Sqlite.SqliteFactory
Microsoft.Data.Sqlite.SqliteParameter
Microsoft.Data.Sqlite.SqliteTransaction</Description>
<TargetFramework>netstandard2.0</TargetFramework>
<MinClientVersion>3.6</MinClientVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<CodeAnalysisRuleSet>Microsoft.Data.Sqlite.Core.ruleset</CodeAnalysisRuleSet>
<PackageTags>SQLite;Data;ADO.NET</PackageTags>
</PropertyGroup>
<ItemGroup>
<None Update="Properties\Resources.Designer.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</None>
<None Update="SqliteConnection.CreateAggregate.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>SqliteConnection.CreateAggregate.cs</LastGenOutput>
</None>
<None Update="SqliteConnection.CreateFunction.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>SqliteConnection.CreateFunction.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.core" Version="$(SQLitePCLRawCorePackageVersion)" />
<PackageReference Include="StyleCop.Analyzers" Version="$(StyleCopAnalyzersPackageVersion)" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.Designer.tt</DependentUpon>
</Compile>
<Compile Update="SqliteCommand.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="SqliteConnection.CreateAggregate.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>SqliteConnection.CreateAggregate.tt</DependentUpon>
</Compile>
<Compile Update="SqliteConnection.CreateFunction.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>SqliteConnection.CreateFunction.tt</DependentUpon>
</Compile>
<Compile Update="SqliteConnection.cs">
<SubType>Component</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Rules for Microsoft.Data.Sqlite" Description="Code analysis rules for Microsoft.Data.Sqlite." ToolsVersion="14.0">
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1000" Action="None" />
<Rule Id="SA1001" Action="None" />
<Rule Id="SA1002" Action="None" />
<Rule Id="SA1003" Action="None" />
<Rule Id="SA1004" Action="None" />
<Rule Id="SA1005" Action="None" />
<Rule Id="SA1006" Action="None" />
<Rule Id="SA1007" Action="None" />
<Rule Id="SA1008" Action="None" />
<Rule Id="SA1009" Action="None" />
<Rule Id="SA1010" Action="None" />
<Rule Id="SA1011" Action="None" />
<Rule Id="SA1012" Action="None" />
<Rule Id="SA1013" Action="None" />
<Rule Id="SA1014" Action="None" />
<Rule Id="SA1015" Action="None" />
<Rule Id="SA1016" Action="None" />
<Rule Id="SA1017" Action="None" />
<Rule Id="SA1018" Action="None" />
<Rule Id="SA1019" Action="None" />
<Rule Id="SA1020" Action="None" />
<Rule Id="SA1021" Action="None" />
<Rule Id="SA1022" Action="None" />
<Rule Id="SA1023" Action="None" />
<Rule Id="SA1024" Action="None" />
<Rule Id="SA1025" Action="None" />
<Rule Id="SA1026" Action="None" />
<Rule Id="SA1027" Action="None" />
<Rule Id="SA1028" Action="None" />
<Rule Id="SA1100" Action="None" />
<Rule Id="SA1101" Action="None" />
<Rule Id="SA1102" Action="None" />
<Rule Id="SA1103" Action="None" />
<Rule Id="SA1104" Action="None" />
<Rule Id="SA1105" Action="None" />
<Rule Id="SA1106" Action="None" />
<Rule Id="SA1107" Action="None" />
<Rule Id="SA1108" Action="None" />
<Rule Id="SA1110" Action="None" />
<Rule Id="SA1111" Action="None" />
<Rule Id="SA1112" Action="None" />
<Rule Id="SA1113" Action="None" />
<Rule Id="SA1114" Action="None" />
<Rule Id="SA1115" Action="None" />
<Rule Id="SA1116" Action="None" />
<Rule Id="SA1117" Action="None" />
<Rule Id="SA1118" Action="None" />
<Rule Id="SA1119" Action="None" />
<Rule Id="SA1120" Action="None" />
<Rule Id="SA1121" Action="None" />
<Rule Id="SA1122" Action="None" />
<Rule Id="SA1123" Action="None" />
<Rule Id="SA1124" Action="None" />
<Rule Id="SA1125" Action="None" />
<Rule Id="SA1127" Action="None" />
<Rule Id="SA1128" Action="None" />
<Rule Id="SA1129" Action="None" />
<Rule Id="SA1130" Action="None" />
<Rule Id="SA1131" Action="None" />
<Rule Id="SA1132" Action="None" />
<Rule Id="SA1133" Action="None" />
<Rule Id="SA1134" Action="None" />
<Rule Id="SA1200" Action="None" />
<Rule Id="SA1201" Action="None" />
<Rule Id="SA1202" Action="None" />
<Rule Id="SA1203" Action="None" />
<Rule Id="SA1204" Action="None" />
<Rule Id="SA1205" Action="None" />
<Rule Id="SA1206" Action="None" />
<Rule Id="SA1207" Action="None" />
<Rule Id="SA1208" Action="None" />
<Rule Id="SA1209" Action="None" />
<Rule Id="SA1210" Action="None" />
<Rule Id="SA1211" Action="None" />
<Rule Id="SA1212" Action="None" />
<Rule Id="SA1213" Action="None" />
<Rule Id="SA1214" Action="None" />
<Rule Id="SA1216" Action="None" />
<Rule Id="SA1217" Action="None" />
<Rule Id="SA1300" Action="None" />
<Rule Id="SA1302" Action="None" />
<Rule Id="SA1303" Action="None" />
<Rule Id="SA1304" Action="None" />
<Rule Id="SA1306" Action="None" />
<Rule Id="SA1307" Action="None" />
<Rule Id="SA1308" Action="None" />
<Rule Id="SA1309" Action="None" />
<Rule Id="SA1310" Action="None" />
<Rule Id="SA1311" Action="None" />
<Rule Id="SA1312" Action="None" />
<Rule Id="SA1313" Action="None" />
<Rule Id="SA1400" Action="None" />
<Rule Id="SA1401" Action="None" />
<Rule Id="SA1402" Action="None" />
<Rule Id="SA1403" Action="None" />
<Rule Id="SA1404" Action="None" />
<Rule Id="SA1405" Action="None" />
<Rule Id="SA1406" Action="None" />
<Rule Id="SA1407" Action="None" />
<Rule Id="SA1408" Action="None" />
<Rule Id="SA1410" Action="None" />
<Rule Id="SA1411" Action="None" />
<Rule Id="SA1500" Action="None" />
<Rule Id="SA1501" Action="None" />
<Rule Id="SA1502" Action="None" />
<Rule Id="SA1503" Action="None" />
<Rule Id="SA1504" Action="None" />
<Rule Id="SA1505" Action="None" />
<Rule Id="SA1506" Action="None" />
<Rule Id="SA1507" Action="None" />
<Rule Id="SA1508" Action="None" />
<Rule Id="SA1509" Action="None" />
<Rule Id="SA1510" Action="None" />
<Rule Id="SA1511" Action="None" />
<Rule Id="SA1512" Action="None" />
<Rule Id="SA1513" Action="None" />
<Rule Id="SA1514" Action="None" />
<Rule Id="SA1515" Action="None" />
<Rule Id="SA1516" Action="None" />
<Rule Id="SA1517" Action="None" />
<Rule Id="SA1518" Action="None" />
<Rule Id="SA1519" Action="None" />
<Rule Id="SA1520" Action="None" />
<Rule Id="SA1600" Action="None" />
<Rule Id="SA1601" Action="None" />
<Rule Id="SA1605" Action="None" />
<Rule Id="SA1609" Action="Warning" />
<Rule Id="SA1612" Action="None" />
<Rule Id="SA1619" Action="None" />
<Rule Id="SA1626" Action="None" />
<Rule Id="SA1633" Action="None" />
<Rule Id="SA1634" Action="None" />
<Rule Id="SA1635" Action="None" />
<Rule Id="SA1636" Action="None" />
<Rule Id="SA1637" Action="None" />
<Rule Id="SA1638" Action="None" />
<Rule Id="SA1640" Action="None" />
<Rule Id="SA1641" Action="None" />
<Rule Id="SA1649" Action="None" />
<Rule Id="SA1652" Action="None" />
</Rules>
</RuleSet>

Просмотреть файл

@ -0,0 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo(
"Microsoft.Data.Sqlite.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

250
src/Microsoft.Data.Sqlite.Core/Properties/Resources.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,250 @@
// <auto-generated />
using System.Reflection;
using System.Resources;
namespace Microsoft.Data.Sqlite.Properties
{
internal static class Resources
{
private static readonly ResourceManager _resourceManager
= new ResourceManager("Microsoft.Data.Sqlite.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly);
/// <summary>
/// {methodName} can only be called when the connection is open.
/// </summary>
public static string CallRequiresOpenConnection(object methodName)
=> string.Format(
GetString("CallRequiresOpenConnection", nameof(methodName)),
methodName);
/// <summary>
/// CommandText must be set before {methodName} can be called.
/// </summary>
public static string CallRequiresSetCommandText(object methodName)
=> string.Format(
GetString("CallRequiresSetCommandText", nameof(methodName)),
methodName);
/// <summary>
/// ConnectionString cannot be set when the connection is open.
/// </summary>
public static string ConnectionStringRequiresClosedConnection
=> GetString("ConnectionStringRequiresClosedConnection");
/// <summary>
/// Invalid attempt to call {operation} when reader is closed.
/// </summary>
public static string DataReaderClosed(object operation)
=> string.Format(
GetString("DataReaderClosed", nameof(operation)),
operation);
/// <summary>
/// The cache mode '{mode}' is invalid.
/// </summary>
public static string InvalidCacheMode(object mode)
=> string.Format(
GetString("InvalidCacheMode", nameof(mode)),
mode);
/// <summary>
/// The CommandBehavior '{behavior}' is invalid.
/// </summary>
public static string InvalidCommandBehavior(object behavior)
=> string.Format(
GetString("InvalidCommandBehavior", nameof(behavior)),
behavior);
/// <summary>
/// The CommandType '{commandType}' is invalid.
/// </summary>
public static string InvalidCommandType(object commandType)
=> string.Format(
GetString("InvalidCommandType", nameof(commandType)),
commandType);
/// <summary>
/// The IsolationLevel '{isolationLevel}' is invalid.
/// </summary>
public static string InvalidIsolationLevel(object isolationLevel)
=> string.Format(
GetString("InvalidIsolationLevel", nameof(isolationLevel)),
isolationLevel);
/// <summary>
/// The ParameterDirection '{direction}' is invalid.
/// </summary>
public static string InvalidParameterDirection(object direction)
=> string.Format(
GetString("InvalidParameterDirection", nameof(direction)),
direction);
/// <summary>
/// Keyword not supported: '{keyword}'.
/// </summary>
public static string KeywordNotSupported(object keyword)
=> string.Format(
GetString("KeywordNotSupported", nameof(keyword)),
keyword);
/// <summary>
/// Must add values for the following parameters: {parameters}
/// </summary>
public static string MissingParameters(object parameters)
=> string.Format(
GetString("MissingParameters", nameof(parameters)),
parameters);
/// <summary>
/// No data exists for the row/column.
/// </summary>
public static string NoData
=> GetString("NoData");
/// <summary>
/// ConnectionString must be set before Open can be called.
/// </summary>
public static string OpenRequiresSetConnectionString
=> GetString("OpenRequiresSetConnectionString");
/// <summary>
/// SqliteConnection does not support nested transactions.
/// </summary>
public static string ParallelTransactionsNotSupported
=> GetString("ParallelTransactionsNotSupported");
/// <summary>
/// A SqliteParameter with ParameterName '{parameterName}' is not contained by this SqliteParameterCollection.
/// </summary>
public static string ParameterNotFound(object parameterName)
=> string.Format(
GetString("ParameterNotFound", nameof(parameterName)),
parameterName);
/// <summary>
/// {propertyName} must be set.
/// </summary>
public static string RequiresSet(object propertyName)
=> string.Format(
GetString("RequiresSet", nameof(propertyName)),
propertyName);
/// <summary>
/// This SqliteTransaction has completed; it is no longer usable.
/// </summary>
public static string TransactionCompleted
=> GetString("TransactionCompleted");
/// <summary>
/// The transaction object is not associated with the connection object.
/// </summary>
public static string TransactionConnectionMismatch
=> GetString("TransactionConnectionMismatch");
/// <summary>
/// Execute requires the command to have a transaction object when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized.
/// </summary>
public static string TransactionRequired
=> GetString("TransactionRequired");
/// <summary>
/// No mapping exists from object type {typeName} to a known managed provider native type.
/// </summary>
public static string UnknownDataType(object typeName)
=> string.Format(
GetString("UnknownDataType", nameof(typeName)),
typeName);
/// <summary>
/// SQLite Error {errorCode}: '{message}'.
/// </summary>
public static string SqliteNativeError(object errorCode, object message)
=> string.Format(
GetString("SqliteNativeError", nameof(errorCode), nameof(message)),
errorCode, message);
/// <summary>
/// For more information on this error code see http://sqlite.org/rescode.html
/// </summary>
public static string DefaultNativeError
=> GetString("DefaultNativeError");
/// <summary>
/// Cannot bind the value for parameter '{parameterName}' because multiple matching parameters were found in the command text. Specify the parameter name with the symbol prefix, e.g. '@{parameterName}'.
/// </summary>
public static string AmbiguousParameterName(object parameterName)
=> string.Format(
GetString("AmbiguousParameterName", nameof(parameterName)),
parameterName);
/// <summary>
/// The SQLite library is already loaded. UseWinSqlite3 must be called before using SQLite.
/// </summary>
public static string AlreadyLoaded
=> GetString("AlreadyLoaded");
/// <summary>
/// The {enumType} enumeration value, {value}, is invalid.
/// </summary>
public static string InvalidEnumValue(object enumType, object value)
=> string.Format(
GetString("InvalidEnumValue", nameof(enumType), nameof(value)),
enumType, value);
/// <summary>
/// Cannot convert object of type '{sourceType}' to object of type '{targetType}'.
/// </summary>
public static string ConvertFailed(object sourceType, object targetType)
=> string.Format(
GetString("ConvertFailed", nameof(sourceType), nameof(targetType)),
sourceType, targetType);
/// <summary>
/// Cannot store 'NaN' values.
/// </summary>
public static string CannotStoreNaN
=> GetString("CannotStoreNaN");
/// <summary>
/// An open reader is already associated with this command. Close it before opening a new one.
/// </summary>
public static string DataReaderOpen
=> GetString("DataReaderOpen");
/// <summary>
/// An open reader is associated with this command. Close it before changing the {propertyName} property.
/// </summary>
public static string SetRequiresNoOpenReader(object propertyName)
=> string.Format(
GetString("SetRequiresNoOpenReader", nameof(propertyName)),
propertyName);
/// <summary>
/// The data is NULL at ordinal {ordinal}. This method can't be called on NULL values. Check using IsDBNull before calling.
/// </summary>
public static string CalledOnNullValue(object ordinal)
=> string.Format(
GetString("CalledOnNullValue", nameof(ordinal)),
ordinal);
/// <summary>
/// The SQL function '{function}' was called with a NULL argument at ordinal {ordinal}. Create the function using a Nullable parameter or rewrite your query to avoid passing NULL.
/// </summary>
public static string UDFCalledWithNull(object function, object ordinal)
=> string.Format(
GetString("UDFCalledWithNull", nameof(function), nameof(ordinal)),
function, ordinal);
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);
for (var i = 0; i < formatterNames.Length; i++)
{
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
}
return value;
}
}
}

Просмотреть файл

@ -0,0 +1,4 @@
<#
Session["ResourceFile"] = "Resources.resx";
#>
<#@ include file="..\..\..\tools\SqliteResources.tt" #>

Просмотреть файл

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CallRequiresOpenConnection" xml:space="preserve">
<value>{methodName} can only be called when the connection is open.</value>
</data>
<data name="CallRequiresSetCommandText" xml:space="preserve">
<value>CommandText must be set before {methodName} can be called.</value>
</data>
<data name="ConnectionStringRequiresClosedConnection" xml:space="preserve">
<value>ConnectionString cannot be set when the connection is open.</value>
</data>
<data name="DataReaderClosed" xml:space="preserve">
<value>Invalid attempt to call {operation} when reader is closed.</value>
</data>
<data name="InvalidCacheMode" xml:space="preserve">
<value>The cache mode '{mode}' is invalid.</value>
</data>
<data name="InvalidCommandBehavior" xml:space="preserve">
<value>The CommandBehavior '{behavior}' is invalid.</value>
</data>
<data name="InvalidCommandType" xml:space="preserve">
<value>The CommandType '{commandType}' is invalid.</value>
</data>
<data name="InvalidIsolationLevel" xml:space="preserve">
<value>The IsolationLevel '{isolationLevel}' is invalid.</value>
</data>
<data name="InvalidParameterDirection" xml:space="preserve">
<value>The ParameterDirection '{direction}' is invalid.</value>
</data>
<data name="KeywordNotSupported" xml:space="preserve">
<value>Keyword not supported: '{keyword}'.</value>
</data>
<data name="MissingParameters" xml:space="preserve">
<value>Must add values for the following parameters: {parameters}</value>
</data>
<data name="NoData" xml:space="preserve">
<value>No data exists for the row/column.</value>
</data>
<data name="OpenRequiresSetConnectionString" xml:space="preserve">
<value>ConnectionString must be set before Open can be called.</value>
</data>
<data name="ParallelTransactionsNotSupported" xml:space="preserve">
<value>SqliteConnection does not support nested transactions.</value>
</data>
<data name="ParameterNotFound" xml:space="preserve">
<value>A SqliteParameter with ParameterName '{parameterName}' is not contained by this SqliteParameterCollection.</value>
</data>
<data name="RequiresSet" xml:space="preserve">
<value>{propertyName} must be set.</value>
</data>
<data name="TransactionCompleted" xml:space="preserve">
<value>This SqliteTransaction has completed; it is no longer usable.</value>
</data>
<data name="TransactionConnectionMismatch" xml:space="preserve">
<value>The transaction object is not associated with the connection object.</value>
</data>
<data name="TransactionRequired" xml:space="preserve">
<value>Execute requires the command to have a transaction object when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized.</value>
</data>
<data name="UnknownDataType" xml:space="preserve">
<value>No mapping exists from object type {typeName} to a known managed provider native type.</value>
</data>
<data name="SqliteNativeError" xml:space="preserve">
<value>SQLite Error {errorCode}: '{message}'.</value>
</data>
<data name="DefaultNativeError" xml:space="preserve">
<value>For more information on this error code see http://sqlite.org/rescode.html</value>
</data>
<data name="AmbiguousParameterName" xml:space="preserve">
<value>Cannot bind the value for parameter '{parameterName}' because multiple matching parameters were found in the command text. Specify the parameter name with the symbol prefix, e.g. '@{parameterName}'.</value>
</data>
<data name="AlreadyLoaded" xml:space="preserve">
<value>The SQLite library is already loaded. UseWinSqlite3 must be called before using SQLite.</value>
</data>
<data name="InvalidEnumValue" xml:space="preserve">
<value>The {enumType} enumeration value, {value}, is invalid.</value>
</data>
<data name="ConvertFailed" xml:space="preserve">
<value>Cannot convert object of type '{sourceType}' to object of type '{targetType}'.</value>
</data>
<data name="CannotStoreNaN" xml:space="preserve">
<value>Cannot store 'NaN' values.</value>
</data>
<data name="DataReaderOpen" xml:space="preserve">
<value>An open reader is already associated with this command. Close it before opening a new one.</value>
</data>
<data name="SetRequiresNoOpenReader" xml:space="preserve">
<value>An open reader is associated with this command. Close it before changing the {propertyName} property.</value>
</data>
<data name="CalledOnNullValue" xml:space="preserve">
<value>The data is NULL at ordinal {ordinal}. This method can't be called on NULL values. Check using IsDBNull before calling.</value>
</data>
<data name="UDFCalledWithNull" xml:space="preserve">
<value>The SQL function '{function}' was called with a NULL argument at ordinal {ordinal}. Create the function using a Nullable parameter or rewrite your query to avoid passing NULL.</value>
</data>
</root>

Просмотреть файл

@ -0,0 +1,28 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Represents the caching modes that can be used when creating a new <see cref="SqliteConnection" />.
/// </summary>
/// <seealso href="http://sqlite.org/sharedcache.html">SQLite Shared-Cache Mode</seealso>
public enum SqliteCacheMode
{
/// <summary>
/// Default mode.
/// </summary>
Default,
/// <summary>
/// Private-cache mode. Each connection uses a private cache.
/// </summary>
Private,
/// <summary>
/// Shared-cache mode. Connections share a cache. This mode can change the behavior of transaction and table
/// locking.
/// </summary>
Shared
}
}

Просмотреть файл

@ -0,0 +1,588 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Represents a SQL statement to be executed against a SQLite database.
/// </summary>
public class SqliteCommand : DbCommand
{
private readonly Lazy<SqliteParameterCollection> _parameters = new Lazy<SqliteParameterCollection>(
() => new SqliteParameterCollection());
private readonly ICollection<sqlite3_stmt> _preparedStatements = new List<sqlite3_stmt>();
private SqliteConnection _connection;
private string _commandText;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteCommand" /> class.
/// </summary>
public SqliteCommand()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SqliteCommand" /> class.
/// </summary>
/// <param name="commandText">The SQL to execute against the database.</param>
public SqliteCommand(string commandText)
=> CommandText = commandText;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteCommand" /> class.
/// </summary>
/// <param name="commandText">The SQL to execute against the database.</param>
/// <param name="connection">The connection used by the command.</param>
public SqliteCommand(string commandText, SqliteConnection connection)
: this(commandText)
{
Connection = connection;
CommandTimeout = connection.DefaultTimeout;
}
/// <summary>
/// Initializes a new instance of the <see cref="SqliteCommand" /> class.
/// </summary>
/// <param name="commandText">The SQL to execute against the database.</param>
/// <param name="connection">The connection used by the command.</param>
/// <param name="transaction">The transaction within which the command executes.</param>
public SqliteCommand(string commandText, SqliteConnection connection, SqliteTransaction transaction)
: this(commandText, connection)
=> Transaction = transaction;
/// <summary>
/// Gets or sets a value indicating how <see cref="CommandText" /> is interpreted. Only
/// <see cref="CommandType.Text" /> is supported.
/// </summary>
/// <value>A value indicating how <see cref="CommandText" /> is interpreted.</value>
public override CommandType CommandType
{
get => CommandType.Text;
set
{
if (value != CommandType.Text)
{
throw new ArgumentException(Resources.InvalidCommandType(value));
}
}
}
/// <summary>
/// Gets or sets the SQL to execute against the database.
/// </summary>
/// <value>The SQL to execute against the database.</value>
public override string CommandText
{
get => _commandText;
set
{
if (DataReader != null)
{
throw new InvalidOperationException(Resources.SetRequiresNoOpenReader(nameof(CommandText)));
}
if (value != _commandText)
{
DisposePreparedStatements();
_commandText = value;
}
}
}
/// <summary>
/// Gets or sets the connection used by the command.
/// </summary>
/// <value>The connection used by the command.</value>
public new virtual SqliteConnection Connection
{
get => _connection;
set
{
if (DataReader != null)
{
throw new InvalidOperationException(Resources.SetRequiresNoOpenReader(nameof(Connection)));
}
if (value != _connection)
{
DisposePreparedStatements();
_connection?.RemoveCommand(this);
_connection = value;
value?.AddCommand(this);
}
}
}
/// <summary>
/// Gets or sets the connection used by the command. Must be a <see cref="SqliteConnection" />.
/// </summary>
/// <value>The connection used by the command.</value>
protected override DbConnection DbConnection
{
get => Connection;
set => Connection = (SqliteConnection)value;
}
/// <summary>
/// Gets or sets the transaction within which the command executes.
/// </summary>
/// <value>The transaction within which the command executes.</value>
public new virtual SqliteTransaction Transaction { get; set; }
/// <summary>
/// Gets or sets the transaction within which the command executes. Must be a <see cref="SqliteTransaction" />.
/// </summary>
/// <value>The transaction within which the command executes.</value>
protected override DbTransaction DbTransaction
{
get => Transaction;
set => Transaction = (SqliteTransaction)value;
}
/// <summary>
/// Gets the collection of parameters used by the command.
/// </summary>
/// <value>The collection of parameters used by the command.</value>
public new virtual SqliteParameterCollection Parameters
=> _parameters.Value;
/// <summary>
/// Gets the collection of parameters used by the command.
/// </summary>
/// <value>The collection of parameters used by the command.</value>
protected override DbParameterCollection DbParameterCollection
=> Parameters;
/// <summary>
/// Gets or sets the number of seconds to wait before terminating the attempt to execute the command. Defaults to 30.
/// </summary>
/// <value>The number of seconds to wait before terminating the attempt to execute the command.</value>
/// <remarks>
/// The timeout is used when the command is waiting to obtain a lock on the table.
/// </remarks>
public override int CommandTimeout { get; set; } = 30;
/// <summary>
/// Gets or sets a value indicating whether the command should be visible in an interface control.
/// </summary>
/// <value>A value indicating whether the command should be visible in an interface control.</value>
public override bool DesignTimeVisible { get; set; }
/// <summary>
/// Gets or sets a value indicating how the results are applied to the row being updated.
/// </summary>
/// <value>A value indicating how the results are applied to the row being updated.</value>
public override UpdateRowSource UpdatedRowSource { get; set; }
/// <summary>
/// Gets or sets the data reader currently being used by the command, or null if none.
/// </summary>
/// <value>The data reader currently being used by the command.</value>
protected internal virtual SqliteDataReader DataReader { get; set; }
/// <summary>
/// Releases any resources used by the connection and closes it.
/// </summary>
/// <param name="disposing">
/// true to release managed and unmanaged resources; false to release only unmanaged resources.
/// </param>
protected override void Dispose(bool disposing)
{
DisposePreparedStatements(disposing);
base.Dispose(disposing);
}
/// <summary>
/// Creates a new parameter.
/// </summary>
/// <returns>The new parameter.</returns>
public new virtual SqliteParameter CreateParameter()
=> new SqliteParameter();
/// <summary>
/// Creates a new parameter.
/// </summary>
/// <returns>The new parameter.</returns>
protected override DbParameter CreateDbParameter()
=> CreateParameter();
/// <summary>
/// Creates a prepared version of the command on the database.
/// </summary>
public override void Prepare()
{
if (_connection?.State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(Prepare)));
}
if (string.IsNullOrEmpty(_commandText))
{
throw new InvalidOperationException(Resources.CallRequiresSetCommandText(nameof(Prepare)));
}
if (_preparedStatements.Count != 0)
{
return;
}
var timer = Stopwatch.StartNew();
try
{
using (var enumerator = PrepareAndEnumerateStatements(timer).GetEnumerator())
{
while (enumerator.MoveNext())
{
}
}
}
catch
{
DisposePreparedStatements();
throw;
}
}
/// <summary>
/// Executes the <see cref="CommandText" /> against the database and returns a data reader.
/// </summary>
/// <returns>The data reader.</returns>
/// <exception cref="SqliteException">A SQLite error occurs during execution.</exception>
public new virtual SqliteDataReader ExecuteReader()
=> ExecuteReader(CommandBehavior.Default);
/// <summary>
/// Executes the <see cref="CommandText" /> against the database and returns a data reader.
/// </summary>
/// <param name="behavior">
/// A description of the results of the query and its effect on the database.
/// <para>
/// Only <see cref="CommandBehavior.Default" />, <see cref="CommandBehavior.SequentialAccess" />,
/// <see cref="CommandBehavior.SingleResult" />, <see cref="CommandBehavior.SingleRow" />, and
/// <see cref="CommandBehavior.CloseConnection" /> are supported.
/// </para>
/// </param>
/// <returns>The data reader.</returns>
/// <exception cref="SqliteException">A SQLite error occurs during execution.</exception>
public new virtual SqliteDataReader ExecuteReader(CommandBehavior behavior)
{
if ((behavior & ~(CommandBehavior.Default | CommandBehavior.SequentialAccess | CommandBehavior.SingleResult
| CommandBehavior.SingleRow | CommandBehavior.CloseConnection)) != 0)
{
throw new ArgumentException(Resources.InvalidCommandBehavior(behavior));
}
if (DataReader != null)
{
throw new InvalidOperationException(Resources.DataReaderOpen);
}
if (_connection?.State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteReader)));
}
if (string.IsNullOrEmpty(_commandText))
{
throw new InvalidOperationException(Resources.CallRequiresSetCommandText(nameof(ExecuteReader)));
}
if (Transaction != _connection.Transaction)
{
throw new InvalidOperationException(
Transaction == null
? Resources.TransactionRequired
: Resources.TransactionConnectionMismatch);
}
if (_connection.Transaction?.ExternalRollback == true)
{
throw new InvalidOperationException(Resources.TransactionCompleted);
}
var hasChanges = false;
var changes = 0;
int rc;
var stmts = new Queue<(sqlite3_stmt, bool)>();
var unprepared = _preparedStatements.Count == 0;
var timer = Stopwatch.StartNew();
try
{
foreach (var stmt in unprepared
? PrepareAndEnumerateStatements(timer)
: _preparedStatements)
{
var boundParams = 0;
if (_parameters.IsValueCreated)
{
boundParams = _parameters.Value.Bind(stmt);
}
var expectedParams = raw.sqlite3_bind_parameter_count(stmt);
if (expectedParams != boundParams)
{
var unboundParams = new List<string>();
for (var i = 1; i <= expectedParams; i++)
{
var name = raw.sqlite3_bind_parameter_name(stmt, i);
if (_parameters.IsValueCreated
|| !_parameters.Value.Cast<SqliteParameter>().Any(p => p.ParameterName == name))
{
unboundParams.Add(name);
}
}
throw new InvalidOperationException(Resources.MissingParameters(string.Join(", ", unboundParams)));
}
while (IsBusy(rc = raw.sqlite3_step(stmt)))
{
if (timer.ElapsedMilliseconds >= CommandTimeout * 1000)
{
break;
}
raw.sqlite3_reset(stmt);
// TODO: Consider having an async path that uses Task.Delay()
Thread.Sleep(150);
}
SqliteException.ThrowExceptionForRC(rc, _connection.Handle);
if (rc == raw.SQLITE_ROW
// NB: This is only a heuristic to separate SELECT statements from INSERT/UPDATE/DELETE statements.
// It will result in false positives, but it's the best we can do without re-parsing SQL
|| raw.sqlite3_stmt_readonly(stmt) != 0)
{
stmts.Enqueue((stmt, rc != raw.SQLITE_DONE));
}
else
{
raw.sqlite3_reset(stmt);
hasChanges = true;
changes += raw.sqlite3_changes(_connection.Handle);
}
}
}
catch when (unprepared)
{
DisposePreparedStatements();
throw;
}
var closeConnection = (behavior & CommandBehavior.CloseConnection) != 0;
return DataReader = new SqliteDataReader(this, stmts, hasChanges ? changes : -1, closeConnection);
}
/// <summary>
/// Executes the <see cref="CommandText" /> against the database and returns a data reader.
/// </summary>
/// <param name="behavior">A description of query's results and its effect on the database.</param>
/// <returns>The data reader.</returns>
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
=> ExecuteReader(behavior);
/// <summary>
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
/// </summary>
/// <returns>A task representing the asynchronous operation.</returns>
/// <remarks>
/// SQLite does not support asynchronous execution. Use write-ahead logging instead.
/// </remarks>
/// <seealso href="http://sqlite.org/wal.html">Write-Ahead Logging</seealso>
public new virtual Task<SqliteDataReader> ExecuteReaderAsync()
=> ExecuteReaderAsync(CommandBehavior.Default, CancellationToken.None);
/// <summary>
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task representing the asynchronous operation.</returns>
/// <remarks>
/// SQLite does not support asynchronous execution. Use write-ahead logging instead.
/// </remarks>
/// <seealso href="http://sqlite.org/wal.html">Write-Ahead Logging</seealso>
public new virtual Task<SqliteDataReader> ExecuteReaderAsync(CancellationToken cancellationToken)
=> ExecuteReaderAsync(CommandBehavior.Default, cancellationToken);
/// <summary>
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
/// </summary>
/// <param name="behavior">A description of query's results and its effect on the database.</param>
/// <returns>A task representing the asynchronous operation.</returns>
/// <remarks>
/// SQLite does not support asynchronous execution. Use write-ahead logging instead.
/// </remarks>
/// <seealso href="http://sqlite.org/wal.html">Write-Ahead Logging</seealso>
public new virtual Task<SqliteDataReader> ExecuteReaderAsync(CommandBehavior behavior)
=> ExecuteReaderAsync(behavior, CancellationToken.None);
/// <summary>
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
/// </summary>
/// <param name="behavior">A description of query's results and its effect on the database.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task representing the asynchronous operation.</returns>
/// <remarks>
/// SQLite does not support asynchronous execution. Use write-ahead logging instead.
/// </remarks>
/// <seealso href="http://sqlite.org/wal.html">Write-Ahead Logging</seealso>
public new virtual Task<SqliteDataReader> ExecuteReaderAsync(
CommandBehavior behavior,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
return Task.FromResult(ExecuteReader(behavior));
}
/// <summary>
/// Executes the <see cref="CommandText" /> asynchronously against the database and returns a data reader.
/// </summary>
/// <param name="behavior">A description of query's results and its effect on the database.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task representing the asynchronous operation.</returns>
protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(
CommandBehavior behavior,
CancellationToken cancellationToken)
=> await ExecuteReaderAsync(behavior, cancellationToken);
/// <summary>
/// Executes the <see cref="CommandText" /> against the database.
/// </summary>
/// <returns>The number of rows inserted, updated, or deleted. -1 for SELECT statements.</returns>
/// <exception cref="SqliteException">A SQLite error occurs during execution.</exception>
public override int ExecuteNonQuery()
{
if (_connection?.State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteNonQuery)));
}
if (_commandText == null)
{
throw new InvalidOperationException(Resources.CallRequiresSetCommandText(nameof(ExecuteNonQuery)));
}
var reader = ExecuteReader();
reader.Dispose();
return reader.RecordsAffected;
}
/// <summary>
/// Executes the <see cref="CommandText" /> against the database and returns the result.
/// </summary>
/// <returns>The first column of the first row of the results, or null if no results.</returns>
/// <exception cref="SqliteException">A SQLite error occurs during execution.</exception>
public override object ExecuteScalar()
{
if (_connection?.State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteScalar)));
}
if (_commandText == null)
{
throw new InvalidOperationException(Resources.CallRequiresSetCommandText(nameof(ExecuteScalar)));
}
using (var reader = ExecuteReader())
{
return reader.Read()
? reader.GetValue(0)
: null;
}
}
/// <summary>
/// Attempts to cancel the execution of the command. Does nothing.
/// </summary>
public override void Cancel()
{
}
private IEnumerable<sqlite3_stmt> PrepareAndEnumerateStatements(Stopwatch timer)
{
int rc;
sqlite3_stmt stmt;
var tail = _commandText;
do
{
string nextTail;
while (IsBusy(rc = raw.sqlite3_prepare_v2(_connection.Handle, tail, out stmt, out nextTail)))
{
if (timer.ElapsedMilliseconds >= CommandTimeout * 1000)
{
break;
}
Thread.Sleep(150);
}
tail = nextTail;
SqliteException.ThrowExceptionForRC(rc, _connection.Handle);
// Statement was empty, white space, or a comment
if (stmt.ptr == IntPtr.Zero)
{
if (!string.IsNullOrEmpty(tail))
{
continue;
}
break;
}
_preparedStatements.Add(stmt);
yield return stmt;
}
while (!string.IsNullOrEmpty(tail));
}
private void DisposePreparedStatements(bool disposing = true)
{
if (disposing
&& DataReader != null)
{
DataReader.Dispose();
DataReader = null;
}
if (_preparedStatements != null)
{
foreach (var stmt in _preparedStatements)
{
stmt.Dispose();
}
_preparedStatements.Clear();
}
}
private static bool IsBusy(int rc)
=> rc == raw.SQLITE_LOCKED
|| rc == raw.SQLITE_BUSY
|| rc == raw.SQLITE_LOCKED_SHAREDCACHE;
}
}

Просмотреть файл

@ -0,0 +1,999 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.Data.Sqlite
{
partial class SqliteConnection
{
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<TAccumulate>(string name, Func<TAccumulate, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 0, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a)), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, TAccumulate>(string name, Func<TAccumulate, T1, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 1, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, TAccumulate>(string name, Func<TAccumulate, T1, T2, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 2, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 3, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 4, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 5, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 6, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 7, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 8, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 9, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 10, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 11, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 12, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 13, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 14, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate>(string name, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 15, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<TAccumulate>(string name, Func<TAccumulate, object[], TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, -1, default, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, GetValues(r))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 0, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a)), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 1, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 2, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 3, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 4, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 5, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 6, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 7, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 8, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 9, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 10, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 11, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 12, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 13, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 14, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, 15, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<TAccumulate>(string name, TAccumulate seed, Func<TAccumulate, object[], TAccumulate> func, bool isDeterministic = false)
=> CreateAggregateCore(name, -1, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, GetValues(r))), a => a, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 0, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a)), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 1, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 2, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 3, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 4, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 5, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 6, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 7, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 8, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 9, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 10, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 11, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 12, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 13, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 14, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, 15, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), resultSelector, isDeterministic);
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="seed">The initial accumulator value.</param>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<TAccumulate, TResult>(string name, TAccumulate seed, Func<TAccumulate, object[], TAccumulate> func, Func<TAccumulate, TResult> resultSelector, bool isDeterministic = false)
=> CreateAggregateCore(name, -1, seed, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, GetValues(r))), resultSelector, isDeterministic);
}
}

Просмотреть файл

@ -0,0 +1,142 @@
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.Data.Sqlite
{
partial class SqliteConnection
{
<#
var ordinal = new[] { "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth" };
var first = true;
foreach (var resultSelector in new[] { false, true })
{
var resultTypeArgument = resultSelector
? ", TResult"
: "";
var resultSelectorParameter = resultSelector
? ", Func<TAccumulate, TResult> resultSelector"
: "";
var resultSelectorArgument = resultSelector
? "resultSelector"
: "a => a";
foreach (var seed in new[] { false, true })
{
if (resultSelector && !seed)
{
continue;
}
var seedParameter = seed
? ", TAccumulate seed"
: "";
var seedArgument = seed
? "seed"
: "default";
for (var arity = 0; arity <= 15; arity++)
{
var parameterTypeArgumentList = Enumerable.Range(1, arity).Select(j => "T" + j).ToList();
var typeArgumentsList = new List<string>();
typeArgumentsList.AddRange(parameterTypeArgumentList);
typeArgumentsList.Add("TAccumulate");
if (resultSelector)
{
typeArgumentsList.Add("TResult");
}
var typeArguments = String.Join(", ", typeArgumentsList);
var lambdaTypeArgumentList = new List<string>();
lambdaTypeArgumentList.Add("TAccumulate");
lambdaTypeArgumentList.AddRange(parameterTypeArgumentList);
lambdaTypeArgumentList.Add("TAccumulate");
var lambdaTypeArguments = string.Join(", ", lambdaTypeArgumentList);
var lambdaArgumentsList = new List<string>();
lambdaArgumentsList.Add("a");
for (var i = 0; i < parameterTypeArgumentList.Count; i++)
{
lambdaArgumentsList.Add("r.GetFieldValue<" + parameterTypeArgumentList[i] + ">(" + i + ")");
}
var lambdaArguments = string.Join(", ", lambdaArgumentsList);
if (first)
{
first = false;
}
else
{
WriteLine("");
}
#>
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
<# for (var i = 1; i <= arity; i++) { #>
/// <typeparam name="T<#= i #>">The type of the <#= ordinal[i - 1] #> parameter of the function.</typeparam>
<# } #>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
<# if (resultSelector) { #>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
<# } #>
/// <param name="name">The name of the SQL function.</param>
<# if (seed) { #>
/// <param name="seed">The initial accumulator value.</param>
<# } #>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
<# if (resultSelector) { #>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
<# } #>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<<#= typeArguments #>>(string name<#= seedParameter #>, Func<<#= lambdaTypeArguments #>> func<#= resultSelectorParameter #>, bool isDeterministic = false)
=> CreateAggregateCore(name, <#= arity #>, <#= seedArgument #>, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(<#= lambdaArguments #>)), <#= resultSelectorArgument #>, isDeterministic);
<#
}
#>
/// <summary>
/// Creates or redefines an aggregate SQL function.
/// </summary>
/// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
<# if (resultSelector) { #>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
<# } #>
/// <param name="name">The name of the SQL function.</param>
<# if (seed) { #>
/// <param name="seed">The initial accumulator value.</param>
<# } #>
/// <param name="func">An accumulator function to be invoked on each element. Pass null to delete a function.</param>
<# if (resultSelector) { #>
/// <param name="resultSelector">
/// A function to transform the final accumulator value into the result value. Pass null to
/// delete a function.
/// </param>
<# } #>
/// <param name="isDeterministic">Flag indicating whether the aggregate is deterministic.</param>
public virtual void CreateAggregate<TAccumulate<#= resultTypeArgument #>>(string name<#= seedParameter #>, Func<TAccumulate, object[], TAccumulate> func<#= resultSelectorParameter #>, bool isDeterministic = false)
=> CreateAggregateCore(name, -1, <#= seedArgument #>, IfNotNull<TAccumulate, TAccumulate>(func, (a, r) => func(a, GetValues(r))), <#= resultSelectorArgument #>, isDeterministic);
<#
}
}
#>
}
}

Просмотреть файл

@ -0,0 +1,650 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.Data.Sqlite
{
partial class SqliteConnection
{
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TResult>(string name, Func<TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 0, null, IfNotNull<object, TResult>(function, (s, r) => function()), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, TResult>(string name, Func<T1, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 1, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, TResult>(string name, Func<T1, T2, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 2, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, TResult>(string name, Func<T1, T2, T3, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 3, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, TResult>(string name, Func<T1, T2, T3, T4, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 4, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, TResult>(string name, Func<T1, T2, T3, T4, T5, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 5, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 6, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 7, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 8, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 9, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 10, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 11, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 12, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 13, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 14, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 15, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
/// <typeparam name="T16">The type of the sixteenth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>(string name, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 16, null, IfNotNull<object, TResult>(function, (s, r) => function(r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14), r.GetFieldValue<T16>(15))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TResult>(string name, Func<object[], TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, -1, null, IfNotNull<object, TResult>(function, (s, r) => function(GetValues(r))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, TResult>(string name, TState state, Func<TState, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 0, state, IfNotNull<TState, TResult>(function, (s, r) => function(s)), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, TResult>(string name, TState state, Func<TState, T1, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 1, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, TResult>(string name, TState state, Func<TState, T1, T2, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 2, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, TResult>(string name, TState state, Func<TState, T1, T2, T3, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 3, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 4, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 5, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 6, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 7, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 8, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 9, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 10, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 11, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 12, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 13, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 14, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="T1">The type of the first parameter of the function.</typeparam>
/// <typeparam name="T2">The type of the second parameter of the function.</typeparam>
/// <typeparam name="T3">The type of the third parameter of the function.</typeparam>
/// <typeparam name="T4">The type of the fourth parameter of the function.</typeparam>
/// <typeparam name="T5">The type of the fifth parameter of the function.</typeparam>
/// <typeparam name="T6">The type of the sixth parameter of the function.</typeparam>
/// <typeparam name="T7">The type of the seventh parameter of the function.</typeparam>
/// <typeparam name="T8">The type of the eighth parameter of the function.</typeparam>
/// <typeparam name="T9">The type of the ninth parameter of the function.</typeparam>
/// <typeparam name="T10">The type of the tenth parameter of the function.</typeparam>
/// <typeparam name="T11">The type of the eleventh parameter of the function.</typeparam>
/// <typeparam name="T12">The type of the twelfth parameter of the function.</typeparam>
/// <typeparam name="T13">The type of the thirteenth parameter of the function.</typeparam>
/// <typeparam name="T14">The type of the fourteenth parameter of the function.</typeparam>
/// <typeparam name="T15">The type of the fifteenth parameter of the function.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(string name, TState state, Func<TState, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, 15, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, r.GetFieldValue<T1>(0), r.GetFieldValue<T2>(1), r.GetFieldValue<T3>(2), r.GetFieldValue<T4>(3), r.GetFieldValue<T5>(4), r.GetFieldValue<T6>(5), r.GetFieldValue<T7>(6), r.GetFieldValue<T8>(7), r.GetFieldValue<T9>(8), r.GetFieldValue<T10>(9), r.GetFieldValue<T11>(10), r.GetFieldValue<T12>(11), r.GetFieldValue<T13>(12), r.GetFieldValue<T14>(13), r.GetFieldValue<T15>(14))), isDeterministic);
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
/// <typeparam name="TState">The type of the state.</typeparam>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
/// <param name="state">An object available during each invocation of the function.</param>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<TState, TResult>(string name, TState state, Func<TState, object[], TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, -1, state, IfNotNull<TState, TResult>(function, (s, r) => function(s, GetValues(r))), isDeterministic);
}
}

Просмотреть файл

@ -0,0 +1,124 @@
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.Data.Sqlite
{
partial class SqliteConnection
{
<#
var ordinal = new[] { "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth", "sixteenth" };
var first = true;
foreach (var state in new[] { false, true })
{
var maxArguments = state
? 15
: 16;
var stateTypeArgument = state
? "TState, "
: "";
var stateParameter = state
? "TState state, "
: "";
var stateArgument = state
? "state"
: "null";
var stateParameterType = state
? "TState"
: "object";
var lambdaStateArgument = state
? "s, "
: "";
for (var arity = 0; arity <= maxArguments; arity++)
{
var parameterTypeArgumentList = Enumerable.Range(1, arity).Select(j => "T" + j).ToList();
var typeArgumentsList = new List<string>();
if (state)
{
typeArgumentsList.Add("TState");
}
typeArgumentsList.AddRange(parameterTypeArgumentList);
typeArgumentsList.Add("TResult");
var typeArguments = String.Join(", ", typeArgumentsList);
var lambdaArgumentsList = new List<string>();
if (state)
{
lambdaArgumentsList.Add("s");
}
for (var i = 0; i < parameterTypeArgumentList.Count; i++)
{
lambdaArgumentsList.Add("r.GetFieldValue<" + parameterTypeArgumentList[i] + ">(" + i + ")");
}
var lambdaArguments = string.Join(", ", lambdaArgumentsList);
if (first)
{
first = false;
}
else
{
WriteLine("");
}
#>
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
<# if (state) { #>
/// <typeparam name="TState">The type of the state.</typeparam>
<# } #>
<# for (var i = 1; i <= arity; i++) { #>
/// <typeparam name="T<#= i #>">The type of the <#= ordinal[i - 1] #> parameter of the function.</typeparam>
<# } #>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
<# if (state) { #>
/// <param name="state">An object available during each invocation of the function.</param>
<# } #>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<<#= typeArguments #>>(string name, <#= stateParameter #>Func<<#= typeArguments #>> function, bool isDeterministic = false)
=> CreateFunctionCore(name, <#= arity #>, <#= stateArgument #>, IfNotNull<<#= stateParameterType #>, TResult>(function, (s, r) => function(<#= lambdaArguments #>)), isDeterministic);
<#
}
#>
/// <summary>
/// Creates or redefines a SQL function.
/// </summary>
<# if (state) { #>
/// <typeparam name="TState">The type of the state.</typeparam>
<# } #>
/// <typeparam name="TResult">The type of the resulting value.</typeparam>
/// <param name="name">The name of the SQL function.</param>
<# if (state) { #>
/// <param name="state">An object available during each invocation of the function.</param>
<# } #>
/// <param name="function">The function to be invoked.</param>
/// <param name="isDeterministic">Flag indicating whether the function is deterministic.</param>
public virtual void CreateFunction<<#= stateTypeArgument #>TResult>(string name, <#= stateParameter #>Func<<#= stateTypeArgument #>object[], TResult> function, bool isDeterministic = false)
=> CreateFunctionCore(name, -1, <#= stateArgument #>, IfNotNull<<#= stateParameterType #>, TResult>(function, (s, r) => function(<#= lambdaStateArgument #>GetValues(r))), isDeterministic);
<#
}
#>
}
}

Просмотреть файл

@ -0,0 +1,621 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.IO;
using Microsoft.Data.Sqlite.Properties;
using Microsoft.Data.Sqlite.Utilities;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Represents a connection to a SQLite database.
/// </summary>
public partial class SqliteConnection : DbConnection
{
private const string MainDatabaseName = "main";
private readonly IList<WeakReference<SqliteCommand>> _commands = new List<WeakReference<SqliteCommand>>();
private string _connectionString;
private ConnectionState _state;
private sqlite3 _db;
static SqliteConnection()
=> BundleInitializer.Initialize();
/// <summary>
/// Initializes a new instance of the <see cref="SqliteConnection" /> class.
/// </summary>
public SqliteConnection()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SqliteConnection" /> class.
/// </summary>
/// <param name="connectionString">The string used to open the connection.</param>
/// <seealso cref="SqliteConnectionStringBuilder" />
public SqliteConnection(string connectionString)
=> ConnectionString = connectionString;
/// <summary>
/// Gets a handle to underlying database connection.
/// </summary>
/// <value>A handle to underlying database connection.</value>
/// <seealso href="http://sqlite.org/c3ref/sqlite3.html">Database Connection Handle</seealso>
public virtual sqlite3 Handle
=> _db;
/// <summary>
/// Gets or sets a string used to open the connection.
/// </summary>
/// <value>A string used to open the connection.</value>
/// <seealso cref="SqliteConnectionStringBuilder" />
public override string ConnectionString
{
get => _connectionString;
set
{
if (State != ConnectionState.Closed)
{
throw new InvalidOperationException(Resources.ConnectionStringRequiresClosedConnection);
}
_connectionString = value;
ConnectionStringBuilder = new SqliteConnectionStringBuilder(value);
}
}
internal SqliteConnectionStringBuilder ConnectionStringBuilder { get; set; }
/// <summary>
/// Gets the name of the current database. Always 'main'.
/// </summary>
/// <value>The name of the current database.</value>
public override string Database
=> MainDatabaseName;
/// <summary>
/// Gets the path to the database file. Will be absolute for open connections.
/// </summary>
/// <value>The path to the database file.</value>
public override string DataSource
{
get
{
string dataSource = null;
if (State == ConnectionState.Open)
{
dataSource = raw.sqlite3_db_filename(_db, MainDatabaseName);
}
return dataSource ?? ConnectionStringBuilder.DataSource;
}
}
/// <summary>
/// Gets or sets the default <see cref="SqliteCommand.CommandTimeout"/> value for commands created using
/// this connection. This is also used for internal commands in methods like
/// <see cref="BeginTransaction()"/>.
/// </summary>
/// <value>The default <see cref="SqliteCommand.CommandTimeout"/> value</value>
public virtual int DefaultTimeout { get; set; } = 30;
/// <summary>
/// Gets the version of SQLite used by the connection.
/// </summary>
/// <value>The version of SQLite used by the connection.</value>
public override string ServerVersion
=> raw.sqlite3_libversion();
/// <summary>
/// Gets the current state of the connection.
/// </summary>
/// <value>The current state of the connection.</value>
public override ConnectionState State
=> _state;
/// <summary>
/// Gets the <see cref="DbProviderFactory" /> for this connection.
/// </summary>
/// <value>The <see cref="DbProviderFactory" />.</value>
protected override DbProviderFactory DbProviderFactory
=> SqliteFactory.Instance;
/// <summary>
/// Gets or sets the transaction currently being used by the connection, or null if none.
/// </summary>
/// <value>The transaction currently being used by the connection.</value>
protected internal virtual SqliteTransaction Transaction { get; set; }
private void SetState(ConnectionState value)
{
var originalState = _state;
if (originalState != value)
{
_state = value;
OnStateChange(new StateChangeEventArgs(originalState, value));
}
}
/// <summary>
/// Opens a connection to the database using the value of <see cref="ConnectionString" />. If
/// <c>Mode=ReadWriteCreate</c> is used (the default) the file is created, if it doesn't already exist.
/// </summary>
/// <exception cref="SqliteException">A SQLite error occurs while opening the connection.</exception>
public override void Open()
{
if (State == ConnectionState.Open)
{
return;
}
if (ConnectionString == null)
{
throw new InvalidOperationException(Resources.OpenRequiresSetConnectionString);
}
var filename = ConnectionStringBuilder.DataSource;
var flags = 0;
if (filename.StartsWith("file:", StringComparison.OrdinalIgnoreCase))
{
flags |= raw.SQLITE_OPEN_URI;
}
switch (ConnectionStringBuilder.Mode)
{
case SqliteOpenMode.ReadOnly:
flags |= raw.SQLITE_OPEN_READONLY;
break;
case SqliteOpenMode.ReadWrite:
flags |= raw.SQLITE_OPEN_READWRITE;
break;
case SqliteOpenMode.Memory:
flags |= raw.SQLITE_OPEN_READWRITE | raw.SQLITE_OPEN_CREATE | raw.SQLITE_OPEN_MEMORY;
if ((flags & raw.SQLITE_OPEN_URI) == 0)
{
flags |= raw.SQLITE_OPEN_URI;
filename = "file:" + filename;
}
break;
default:
Debug.Assert(
ConnectionStringBuilder.Mode == SqliteOpenMode.ReadWriteCreate,
"ConnectionStringBuilder.Mode is not ReadWriteCreate");
flags |= raw.SQLITE_OPEN_READWRITE | raw.SQLITE_OPEN_CREATE;
break;
}
switch (ConnectionStringBuilder.Cache)
{
case SqliteCacheMode.Shared:
flags |= raw.SQLITE_OPEN_SHAREDCACHE;
break;
case SqliteCacheMode.Private:
flags |= raw.SQLITE_OPEN_PRIVATECACHE;
break;
default:
Debug.Assert(
ConnectionStringBuilder.Cache == SqliteCacheMode.Default,
"ConnectionStringBuilder.Cache is not Default.");
break;
}
var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory") as string;
if (!string.IsNullOrEmpty(dataDirectory)
&& (flags & raw.SQLITE_OPEN_URI) == 0
&& !filename.Equals(":memory:", StringComparison.OrdinalIgnoreCase)
&& !Path.IsPathRooted(filename))
{
filename = Path.Combine(dataDirectory, filename);
}
var rc = raw.sqlite3_open_v2(filename, out _db, flags, vfs: null);
SqliteException.ThrowExceptionForRC(rc, _db);
SetState(ConnectionState.Open);
}
/// <summary>
/// Closes the connection to the database. Open transactions are rolled back.
/// </summary>
public override void Close()
{
if (_db == null
|| _db.ptr == IntPtr.Zero)
{
return;
}
Transaction?.Dispose();
foreach (var reference in _commands)
{
if (reference.TryGetTarget(out var command))
{
command.Dispose();
}
}
_commands.Clear();
_db.Dispose2();
_db = null;
SetState(ConnectionState.Closed);
}
/// <summary>
/// Releases any resources used by the connection and closes it.
/// </summary>
/// <param name="disposing">
/// true to release managed and unmanaged resources; false to release only unmanaged resources.
/// </param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
Close();
}
base.Dispose(disposing);
}
/// <summary>
/// Creates a new command associated with the connection.
/// </summary>
/// <returns>The new command.</returns>
/// <remarks>
/// The command's <seealso cref="SqliteCommand.Transaction" /> property will also be set to the current
/// transaction.
/// </remarks>
public new virtual SqliteCommand CreateCommand()
=> new SqliteCommand { Connection = this, CommandTimeout = DefaultTimeout, Transaction = Transaction };
/// <summary>
/// Creates a new command associated with the connection.
/// </summary>
/// <returns>The new command.</returns>
protected override DbCommand CreateDbCommand()
=> CreateCommand();
internal void AddCommand(SqliteCommand command)
=> _commands.Add(new WeakReference<SqliteCommand>(command));
internal void RemoveCommand(SqliteCommand command)
{
for (var i = _commands.Count - 1; i >= 0; i--)
{
if (!_commands[i].TryGetTarget(out var item)
|| item == command)
{
_commands.RemoveAt(i);
}
}
}
/// <summary>
/// Create custom collation.
/// </summary>
/// <param name="name">Name of the collation.</param>
/// <param name="comparison">Method that compares two strings.</param>
public virtual void CreateCollation(string name, Comparison<string> comparison)
=> CreateCollation(name, null, comparison != null ? (_, s1, s2) => comparison(s1, s2) : (Func<object, string, string, int>)null);
/// <summary>
/// Create custom collation.
/// </summary>
/// <typeparam name="T">The type of the state object.</typeparam>
/// <param name="name">Name of the collation.</param>
/// <param name="state">State object passed to each invocation of the collation.</param>
/// <param name="comparison">Method that compares two strings, using additional state.</param>
public virtual void CreateCollation<T>(string name, T state, Func<T, string, string, int> comparison)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
if (State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(CreateCollation)));
}
var collation = comparison != null ? (v, s1, s2) => comparison((T)v, s1, s2) : (delegate_collation)null;
var rc = raw.sqlite3_create_collation(_db, name, state, collation);
SqliteException.ThrowExceptionForRC(rc, _db);
}
/// <summary>
/// Begins a transaction on the connection.
/// </summary>
/// <returns>The transaction.</returns>
public new virtual SqliteTransaction BeginTransaction()
=> BeginTransaction(IsolationLevel.Unspecified);
/// <summary>
/// Begins a transaction on the connection.
/// </summary>
/// <param name="isolationLevel">The isolation level of the transaction.</param>
/// <returns>The transaction.</returns>
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
=> BeginTransaction(isolationLevel);
/// <summary>
/// Begins a transaction on the connection.
/// </summary>
/// <param name="isolationLevel">The isolation level of the transaction.</param>
/// <returns>The transaction.</returns>
public new virtual SqliteTransaction BeginTransaction(IsolationLevel isolationLevel)
{
if (State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(BeginTransaction)));
}
if (Transaction != null)
{
throw new InvalidOperationException(Resources.ParallelTransactionsNotSupported);
}
return Transaction = new SqliteTransaction(this, isolationLevel);
}
/// <summary>
/// Changes the current database. Not supported.
/// </summary>
/// <param name="databaseName">The name of the database to use.</param>
/// <exception cref="NotSupportedException">Always.</exception>
public override void ChangeDatabase(string databaseName)
=> throw new NotSupportedException();
/// <summary>
/// Enables extension loading on the connection.
/// </summary>
/// <param name="enable">true to enable; false to disable</param>
/// <seealso href="http://sqlite.org/loadext.html">Run-Time Loadable Extensions</seealso>
public virtual void EnableExtensions(bool enable = true)
{
if (_db == null
|| _db.ptr == IntPtr.Zero)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(EnableExtensions)));
}
var rc = raw.sqlite3_enable_load_extension(_db, enable ? 1 : 0);
SqliteException.ThrowExceptionForRC(rc, _db);
}
/// <summary>
/// Backup of the connected database.
/// </summary>
/// <param name="destination">The destination of the backup.</param>
public virtual void BackupDatabase(SqliteConnection destination)
=> BackupDatabase(destination, MainDatabaseName, MainDatabaseName);
/// <summary>
/// Backup of the connected database.
/// </summary>
/// <param name="destination">The destination of the backup.</param>
/// <param name="destinationName">The name of the destination database.</param>
/// <param name="sourceName">The name of the source database.</param>
public virtual void BackupDatabase(SqliteConnection destination, string destinationName, string sourceName)
{
if (_db == null
|| _db.ptr == IntPtr.Zero)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(BackupDatabase)));
}
if (destination == null)
{
throw new ArgumentNullException(nameof(destination));
}
var close = false;
if (destination.State != ConnectionState.Open)
{
destination.Open();
close = true;
}
try
{
using (var backup = raw.sqlite3_backup_init(destination._db, destinationName, _db, sourceName))
{
int rc;
if (backup.ptr == IntPtr.Zero)
{
rc = raw.sqlite3_errcode(destination._db);
SqliteException.ThrowExceptionForRC(rc, destination._db);
}
rc = raw.sqlite3_backup_step(backup, -1);
SqliteException.ThrowExceptionForRC(rc, destination._db);
}
}
finally
{
if (close)
{
destination.Close();
}
}
}
private void CreateFunctionCore<TState, TResult>(
string name,
int arity,
TState state,
Func<TState, SqliteValueReader, TResult> function,
bool isDeterministic)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
if (State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(CreateFunction)));
}
delegate_function_scalar func = null;
if (function != null)
{
func = (ctx, user_data, args) =>
{
// TODO: Avoid allocation when niladic
var values = new SqliteParameterReader(name, args);
try
{
// TODO: Avoid closure by passing function via user_data
var result = function((TState)user_data, values);
new SqliteResultBinder(ctx, result).Bind();
}
catch (Exception ex)
{
raw.sqlite3_result_error(ctx, ex.Message);
if (ex is SqliteException sqlEx)
{
// NB: This must be called after sqlite3_result_error()
raw.sqlite3_result_error_code(ctx, sqlEx.SqliteErrorCode);
}
}
};
}
var rc = raw.sqlite3_create_function(
_db,
name,
arity,
isDeterministic ? raw.SQLITE_DETERMINISTIC : 0,
state,
func);
SqliteException.ThrowExceptionForRC(rc, _db);
}
private void CreateAggregateCore<TAccumulate, TResult>(
string name,
int arity,
TAccumulate seed,
Func<TAccumulate, SqliteValueReader, TAccumulate> func,
Func<TAccumulate, TResult> resultSelector,
bool isDeterministic)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
if (State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(CreateAggregate)));
}
delegate_function_aggregate_step func_step = null;
if (func != null)
{
func_step = (ctx, user_data, args) =>
{
var context = (AggregateContext<TAccumulate>)user_data;
if (context.Exception != null)
{
return;
}
// TODO: Avoid allocation when niladic
var reader = new SqliteParameterReader(name, args);
try
{
// TODO: Avoid closure by passing func via user_data
// NB: No need to set ctx.state since we just mutate the instance
context.Accumulate = func(context.Accumulate, reader);
}
catch (Exception ex)
{
context.Exception = ex;
}
};
}
delegate_function_aggregate_final func_final = null;
if (resultSelector != null)
{
func_final = (ctx, user_data) =>
{
var context = (AggregateContext<TAccumulate>)user_data;
if (context.Exception == null)
{
try
{
// TODO: Avoid closure by passing resultSelector via user_data
var result = resultSelector(context.Accumulate);
new SqliteResultBinder(ctx, result).Bind();
}
catch (Exception ex)
{
context.Exception = ex;
}
}
if (context.Exception != null)
{
raw.sqlite3_result_error(ctx, context.Exception.Message);
if (context.Exception is SqliteException sqlEx)
{
// NB: This must be called after sqlite3_result_error()
raw.sqlite3_result_error_code(ctx, sqlEx.SqliteErrorCode);
}
}
};
}
var rc = raw.sqlite3_create_function(
_db,
name,
arity,
isDeterministic ? raw.SQLITE_DETERMINISTIC : 0,
new AggregateContext<TAccumulate>(seed),
func_step,
func_final);
SqliteException.ThrowExceptionForRC(rc, _db);
}
private static Func<TState, SqliteValueReader, TResult> IfNotNull<TState, TResult>(
object x,
Func<TState, SqliteValueReader, TResult> value)
=> x != null ? value : null;
private static object[] GetValues(SqliteValueReader reader)
{
var values = new object[reader.FieldCount];
reader.GetValues(values);
return values;
}
private class AggregateContext<T>
{
public AggregateContext(T seed)
=> Accumulate = seed;
public T Accumulate { get; set; }
public Exception Exception { get; set; }
}
}
}

Просмотреть файл

@ -0,0 +1,317 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using Microsoft.Data.Sqlite.Properties;
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Provides a simple way to create and manage the contents of connection strings used by
/// <see cref="SqliteConnection" />.
/// </summary>
public class SqliteConnectionStringBuilder : DbConnectionStringBuilder
{
private const string DataSourceKeyword = "Data Source";
private const string DataSourceNoSpaceKeyword = "DataSource";
private const string ModeKeyword = "Mode";
private const string CacheKeyword = "Cache";
private const string FilenameKeyword = "Filename";
private enum Keywords
{
DataSource,
Mode,
Cache
}
private static readonly IReadOnlyList<string> _validKeywords;
private static readonly IReadOnlyDictionary<string, Keywords> _keywords;
private string _dataSource = string.Empty;
private SqliteOpenMode _mode = SqliteOpenMode.ReadWriteCreate;
private SqliteCacheMode _cache = SqliteCacheMode.Default;
static SqliteConnectionStringBuilder()
{
var validKeywords = new string[3];
validKeywords[(int)Keywords.DataSource] = DataSourceKeyword;
validKeywords[(int)Keywords.Mode] = ModeKeyword;
validKeywords[(int)Keywords.Cache] = CacheKeyword;
_validKeywords = validKeywords;
_keywords = new Dictionary<string, Keywords>(3, StringComparer.OrdinalIgnoreCase)
{
[DataSourceKeyword] = Keywords.DataSource,
[ModeKeyword] = Keywords.Mode,
[CacheKeyword] = Keywords.Cache,
// aliases
[FilenameKeyword] = Keywords.DataSource,
[DataSourceNoSpaceKeyword] = Keywords.DataSource
};
}
/// <summary>
/// Initializes a new instance of the <see cref="SqliteConnectionStringBuilder" /> class.
/// </summary>
public SqliteConnectionStringBuilder()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SqliteConnectionStringBuilder" /> class.
/// </summary>
/// <param name="connectionString">
/// The initial connection string the builder will represent. Can be null.
/// </param>
public SqliteConnectionStringBuilder(string connectionString)
=> ConnectionString = connectionString;
/// <summary>
/// Gets or sets the database file.
/// </summary>
/// <value>The database file.</value>
public virtual string DataSource
{
get => _dataSource;
set => base[DataSourceKeyword] = _dataSource = value;
}
/// <summary>
/// Gets or sets the connection mode.
/// </summary>
/// <value>The connection mode.</value>
public virtual SqliteOpenMode Mode
{
get => _mode;
set => base[ModeKeyword] = _mode = value;
}
/// <summary>
/// Gets a collection containing the keys used by the connection string.
/// </summary>
/// <value>A collection containing the keys used by the connection string.</value>
public override ICollection Keys
=> new ReadOnlyCollection<string>((string[])_validKeywords);
/// <summary>
/// Gets a collection containing the values used by the connection string.
/// </summary>
/// <value>A collection containing the values used by the connection string.</value>
public override ICollection Values
{
get
{
var values = new object[_validKeywords.Count];
for (var i = 0; i < _validKeywords.Count; i++)
{
values[i] = GetAt((Keywords)i);
}
return new ReadOnlyCollection<object>(values);
}
}
/// <summary>
/// Gets or sets the caching mode used by the connection.
/// </summary>
/// <value>The caching mode used by the connection.</value>
/// <seealso href="http://sqlite.org/sharedcache.html">SQLite Shared-Cache Mode</seealso>
public virtual SqliteCacheMode Cache
{
get => _cache;
set => base[CacheKeyword] = _cache = value;
}
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <param name="keyword">The key.</param>
/// <returns>The value.</returns>
public override object this[string keyword]
{
get => GetAt(GetIndex(keyword));
set
{
if (value == null)
{
Remove(keyword);
return;
}
switch (GetIndex(keyword))
{
case Keywords.DataSource:
DataSource = Convert.ToString(value, CultureInfo.InvariantCulture);
return;
case Keywords.Mode:
Mode = ConvertToEnum<SqliteOpenMode>(value);
return;
case Keywords.Cache:
Cache = ConvertToEnum<SqliteCacheMode>(value);
return;
default:
Debug.Assert(false, "Unexpected keyword: " + keyword);
return;
}
}
}
private static TEnum ConvertToEnum<TEnum>(object value)
where TEnum : struct
{
if (value is string stringValue)
{
return (TEnum)Enum.Parse(typeof(TEnum), stringValue, ignoreCase: true);
}
if (value is TEnum enumValue)
{
enumValue = (TEnum)value;
}
else if (value.GetType().GetTypeInfo().IsEnum)
{
throw new ArgumentException(Resources.ConvertFailed(value.GetType(), typeof(TEnum)));
}
else
{
enumValue = (TEnum)Enum.ToObject(typeof(TEnum), value);
}
if (!Enum.IsDefined(typeof(TEnum), enumValue))
{
throw new ArgumentOutOfRangeException(
nameof(value),
value,
Resources.InvalidEnumValue(typeof(TEnum), enumValue));
}
return enumValue;
}
/// <summary>
/// Clears the contents of the builder.
/// </summary>
public override void Clear()
{
base.Clear();
for (var i = 0; i < _validKeywords.Count; i++)
{
Reset((Keywords)i);
}
}
/// <summary>
/// Determines whether the specified key is used by the connection string.
/// </summary>
/// <param name="keyword">The key to look for.</param>
/// <returns>true if it is use; otherwise, false.</returns>
public override bool ContainsKey(string keyword)
=> _keywords.ContainsKey(keyword);
/// <summary>
/// Removes the specified key and its value from the connection string.
/// </summary>
/// <param name="keyword">The key to remove.</param>
/// <returns>true if the key was used; otherwise, false.</returns>
public override bool Remove(string keyword)
{
if (!_keywords.TryGetValue(keyword, out var index)
|| !base.Remove(_validKeywords[(int)index]))
{
return false;
}
Reset(index);
return true;
}
/// <summary>
/// Determines whether the specified key should be serialized into the connection string.
/// </summary>
/// <param name="keyword">The key to check.</param>
/// <returns>true if it should be serialized; otherwise, false.</returns>
public override bool ShouldSerialize(string keyword)
=> _keywords.TryGetValue(keyword, out var index) && base.ShouldSerialize(_validKeywords[(int)index]);
/// <summary>
/// Gets the value of the specified key if it is used.
/// </summary>
/// <param name="keyword">The key.</param>
/// <param name="value">The value.</param>
/// <returns>true if the key was used; otherwise, false.</returns>
public override bool TryGetValue(string keyword, out object value)
{
if (!_keywords.TryGetValue(keyword, out var index))
{
value = null;
return false;
}
value = GetAt(index);
return true;
}
private object GetAt(Keywords index)
{
switch (index)
{
case Keywords.DataSource:
return DataSource;
case Keywords.Mode:
return Mode;
case Keywords.Cache:
return Cache;
default:
Debug.Assert(false, "Unexpected keyword: " + index);
return null;
}
}
private static Keywords GetIndex(string keyword)
=> !_keywords.TryGetValue(keyword, out var index)
? throw new ArgumentException(Resources.KeywordNotSupported(keyword))
: index;
private void Reset(Keywords index)
{
switch (index)
{
case Keywords.DataSource:
_dataSource = string.Empty;
return;
case Keywords.Mode:
_mode = SqliteOpenMode.ReadWriteCreate;
return;
case Keywords.Cache:
_cache = SqliteCacheMode.Default;
return;
default:
Debug.Assert(false, "Unexpected keyword: " + index);
return;
}
}
}
}

Просмотреть файл

@ -0,0 +1,585 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Text;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Provides methods for reading the result of a command executed against a SQLite database.
/// </summary>
public class SqliteDataReader : DbDataReader
{
private readonly SqliteCommand _command;
private readonly bool _closeConnection;
private readonly Queue<(sqlite3_stmt stmt, bool)> _stmtQueue;
private sqlite3_stmt _stmt;
private SqliteDataRecord _record;
private bool _hasRows;
private bool _stepped;
private bool _done;
private bool _closed;
internal SqliteDataReader(
SqliteCommand command,
Queue<(sqlite3_stmt, bool)> stmtQueue,
int recordsAffected,
bool closeConnection)
{
if (stmtQueue.Count != 0)
{
(_stmt, _hasRows) = stmtQueue.Dequeue();
_record = new SqliteDataRecord(_stmt);
}
_command = command;
_stmtQueue = stmtQueue;
RecordsAffected = recordsAffected;
_closeConnection = closeConnection;
}
/// <summary>
/// Gets the depth of nesting for the current row. Always zero.
/// </summary>
/// <value>The depth of nesting for the current row.</value>
public override int Depth
=> 0;
/// <summary>
/// Gets the number of columns in the current row.
/// </summary>
/// <value>The number of columns in the current row.</value>
public override int FieldCount
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(FieldCount)))
: _record.FieldCount;
/// <summary>
/// Gets a handle to underlying prepared statement.
/// </summary>
/// <value>A handle to underlying prepared statement.</value>
/// <seealso href="http://sqlite.org/c3ref/stmt.html">Prepared Statement Object</seealso>
public virtual sqlite3_stmt Handle
=> _stmt;
/// <summary>
/// Gets a value indicating whether the data reader contains any rows.
/// </summary>
/// <value>A value indicating whether the data reader contains any rows.</value>
public override bool HasRows
=> _hasRows;
/// <summary>
/// Gets a value indicating whether the data reader is closed.
/// </summary>
/// <value>A value indicating whether the data reader is closed.</value>
public override bool IsClosed
=> _closed;
/// <summary>
/// Gets the number of rows inserted, updated, or deleted. -1 for SELECT statements.
/// </summary>
/// <value>The number of rows inserted, updated, or deleted.</value>
public override int RecordsAffected { get; }
/// <summary>
/// Gets the value of the specified column.
/// </summary>
/// <param name="name">The name of the column. The value is case-sensitive.</param>
/// <returns>The value.</returns>
public override object this[string name]
=> _record[name];
/// <summary>
/// Gets the value of the specified column.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value.</returns>
public override object this[int ordinal]
=> _record[ordinal];
/// <summary>
/// Gets an enumerator that can be used to iterate through the rows in the data reader.
/// </summary>
/// <returns>The enumerator.</returns>
public override IEnumerator GetEnumerator()
=> new DbEnumerator(this, closeReader: false);
/// <summary>
/// Advances to the next row in the result set.
/// </summary>
/// <returns>true if there are more rows; otherwise, false.</returns>
public override bool Read()
{
if (_closed)
{
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(Read)));
}
if (!_stepped)
{
_stepped = true;
return _hasRows;
}
var rc = raw.sqlite3_step(_stmt);
SqliteException.ThrowExceptionForRC(rc, _command.Connection.Handle);
_record.Clear();
_done = rc == raw.SQLITE_DONE;
return !_done;
}
/// <summary>
/// Advances to the next result set for batched statements.
/// </summary>
/// <returns>true if there are more result sets; otherwise, false.</returns>
public override bool NextResult()
{
if (_stmtQueue.Count == 0)
{
return false;
}
raw.sqlite3_reset(_stmt);
(_stmt, _hasRows) = _stmtQueue.Dequeue();
_record = new SqliteDataRecord(_stmt);
_stepped = false;
_done = false;
return true;
}
/// <summary>
/// Closes the data reader.
/// </summary>
public override void Close()
=> Dispose(true);
/// <summary>
/// Releases any resources used by the data reader and closes it.
/// </summary>
/// <param name="disposing">
/// true to release managed and unmanaged resources; false to release only unmanaged resources.
/// </param>
protected override void Dispose(bool disposing)
{
if (!disposing)
{
return;
}
_command.DataReader = null;
if (_stmt != null)
{
raw.sqlite3_reset(_stmt);
_stmt = null;
_record = null;
}
while (_stmtQueue.Count != 0)
{
raw.sqlite3_reset(_stmtQueue.Dequeue().stmt);
}
_closed = true;
if (_closeConnection)
{
_command.Connection.Close();
}
}
/// <summary>
/// Gets the name of the specified column.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The name of the column.</returns>
public override string GetName(int ordinal)
{
if (_closed)
{
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetName)));
}
return _record.GetName(ordinal);
}
/// <summary>
/// Gets the ordinal of the specified column.
/// </summary>
/// <param name="name">The name of the column.</param>
/// <returns>The zero-based column ordinal.</returns>
public override int GetOrdinal(string name)
=> _record.GetOrdinal(name);
/// <summary>
/// Gets the declared data type name of the specified column. The storage class is returned for computed
/// columns.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The data type name of the column.</returns>
/// <remarks>Due to SQLite's dynamic type system, this may not reflect the actual type of the value.</remarks>
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
public override string GetDataTypeName(int ordinal)
{
if (_closed)
{
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDataTypeName)));
}
return _record.GetDataTypeName(ordinal);
}
/// <summary>
/// Gets the data type of the specified column.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The data type of the column.</returns>
public override Type GetFieldType(int ordinal)
{
if (_closed)
{
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFieldType)));
}
return _record.GetFieldType(ordinal);
}
/// <summary>
/// Gets a value indicating whether the specified column is <see cref="DBNull" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>true if the specified column is <see cref="DBNull" />; otherwise, false.</returns>
public override bool IsDBNull(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(IsDBNull)))
: !_stepped || _done
? throw new InvalidOperationException(Resources.NoData)
: _record.IsDBNull(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="bool" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override bool GetBoolean(int ordinal)
=> _record.GetBoolean(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="byte" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override byte GetByte(int ordinal)
=> _record.GetByte(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="char" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override char GetChar(int ordinal)
=> _record.GetChar(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="DateTime" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override DateTime GetDateTime(int ordinal)
=> _record.GetDateTime(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="DateTimeOffset" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public virtual DateTimeOffset GetDateTimeOffset(int ordinal)
=> _record.GetDateTimeOffset(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="TimeSpan" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public virtual TimeSpan GetTimeSpan(int ordinal)
=> _record.GetTimeSpan(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="decimal" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override decimal GetDecimal(int ordinal)
=> _record.GetDecimal(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="double" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override double GetDouble(int ordinal)
=> _record.GetDouble(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="float" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override float GetFloat(int ordinal)
=> _record.GetFloat(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="Guid" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override Guid GetGuid(int ordinal)
=> _record.GetGuid(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="short" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override short GetInt16(int ordinal)
=> _record.GetInt16(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="int" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override int GetInt32(int ordinal)
=> _record.GetInt32(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="long" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override long GetInt64(int ordinal)
=> _record.GetInt64(ordinal);
/// <summary>
/// Gets the value of the specified column as a <see cref="string" />.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override string GetString(int ordinal)
=> _record.GetString(ordinal);
/// <summary>
/// Reads a stream of bytes from the specified column. Not supported.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <param name="dataOffset">The index from which to begin the read operation.</param>
/// <param name="buffer">The buffer into which the data is copied.</param>
/// <param name="bufferOffset">The index to which the data will be copied.</param>
/// <param name="length">The maximum number of bytes to read.</param>
/// <returns>The actual number of bytes read.</returns>
public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
=> _record.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length);
/// <summary>
/// Reads a stream of characters from the specified column. Not supported.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <param name="dataOffset">The index from which to begin the read operation.</param>
/// <param name="buffer">The buffer into which the data is copied.</param>
/// <param name="bufferOffset">The index to which the data will be copied.</param>
/// <param name="length">The maximum number of characters to read.</param>
/// <returns>The actual number of characters read.</returns>
public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)
=> _record.GetChars(ordinal, dataOffset, buffer, bufferOffset, length);
/// <summary>
/// Retrieves data as a Stream.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The returned object.</returns>
public override Stream GetStream(int ordinal)
=> _record.GetStream(ordinal);
/// <summary>
/// Gets the value of the specified column.
/// </summary>
/// <typeparam name="T">The type of the value.</typeparam>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override T GetFieldValue<T>(int ordinal)
{
if (typeof(T) == typeof(DBNull)
&& (!_stepped || _done))
{
throw new InvalidOperationException(Resources.NoData);
}
return _record.GetFieldValue<T>(ordinal);
}
/// <summary>
/// Gets the value of the specified column.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value of the column.</returns>
public override object GetValue(int ordinal)
{
if (_closed)
{
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetValue)));
}
if (!_stepped || _done)
{
throw new InvalidOperationException(Resources.NoData);
}
return _record.GetValue(ordinal);
}
/// <summary>
/// Gets the column values of the current row.
/// </summary>
/// <param name="values">An array into which the values are copied.</param>
/// <returns>The number of values copied into the array.</returns>
public override int GetValues(object[] values)
=> _record.GetValues(values);
/// <summary>
/// Returns a System.Data.DataTable that describes the column metadata of the System.Data.Common.DbDataReader.
/// </summary>
/// <returns>A System.Data.DataTable that describes the column metadata.</returns>
public override DataTable GetSchemaTable()
{
var schemaTable = new DataTable("SchemaTable");
var ColumnName = new DataColumn(SchemaTableColumn.ColumnName, typeof(string));
var ColumnOrdinal = new DataColumn(SchemaTableColumn.ColumnOrdinal, typeof(int));
var ColumnSize = new DataColumn(SchemaTableColumn.ColumnSize, typeof(int));
var NumericPrecision = new DataColumn(SchemaTableColumn.NumericPrecision, typeof(short));
var NumericScale = new DataColumn(SchemaTableColumn.NumericScale, typeof(short));
var DataType = new DataColumn(SchemaTableColumn.DataType, typeof(Type));
var DataTypeName = new DataColumn("DataTypeName", typeof(string));
var IsLong = new DataColumn(SchemaTableColumn.IsLong, typeof(bool));
var AllowDBNull = new DataColumn(SchemaTableColumn.AllowDBNull, typeof(bool));
var IsUnique = new DataColumn(SchemaTableColumn.IsUnique, typeof(bool));
var IsKey = new DataColumn(SchemaTableColumn.IsKey, typeof(bool));
var IsAutoIncrement = new DataColumn(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool));
var BaseCatalogName = new DataColumn(SchemaTableOptionalColumn.BaseCatalogName, typeof(string));
var BaseSchemaName = new DataColumn(SchemaTableColumn.BaseSchemaName, typeof(string));
var BaseTableName = new DataColumn(SchemaTableColumn.BaseTableName, typeof(string));
var BaseColumnName = new DataColumn(SchemaTableColumn.BaseColumnName, typeof(string));
var BaseServerName = new DataColumn(SchemaTableOptionalColumn.BaseServerName, typeof(string));
var IsAliased = new DataColumn(SchemaTableColumn.IsAliased, typeof(bool));
var IsExpression = new DataColumn(SchemaTableColumn.IsExpression, typeof(bool));
var columns = schemaTable.Columns;
columns.Add(ColumnName);
columns.Add(ColumnOrdinal);
columns.Add(ColumnSize);
columns.Add(NumericPrecision);
columns.Add(NumericScale);
columns.Add(IsUnique);
columns.Add(IsKey);
columns.Add(BaseServerName);
columns.Add(BaseCatalogName);
columns.Add(BaseColumnName);
columns.Add(BaseSchemaName);
columns.Add(BaseTableName);
columns.Add(DataType);
columns.Add(DataTypeName);
columns.Add(AllowDBNull);
columns.Add(IsAliased);
columns.Add(IsExpression);
columns.Add(IsAutoIncrement);
columns.Add(IsLong);
for (var i = 0; i < FieldCount; i++)
{
var schemaRow = schemaTable.NewRow();
schemaRow[ColumnName] = GetName(i);
schemaRow[ColumnOrdinal] = i;
schemaRow[ColumnSize] = DBNull.Value;
schemaRow[NumericPrecision] = DBNull.Value;
schemaRow[NumericScale] = DBNull.Value;
schemaRow[BaseServerName] = _command.Connection.DataSource;
var databaseName = raw.sqlite3_column_database_name(_stmt, i);
schemaRow[BaseCatalogName] = databaseName;
var columnName = raw.sqlite3_column_origin_name(_stmt, i);
schemaRow[BaseColumnName] = columnName;
schemaRow[BaseSchemaName] = DBNull.Value;
var tableName = raw.sqlite3_column_table_name(_stmt, i);
schemaRow[BaseTableName] = tableName;
schemaRow[DataType] = GetFieldType(i);
schemaRow[DataTypeName] = GetDataTypeName(i);
schemaRow[IsAliased] = columnName != GetName(i);
schemaRow[IsExpression] = columnName == null;
schemaRow[IsLong] = DBNull.Value;
if (!string.IsNullOrEmpty(tableName)
&& !string.IsNullOrEmpty(columnName))
{
using (var command = _command.Connection.CreateCommand())
{
command.CommandText = new StringBuilder()
.AppendLine("SELECT COUNT(*)")
.AppendLine("FROM pragma_index_list($table) i, pragma_index_info(i.name) c")
.AppendLine("WHERE \"unique\" = 1 AND c.name = $column AND")
.AppendLine("NOT EXISTS (SELECT * FROM pragma_index_info(i.name) c2 WHERE c2.name != c.name);").ToString();
command.Parameters.AddWithValue("$table", tableName);
command.Parameters.AddWithValue("$column", columnName);
var cnt = (long)command.ExecuteScalar();
schemaRow[IsUnique] = cnt != 0;
command.Parameters.Clear();
var columnType = "typeof(\"" + columnName.Replace("\"", "\"\"") + "\")";
command.CommandText = new StringBuilder()
.AppendLine($"SELECT {columnType}")
.AppendLine($"FROM \"{tableName}\"")
.AppendLine($"WHERE {columnType} != 'null'")
.AppendLine($"GROUP BY {columnType}")
.AppendLine("ORDER BY count() DESC")
.AppendLine("LIMIT 1;").ToString();
var type = (string)command.ExecuteScalar();
schemaRow[DataType] = SqliteDataRecord.GetFieldType(type);
}
if (!string.IsNullOrEmpty(databaseName))
{
var rc = raw.sqlite3_table_column_metadata(_command.Connection.Handle, databaseName, tableName, columnName, out var dataType, out var collSeq, out var notNull, out var primaryKey, out var autoInc);
SqliteException.ThrowExceptionForRC(rc, _command.Connection.Handle);
schemaRow[IsKey] = primaryKey != 0;
schemaRow[AllowDBNull] = notNull == 0;
schemaRow[IsAutoIncrement] = autoInc != 0;
}
}
schemaTable.Rows.Add(schemaRow);
}
return schemaTable;
}
}
}

Просмотреть файл

@ -0,0 +1,227 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.IO;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
internal class SqliteDataRecord : SqliteValueReader
{
private readonly sqlite3_stmt _stmt;
private readonly byte[][] _blobCache;
public SqliteDataRecord(sqlite3_stmt stmt)
{
_stmt = stmt;
_blobCache = new byte[FieldCount][];
}
public virtual object this[string name]
=> GetValue(GetOrdinal(name));
public virtual object this[int ordinal]
=> GetValue(ordinal);
public override int FieldCount
=> raw.sqlite3_column_count(_stmt);
protected override double GetDoubleCore(int ordinal)
=> raw.sqlite3_column_double(_stmt, ordinal);
protected override long GetInt64Core(int ordinal)
=> raw.sqlite3_column_int64(_stmt, ordinal);
protected override string GetStringCore(int ordinal)
=> raw.sqlite3_column_text(_stmt, ordinal);
protected override byte[] GetBlobCore(int ordinal)
=> raw.sqlite3_column_blob(_stmt, ordinal);
protected override int GetSqliteType(int ordinal)
{
var type = raw.sqlite3_column_type(_stmt, ordinal);
if (type == raw.SQLITE_NULL
&& (ordinal < 0 || ordinal >= FieldCount))
{
// NB: Message is provided by the framework
throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null);
}
return type;
}
protected override T GetNull<T>(int ordinal)
=> typeof(T) == typeof(DBNull) || typeof(T) == typeof(object)
? (T)(object)DBNull.Value
: throw new InvalidOperationException(GetOnNullErrorMsg(ordinal));
public virtual string GetName(int ordinal)
{
var name = raw.sqlite3_column_name(_stmt, ordinal);
if (name == null
&& (ordinal < 0 || ordinal >= FieldCount))
{
// NB: Message is provided by the framework
throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null);
}
return name;
}
public virtual int GetOrdinal(string name)
{
for (var i = 0; i < FieldCount; i++)
{
if (GetName(i) == name)
{
return i;
}
}
// NB: Message is provided by framework
throw new ArgumentOutOfRangeException(nameof(name), name, message: null);
}
public virtual string GetDataTypeName(int ordinal)
{
var typeName = raw.sqlite3_column_decltype(_stmt, ordinal);
if (typeName != null)
{
var i = typeName.IndexOf('(');
return i == -1
? typeName
: typeName.Substring(0, i);
}
var sqliteType = GetSqliteType(ordinal);
switch (sqliteType)
{
case raw.SQLITE_INTEGER:
return "INTEGER";
case raw.SQLITE_FLOAT:
return "REAL";
case raw.SQLITE_TEXT:
return "TEXT";
case raw.SQLITE_BLOB:
return "BLOB";
case raw.SQLITE_NULL:
return "INTEGER";
default:
Debug.Assert(false, "Unexpected column type: " + sqliteType);
return "INTEGER";
}
}
public virtual Type GetFieldType(int ordinal)
{
var sqliteType = GetSqliteType(ordinal);
switch (sqliteType)
{
case raw.SQLITE_INTEGER:
return typeof(long);
case raw.SQLITE_FLOAT:
return typeof(double);
case raw.SQLITE_TEXT:
return typeof(string);
case raw.SQLITE_BLOB:
return typeof(byte[]);
case raw.SQLITE_NULL:
return typeof(int);
default:
Debug.Assert(false, "Unexpected column type: " + sqliteType);
return typeof(int);
}
}
public static Type GetFieldType(string type)
{
switch (type)
{
case "integer":
return typeof(long);
case "real":
return typeof(double);
case "text":
return typeof(string);
case "blob":
return typeof(byte[]);
case null:
return typeof(int);
default:
Debug.Assert(false, "Unexpected column type: " + type);
return typeof(int);
}
}
public virtual long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
{
var blob = GetCachedBlob(ordinal);
long bytesToRead = (long)blob.Length - dataOffset;
if (buffer != null)
{
bytesToRead = System.Math.Min(bytesToRead, length);
Array.Copy(blob, dataOffset, buffer, bufferOffset, bytesToRead);
}
return bytesToRead;
}
public virtual long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)
{
var text = GetString(ordinal);
int charsToRead = text.Length - (int)dataOffset;
charsToRead = System.Math.Min(charsToRead, length);
text.CopyTo((int)dataOffset, buffer, bufferOffset, charsToRead);
return charsToRead;
}
public virtual Stream GetStream(int ordinal)
=> new MemoryStream(GetCachedBlob(ordinal), false);
internal void Clear()
{
for (var i = 0; i < _blobCache.Length; i++)
{
_blobCache[i] = null;
}
}
private byte[] GetCachedBlob(int ordinal)
{
if (ordinal < 0 || ordinal >= FieldCount)
{
// NB: Message is provided by the framework
throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null);
}
var blob = _blobCache[ordinal];
if (blob == null)
{
blob = GetBlob(ordinal);
_blobCache[ordinal] = blob;
}
return blob;
}
}
}

Просмотреть файл

@ -0,0 +1,85 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Data.Common;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Represents a SQLite error.
/// </summary>
public class SqliteException : DbException
{
/// <summary>
/// Initializes a new instance of the <see cref="SqliteException" /> class.
/// </summary>
/// <param name="message">The message to display for the exception. Can be null.</param>
/// <param name="errorCode">The SQLite error code.</param>
public SqliteException(string message, int errorCode)
: this(message, errorCode, errorCode)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="SqliteException" /> class.
/// </summary>
/// <param name="message">The message to display for the exception. Can be null.</param>
/// <param name="errorCode">The SQLite error code.</param>
/// /// <param name="extendedErrorCode">The extended SQLite error code.</param>
public SqliteException(string message, int errorCode, int extendedErrorCode)
: base(message)
{
SqliteErrorCode = errorCode;
SqliteExtendedErrorCode = extendedErrorCode;
}
/// <summary>
/// Gets the SQLite error code.
/// </summary>
/// <value>The SQLite error code.</value>
/// <seealso href="http://sqlite.org/rescode.html">SQLite Result Codes</seealso>
public virtual int SqliteErrorCode { get; }
/// <summary>
/// Gets the extended SQLite error code.
/// </summary>
/// <value>The SQLite error code.</value>
/// <seealso href="https://sqlite.org/rescode.html#extrc">SQLite Result Codes</seealso>
public virtual int SqliteExtendedErrorCode { get; }
/// <summary>
/// Throws an exception with a specific SQLite error code value.
/// </summary>
/// <param name="rc">The SQLite error code corresponding to the desired exception.</param>
/// <param name="db">A handle to database connection.</param>
/// <remarks>
/// No exception is thrown for non-error result codes.
/// </remarks>
public static void ThrowExceptionForRC(int rc, sqlite3 db)
{
if (rc == raw.SQLITE_OK
|| rc == raw.SQLITE_ROW
|| rc == raw.SQLITE_DONE)
{
return;
}
string message;
int extendedErrorCode;
if (db == null || db.ptr == IntPtr.Zero || rc != raw.sqlite3_errcode(db))
{
message = raw.sqlite3_errstr(rc) + " " + Resources.DefaultNativeError;
extendedErrorCode = rc;
}
else
{
message = raw.sqlite3_errmsg(db);
extendedErrorCode = raw.sqlite3_extended_errcode(db);
}
throw new SqliteException(Resources.SqliteNativeError(rc, message), rc, extendedErrorCode);
}
}
}

Просмотреть файл

@ -0,0 +1,50 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Data.Common;
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Creates instances of various Microsoft.Data.Sqlite classes.
/// </summary>
public class SqliteFactory : DbProviderFactory
{
private SqliteFactory()
{
}
/// <summary>
/// The singleton instance.
/// </summary>
public static readonly SqliteFactory Instance = new SqliteFactory();
/// <summary>
/// Creates a new command.
/// </summary>
/// <returns>The new command.</returns>
public override DbCommand CreateCommand()
=> new SqliteCommand();
/// <summary>
/// Creates a new connection.
/// </summary>
/// <returns>The new connection.</returns>
public override DbConnection CreateConnection()
=> new SqliteConnection();
/// <summary>
/// Creates a new connection string builder.
/// </summary>
/// <returns>The new connection string builder.</returns>
public override DbConnectionStringBuilder CreateConnectionStringBuilder()
=> new SqliteConnectionStringBuilder();
/// <summary>
/// Creates a new parameter.
/// </summary>
/// <returns>The new parameter.</returns>
public override DbParameter CreateParameter()
=> new SqliteParameter();
}
}

Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Represents the connection modes that can be used when opening a connection.
/// </summary>
public enum SqliteOpenMode
{
/// <summary>
/// Opens the database for reading and writing, and creates it if it doesn't exist.
/// </summary>
ReadWriteCreate,
/// <summary>
/// Opens the database for reading and writing.
/// </summary>
ReadWrite,
/// <summary>
/// Opens the database in read-only mode.
/// </summary>
ReadOnly,
/// <summary>
/// Opens an in-memory database.
/// </summary>
Memory
}
}

Просмотреть файл

@ -0,0 +1,268 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Data;
using System.Data.Common;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
// TODO: Truncate to specified size
// TODO: Infer type and size from value
/// <summary>
/// Represents a parameter and its value in a <see cref="SqliteCommand" />.
/// </summary>
/// <remarks>Due to SQLite's dynamic type system, parameter values are not converted.</remarks>
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
public class SqliteParameter : DbParameter
{
private string _parameterName = string.Empty;
private object _value;
private int? _size;
private SqliteType? _sqliteType;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
/// </summary>
public SqliteParameter()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
/// </summary>
/// <param name="name">The name of the parameter.</param>
/// <param name="value">The value of the parameter. Can be null.</param>
public SqliteParameter(string name, object value)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
_parameterName = name;
Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
/// </summary>
/// <param name="name">The name of the parameter.</param>
/// <param name="type">The type of the parameter.</param>
public SqliteParameter(string name, SqliteType type)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
_parameterName = name;
SqliteType = type;
}
/// <summary>
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
/// </summary>
/// <param name="name">The name of the parameter.</param>
/// <param name="type">The type of the parameter.</param>
/// <param name="size">The maximum size, in bytes, of the parameter.</param>
public SqliteParameter(string name, SqliteType type, int size)
: this(name, type)
=> Size = size;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteParameter" /> class.
/// </summary>
/// <param name="name">The name of the parameter.</param>
/// <param name="type">The type of the parameter.</param>
/// <param name="size">The maximum size, in bytes, of the parameter.</param>
/// <param name="sourceColumn">The source column used for loading the value. Can be null.</param>
public SqliteParameter(string name, SqliteType type, int size, string sourceColumn)
: this(name, type, size)
=> SourceColumn = sourceColumn;
/// <summary>
/// Gets or sets the type of the parameter.
/// </summary>
/// <value>The type of the parameter.</value>
/// <remarks>Due to SQLite's dynamic type system, parameter values are not converted.</remarks>
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
public override DbType DbType { get; set; } = DbType.String;
/// <summary>
/// Gets or sets the SQLite type of the parameter.
/// </summary>
/// <value>The SQLite type of the parameter.</value>
/// <remarks>Due to SQLite's dynamic type system, parameter values are not converted.</remarks>
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
public virtual SqliteType SqliteType
{
get => _sqliteType ?? SqliteValueBinder.GetSqliteType(_value);
set => _sqliteType = value;
}
/// <summary>
/// Gets or sets the direction of the parameter. Only <see cref="ParameterDirection.Input" /> is supported.
/// </summary>
/// <value>The direction of the parameter.</value>
public override ParameterDirection Direction
{
get => ParameterDirection.Input;
set
{
if (value != ParameterDirection.Input)
{
throw new ArgumentException(Resources.InvalidParameterDirection(value));
}
}
}
/// <summary>
/// Gets or sets a value indicating whether the parameter is nullable.
/// </summary>
/// <value>A value indicating whether the parameter is nullable.</value>
public override bool IsNullable { get; set; }
/// <summary>
/// Gets or sets the name of the parameter.
/// </summary>
/// <value>The name of the parameter.</value>
public override string ParameterName
{
get => _parameterName;
set
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentNullException(nameof(value));
}
_parameterName = value;
}
}
/// <summary>
/// Gets or sets the maximum size, in bytes, of the parameter.
/// </summary>
/// <value>The maximum size, in bytes, of the parameter.</value>
public override int Size
{
get => _size
?? (_value is string stringValue
? stringValue.Length
: _value is byte[] byteArray
? byteArray.Length
: 0);
set
{
if (value < -1)
{
// NB: Message is provided by the framework
throw new ArgumentOutOfRangeException(nameof(value), value, message: null);
}
_size = value;
}
}
/// <summary>
/// Gets or sets the source column used for loading the value.
/// </summary>
/// <value>The source column used for loading the value.</value>
public override string SourceColumn { get; set; } = string.Empty;
/// <summary>
/// Gets or sets a value indicating whether the source column is nullable.
/// </summary>
/// <value>A value indicating whether the source column is nullable.</value>
public override bool SourceColumnNullMapping { get; set; }
/// <summary>
/// Gets or sets the value of the parameter.
/// </summary>
/// <value>The value of the parameter.</value>
/// <remarks>Due to SQLite's dynamic type system, parameter values are not converted.</remarks>
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
public override object Value
{
get => _value;
set { _value = value; }
}
/// <summary>
/// Resets the <see cref="DbType" /> property to its original value.
/// </summary>
public override void ResetDbType()
=> ResetSqliteType();
/// <summary>
/// Resets the <see cref="SqliteType" /> property to its original value.
/// </summary>
public virtual void ResetSqliteType()
{
DbType = DbType.String;
SqliteType = SqliteType.Text;
}
internal bool Bind(sqlite3_stmt stmt)
{
if (_parameterName.Length == 0)
{
throw new InvalidOperationException(Resources.RequiresSet(nameof(ParameterName)));
}
var index = raw.sqlite3_bind_parameter_index(stmt, _parameterName);
if (index == 0
&& (index = FindPrefixedParameter(stmt)) == 0)
{
return false;
}
if (_value == null)
{
throw new InvalidOperationException(Resources.RequiresSet(nameof(Value)));
}
new SqliteParameterBinder(stmt, index, _value, _size, _sqliteType).Bind();
return true;
}
private static readonly char[] _parameterPrefixes = { '@', '$', ':' };
private int FindPrefixedParameter(sqlite3_stmt stmt)
{
var index = 0;
int nextIndex;
foreach (var prefix in _parameterPrefixes)
{
if (_parameterName[0] == prefix)
{
// If name already has a prefix characters, the first call to sqlite3_bind_parameter_index
// would have worked if the parameter name was in the statement
return 0;
}
nextIndex = raw.sqlite3_bind_parameter_index(stmt, prefix + _parameterName);
if (nextIndex == 0)
{
continue;
}
if (index != 0)
{
throw new InvalidOperationException(Resources.AmbiguousParameterName(_parameterName));
}
index = nextIndex;
}
return index;
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
internal class SqliteParameterBinder : SqliteValueBinder
{
private readonly sqlite3_stmt _stmt;
private readonly int _index;
private readonly int? _size;
public SqliteParameterBinder(sqlite3_stmt stmt, int index, object value, int? size, SqliteType? sqliteType)
: base(value, sqliteType)
{
_stmt = stmt;
_index = index;
_size = size;
}
protected override void BindBlob(byte[] value)
{
var blob = value;
if (ShouldTruncate(value.Length))
{
blob = new byte[_size.Value];
Array.Copy(value, blob, _size.Value);
}
raw.sqlite3_bind_blob(_stmt, _index, blob);
}
protected override void BindDoubleCore(double value)
=> raw.sqlite3_bind_double(_stmt, _index, value);
protected override void BindInt64(long value)
=> raw.sqlite3_bind_int64(_stmt, _index, value);
protected override void BindNull()
=> raw.sqlite3_bind_null(_stmt, _index);
protected override void BindText(string value)
=> raw.sqlite3_bind_text(
_stmt,
_index,
ShouldTruncate(value.Length)
? value.Substring(0, _size.Value)
: value);
private bool ShouldTruncate(int length)
=> _size.HasValue
&& length > _size.Value
&& _size.Value != -1;
}
}

Просмотреть файл

@ -0,0 +1,347 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Represents a collection of SQLite parameters.
/// </summary>
public class SqliteParameterCollection : DbParameterCollection
{
private readonly List<SqliteParameter> _parameters = new List<SqliteParameter>();
/// <summary>
/// Initializes a new instance of the <see cref="SqliteParameterCollection" /> class.
/// </summary>
protected internal SqliteParameterCollection()
{
}
/// <summary>
/// Gets the number of items in the collection.
/// </summary>
/// <value>The number of items in the collection.</value>
public override int Count
=> _parameters.Count;
/// <summary>
/// Gets the object used to synchronize access to the collection.
/// </summary>
/// <value>The object used to synchronize access to the collection.</value>
public override object SyncRoot
=> ((ICollection)_parameters).SyncRoot;
/// <summary>
/// Gets or sets the parameter at the specified index.
/// </summary>
/// <param name="index">The zero-based index of the parameter.</param>
/// <returns>The parameter.</returns>
public new virtual SqliteParameter this[int index]
{
get => _parameters[index];
set
{
if (_parameters[index] == value)
{
return;
}
_parameters[index] = value;
}
}
/// <summary>
/// Gets or sets the parameter with the specified name.
/// </summary>
/// <param name="parameterName">The name of the parameter.</param>
/// <returns>The parameter.</returns>
public new virtual SqliteParameter this[string parameterName]
{
get => this[IndexOfChecked(parameterName)];
set => this[IndexOfChecked(parameterName)] = value;
}
/// <summary>
/// Adds a parameter to the collection.
/// </summary>
/// <param name="value">The parameter to add. Must be a <see cref="SqliteParameter" />.</param>
/// <returns>The zero-based index of the parameter that was added.</returns>
public override int Add(object value)
{
_parameters.Add((SqliteParameter)value);
return Count - 1;
}
/// <summary>
/// Adds a parameter to the collection.
/// </summary>
/// <param name="value">The parameter to add.</param>
/// <returns>The parameter that was added.</returns>
public virtual SqliteParameter Add(SqliteParameter value)
{
_parameters.Add(value);
return value;
}
/// <summary>
/// Adds a parameter to the collection.
/// </summary>
/// <param name="parameterName">The name of the parameter.</param>
/// <param name="type">The SQLite type of the parameter.</param>
/// <returns>The parameter that was added.</returns>
public virtual SqliteParameter Add(string parameterName, SqliteType type)
=> Add(new SqliteParameter(parameterName, type));
/// <summary>
/// Adds a parameter to the collection.
/// </summary>
/// <param name="parameterName">The name of the parameter.</param>
/// <param name="type">The SQLite type of the parameter.</param>
/// <param name="size">The maximum size, in bytes, of the parameter.</param>
/// <returns>The parameter that was added.</returns>
public virtual SqliteParameter Add(string parameterName, SqliteType type, int size)
=> Add(new SqliteParameter(parameterName, type, size));
/// <summary>
/// Adds a parameter to the collection.
/// </summary>
/// <param name="parameterName">The name of the parameter.</param>
/// <param name="type">The SQLite type of the parameter.</param>
/// <param name="size">The maximum size, in bytes, of the parameter.</param>
/// <param name="sourceColumn">
/// The source column used for loading the value of the parameter. Can be null.
/// </param>
/// <returns>The parameter that was added.</returns>
public virtual SqliteParameter Add(string parameterName, SqliteType type, int size, string sourceColumn)
=> Add(new SqliteParameter(parameterName, type, size, sourceColumn));
/// <summary>
/// Adds multiple parameters to the collection.
/// </summary>
/// <param name="values">
/// An array of parameters to add. They must be <see cref="SqliteParameter" /> objects.
/// </param>
public override void AddRange(Array values)
=> AddRange(values.Cast<SqliteParameter>());
/// <summary>
/// Adds multiple parameters to the collection.
/// </summary>
/// <param name="values">The parameters to add.</param>
public virtual void AddRange(IEnumerable<SqliteParameter> values)
=> _parameters.AddRange(values);
/// <summary>
/// Adds a parameter to the collection.
/// </summary>
/// <param name="parameterName">The name of the parameter.</param>
/// <param name="value">The value of the parameter. Can be null.</param>
/// <returns>The parameter that was added.</returns>
public virtual SqliteParameter AddWithValue(string parameterName, object value)
{
var parameter = new SqliteParameter(parameterName, value);
Add(parameter);
return parameter;
}
/// <summary>
/// Removes all parameters from the collection.
/// </summary>
public override void Clear()
=> _parameters.Clear();
/// <summary>
/// Gets a value indicating whether the collection contains the specified parameter.
/// </summary>
/// <param name="value">The parameter to look for. Must be a <see cref="SqliteParameter" />.</param>
/// <returns>true if the collection contains the parameter; otherwise, false.</returns>
public override bool Contains(object value)
=> Contains((SqliteParameter)value);
/// <summary>
/// Gets a value indicating whether the collection contains the specified parameter.
/// </summary>
/// <param name="value">The parameter to look for.</param>
/// <returns>true if the collection contains the parameter; otherwise, false.</returns>
public virtual bool Contains(SqliteParameter value)
=> _parameters.Contains(value);
/// <summary>
/// Gets a value indicating whether the collection contains a parameter with the specified name.
/// </summary>
/// <param name="value">The name of the parameter.</param>
/// <returns>true if the collection contains the parameter; otherwise, false.</returns>
public override bool Contains(string value)
=> IndexOf(value) != -1;
/// <summary>
/// Copies the collection to an array of parameters.
/// </summary>
/// <param name="array">
/// The array into which the parameters are copied. Must be an array of <see cref="SqliteParameter" /> objects.
/// </param>
/// <param name="index">The zero-based index to which the parameters are copied.</param>
public override void CopyTo(Array array, int index)
=> CopyTo((SqliteParameter[])array, index);
/// <summary>
/// Copies the collection to an array of parameters.
/// </summary>
/// <param name="array">The array into which the parameters are copied.</param>
/// <param name="index">The zero-based index to which the parameters are copied.</param>
public virtual void CopyTo(SqliteParameter[] array, int index)
=> _parameters.CopyTo(array, index);
/// <summary>
/// Gets an enumerator that iterates through the collection.
/// </summary>
/// <returns>The enumerator.</returns>
public override IEnumerator GetEnumerator()
=> _parameters.GetEnumerator();
/// <summary>
/// Gets a parameter at the specified index.
/// </summary>
/// <param name="index">The zero-based index of the parameter.</param>
/// <returns>The parameter.</returns>
protected override DbParameter GetParameter(int index)
=> this[index];
/// <summary>
/// Gets a parameter with the specified name.
/// </summary>
/// <param name="parameterName">The name of the parameter.</param>
/// <returns>The parameter.</returns>
protected override DbParameter GetParameter(string parameterName)
=> GetParameter(IndexOfChecked(parameterName));
/// <summary>
/// Gets the index of the specified parameter.
/// </summary>
/// <param name="value">The parameter. Must be a <see cref="SqliteParameter" />.</param>
/// <returns>The zero-based index of the parameter.</returns>
public override int IndexOf(object value)
=> IndexOf((SqliteParameter)value);
/// <summary>
/// Gets the index of the specified parameter.
/// </summary>
/// <param name="value">The parameter.</param>
/// <returns>The zero-based index of the parameter.</returns>
public virtual int IndexOf(SqliteParameter value)
=> _parameters.IndexOf(value);
/// <summary>
/// Gets the index of the parameter with the specified name.
/// </summary>
/// <param name="parameterName">The name of the parameter.</param>
/// <returns>The zero-based index of the parameter or -1 if not found.</returns>
public override int IndexOf(string parameterName)
{
for (var index = 0; index < _parameters.Count; index++)
{
if (_parameters[index].ParameterName == parameterName)
{
return index;
}
}
return -1;
}
/// <summary>
/// Inserts a parameter into the collection at the specified index.
/// </summary>
/// <param name="index">The zero-based index at which the parameter should be inserted.</param>
/// <param name="value">The parameter to insert. Must be a <see cref="SqliteParameter" />.</param>
public override void Insert(int index, object value)
=> Insert(index, (SqliteParameter)value);
/// <summary>
/// Inserts a parameter into the collection at the specified index.
/// </summary>
/// <param name="index">The zero-based index at which the parameter should be inserted.</param>
/// <param name="value">The parameter to insert.</param>
public virtual void Insert(int index, SqliteParameter value)
=> _parameters.Insert(index, value);
/// <summary>
/// Removes a parameter from the collection.
/// </summary>
/// <param name="value">The parameter to remove. Must be a <see cref="SqliteParameter" />.</param>
public override void Remove(object value)
=> Remove((SqliteParameter)value);
/// <summary>
/// Removes a parameter from the collection.
/// </summary>
/// <param name="value">The parameter to remove.</param>
public virtual void Remove(SqliteParameter value)
=> _parameters.Remove(value);
/// <summary>
/// Removes a parameter from the collection at the specified index.
/// </summary>
/// <param name="index">The zero-based index of the parameter to remove.</param>
public override void RemoveAt(int index)
=> _parameters.RemoveAt(index);
/// <summary>
/// Removes a parameter with the specified name from the collection.
/// </summary>
/// <param name="parameterName">The name of the parameter to remove.</param>
public override void RemoveAt(string parameterName)
=> RemoveAt(IndexOfChecked(parameterName));
/// <summary>
/// Sets the parameter at the specified index.
/// </summary>
/// <param name="index">The zero-based index of the parameter to set.</param>
/// <param name="value">The parameter. Must be a <see cref="SqliteParameter" />.</param>
protected override void SetParameter(int index, DbParameter value)
=> this[index] = (SqliteParameter)value;
/// <summary>
/// Sets the parameter with the specified name.
/// </summary>
/// <param name="parameterName">The name of the parameter to set.</param>
/// <param name="value">The parameter. Must be a <see cref="SqliteParameter" />.</param>
protected override void SetParameter(string parameterName, DbParameter value)
=> SetParameter(IndexOfChecked(parameterName), value);
internal int Bind(sqlite3_stmt stmt)
{
var bound = 0;
foreach (var parameter in _parameters)
{
if (parameter.Bind(stmt))
{
bound++;
}
}
return bound;
}
private int IndexOfChecked(string parameterName)
{
var index = IndexOf(parameterName);
if (index == -1)
{
throw new IndexOutOfRangeException(Resources.ParameterNotFound(parameterName));
}
return index;
}
}
}

Просмотреть файл

@ -0,0 +1,41 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
internal class SqliteParameterReader : SqliteValueReader
{
private readonly string _function;
private readonly sqlite3_value[] _values;
public SqliteParameterReader(string function, sqlite3_value[] values)
{
_function = function;
_values = values;
}
public override int FieldCount
=> _values.Length;
protected override string GetOnNullErrorMsg(int ordinal)
=> Resources.UDFCalledWithNull(_function, ordinal);
protected override double GetDoubleCore(int ordinal)
=> raw.sqlite3_value_double(_values[ordinal]);
protected override long GetInt64Core(int ordinal)
=> raw.sqlite3_value_int64(_values[ordinal]);
protected override string GetStringCore(int ordinal)
=> raw.sqlite3_value_text(_values[ordinal]);
protected override byte[] GetBlobCore(int ordinal)
=> raw.sqlite3_value_blob(_values[ordinal]);
protected override int GetSqliteType(int ordinal)
=> raw.sqlite3_value_type(_values[ordinal]);
}
}

Просмотреть файл

@ -0,0 +1,33 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
internal class SqliteResultBinder : SqliteValueBinder
{
private readonly sqlite3_context _ctx;
public SqliteResultBinder(sqlite3_context ctx, object value)
: base(value)
{
_ctx = ctx;
}
protected override void BindBlob(byte[] value)
=> raw.sqlite3_result_blob(_ctx, value);
protected override void BindDoubleCore(double value)
=> raw.sqlite3_result_double(_ctx, value);
protected override void BindInt64(long value)
=> raw.sqlite3_result_int64(_ctx, value);
protected override void BindNull()
=> raw.sqlite3_result_null(_ctx);
protected override void BindText(string value)
=> raw.sqlite3_result_text(_ctx, value);
}
}

Просмотреть файл

@ -0,0 +1,155 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Data;
using System.Data.Common;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Represents a transaction made against a SQLite database.
/// </summary>
public class SqliteTransaction : DbTransaction
{
private SqliteConnection _connection;
private readonly IsolationLevel _isolationLevel;
private bool _completed;
private bool _externalRollback;
internal SqliteTransaction(SqliteConnection connection, IsolationLevel isolationLevel)
{
if ((isolationLevel == IsolationLevel.ReadUncommitted
&& connection.ConnectionStringBuilder.Cache != SqliteCacheMode.Shared)
|| isolationLevel == IsolationLevel.ReadCommitted
|| isolationLevel == IsolationLevel.RepeatableRead)
{
isolationLevel = IsolationLevel.Serializable;
}
_connection = connection;
_isolationLevel = isolationLevel;
if (isolationLevel == IsolationLevel.ReadUncommitted)
{
connection.ExecuteNonQuery("PRAGMA read_uncommitted = 1;");
}
else if (isolationLevel == IsolationLevel.Serializable)
{
connection.ExecuteNonQuery("PRAGMA read_uncommitted = 0;");
}
else if (isolationLevel != IsolationLevel.Unspecified)
{
throw new ArgumentException(Resources.InvalidIsolationLevel(isolationLevel));
}
connection.ExecuteNonQuery(
IsolationLevel == IsolationLevel.Serializable
? "BEGIN IMMEDIATE;"
: "BEGIN;");
raw.sqlite3_rollback_hook(connection.Handle, RollbackExternal, null);
}
/// <summary>
/// Gets the connection associated with the transaction.
/// </summary>
/// <value>The connection associated with the transaction.</value>
public new virtual SqliteConnection Connection
=> _connection;
/// <summary>
/// Gets the connection associated with the transaction.
/// </summary>
/// <value>The connection associated with the transaction.</value>
protected override DbConnection DbConnection
=> Connection;
internal bool ExternalRollback
=> _externalRollback;
/// <summary>
/// Gets the isolation level for the transaction. This cannot be changed if the transaction is completed or
/// closed.
/// </summary>
/// <value>The isolation level for the transaction.</value>
public override IsolationLevel IsolationLevel
=> _completed || _connection.State != ConnectionState.Open
? throw new InvalidOperationException(Resources.TransactionCompleted)
: _isolationLevel != IsolationLevel.Unspecified
? _isolationLevel
: (_connection.ConnectionStringBuilder.Cache == SqliteCacheMode.Shared
&& _connection.ExecuteScalar<long>("PRAGMA read_uncommitted;") != 0)
? IsolationLevel.ReadUncommitted
: IsolationLevel.Serializable;
/// <summary>
/// Applies the changes made in the transaction.
/// </summary>
public override void Commit()
{
if (_externalRollback || _completed || _connection.State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.TransactionCompleted);
}
raw.sqlite3_rollback_hook(_connection.Handle, null, null);
_connection.ExecuteNonQuery("COMMIT;");
Complete();
}
/// <summary>
/// Reverts the changes made in the transaction.
/// </summary>
public override void Rollback()
{
if (_completed || _connection.State != ConnectionState.Open)
{
throw new InvalidOperationException(Resources.TransactionCompleted);
}
RollbackInternal();
}
/// <summary>
/// Releases any resources used by the transaction and rolls it back.
/// </summary>
/// <param name="disposing">
/// true to release managed and unmanaged resources; false to release only unmanaged resources.
/// </param>
protected override void Dispose(bool disposing)
{
if (disposing
&& !_completed
&& _connection.State == ConnectionState.Open)
{
RollbackInternal();
}
}
private void Complete()
{
_connection.Transaction = null;
_connection = null;
_completed = true;
}
private void RollbackInternal()
{
if (!_externalRollback)
{
raw.sqlite3_rollback_hook(_connection.Handle, null, null);
_connection.ExecuteNonQuery("ROLLBACK;");
}
Complete();
}
private void RollbackExternal(object userData)
{
raw.sqlite3_rollback_hook(_connection.Handle, null, null);
_externalRollback = true;
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
/// <summary>
/// Represents the type affinities used by columns in SQLite tables.
/// </summary>
/// <seealso href="http://sqlite.org/datatype3.html">Datatypes In SQLite Version 3</seealso>
public enum SqliteType
{
/// <summary>
/// A signed integer.
/// </summary>
Integer = raw.SQLITE_INTEGER,
/// <summary>
/// A floating point value.
/// </summary>
Real = raw.SQLITE_FLOAT,
/// <summary>
/// A text string.
/// </summary>
Text = raw.SQLITE_TEXT,
/// <summary>
/// A blob of data.
/// </summary>
Blob = raw.SQLITE_BLOB
}
}

Просмотреть файл

@ -0,0 +1,275 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.Data.Sqlite.Properties;
namespace Microsoft.Data.Sqlite
{
// TODO: Make generic
internal abstract class SqliteValueBinder
{
private readonly object _value;
private readonly SqliteType? _sqliteType;
protected SqliteValueBinder(object value)
: this(value, null)
{
}
protected SqliteValueBinder(object value, SqliteType? sqliteType)
{
_value = value;
_sqliteType = sqliteType;
}
protected abstract void BindInt64(long value);
protected virtual void BindDouble(double value)
{
if (double.IsNaN(value))
{
throw new InvalidOperationException(Resources.CannotStoreNaN);
}
BindDoubleCore(value);
}
protected abstract void BindDoubleCore(double value);
protected abstract void BindText(string value);
protected abstract void BindBlob(byte[] value);
protected abstract void BindNull();
public virtual void Bind()
{
if (_value == null)
{
BindNull();
return;
}
var type = _value.GetType().UnwrapNullableType().UnwrapEnumType();
if (type == typeof(bool))
{
var value = (bool)_value ? 1L : 0;
BindInt64(value);
}
else if (type == typeof(byte))
{
var value = (long)(byte)_value;
BindInt64(value);
}
else if (type == typeof(byte[]))
{
var value = (byte[])_value;
BindBlob(value);
}
else if (type == typeof(char))
{
var chr = (char)_value;
if (_sqliteType == SqliteType.Text)
{
var value = new string(chr, 1);
BindText(value);
}
else
{
var value = (long)chr;
BindInt64(value);
}
}
else if (type == typeof(DateTime))
{
var dateTime = (DateTime)_value;
if (_sqliteType == SqliteType.Real)
{
var value = ToJulianDate(dateTime);
BindDouble(value);
}
else
{
var value = dateTime.ToString(@"yyyy\-MM\-dd HH\:mm\:ss.FFFFFFF", CultureInfo.InvariantCulture);
BindText(value);
}
}
else if (type == typeof(DateTimeOffset))
{
var dateTimeOffset = (DateTimeOffset)_value;
if (_sqliteType == SqliteType.Real)
{
var value = ToJulianDate(dateTimeOffset.DateTime);
BindDouble(value);
}
else
{
var value = dateTimeOffset.ToString(@"yyyy\-MM\-dd HH\:mm\:ss.FFFFFFFzzz", CultureInfo.InvariantCulture);
BindText(value);
}
}
else if (type == typeof(DBNull))
{
BindNull();
}
else if (type == typeof(decimal))
{
var value = ((decimal)_value).ToString("0.0###########################", CultureInfo.InvariantCulture);
BindText(value);
}
else if (type == typeof(double))
{
var value = (double)_value;
BindDouble(value);
}
else if (type == typeof(float))
{
var value = (double)(float)_value;
BindDouble(value);
}
else if (type == typeof(Guid))
{
var guid = (Guid)_value;
if (_sqliteType == SqliteType.Text)
{
var value = guid.ToString().ToUpper();
BindText(value);
}
else
{
var value = guid.ToByteArray();
BindBlob(value);
}
}
else if (type == typeof(int))
{
var value = (long)(int)_value;
BindInt64(value);
}
else if (type == typeof(long))
{
var value = (long)_value;
BindInt64(value);
}
else if (type == typeof(sbyte))
{
var value = (long)(sbyte)_value;
BindInt64(value);
}
else if (type == typeof(short))
{
var value = (long)(short)_value;
BindInt64(value);
}
else if (type == typeof(string))
{
var value = (string)_value;
BindText(value);
}
else if (type == typeof(TimeSpan))
{
var timeSpan = (TimeSpan)_value;
if (_sqliteType == SqliteType.Real)
{
var value = timeSpan.TotalDays;
BindDouble(value);
}
else
{
var value = timeSpan.ToString("c");
BindText(value);
}
}
else if (type == typeof(uint))
{
var value = (long)(uint)_value;
BindInt64(value);
}
else if (type == typeof(ulong))
{
var value = (long)(ulong)_value;
BindInt64(value);
}
else if (type == typeof(ushort))
{
var value = (long)(ushort)_value;
BindInt64(value);
}
else
{
throw new InvalidOperationException(Resources.UnknownDataType(type));
}
}
private static readonly Dictionary<Type, SqliteType> _sqliteTypeMapping =
new Dictionary<Type, SqliteType>()
{
{typeof(bool), SqliteType.Integer},
{typeof(byte),SqliteType.Integer},
{typeof(byte[]), SqliteType.Blob},
{typeof(char),SqliteType.Integer},
{typeof(DateTime), SqliteType.Text},
{typeof(DateTimeOffset), SqliteType.Text},
{typeof(DBNull), SqliteType.Text},
{typeof(decimal),SqliteType.Text},
{typeof(double), SqliteType.Real},
{typeof(float), SqliteType.Real},
{typeof(Guid), SqliteType.Blob},
{typeof(int), SqliteType.Integer},
{typeof(long), SqliteType.Integer},
{typeof(sbyte),SqliteType.Integer},
{typeof(short), SqliteType.Integer},
{typeof(string), SqliteType.Integer},
{typeof(TimeSpan), SqliteType.Text},
{typeof(uint), SqliteType.Integer},
{typeof(ulong), SqliteType.Integer},
{typeof(ushort), SqliteType.Integer},
};
internal static SqliteType GetSqliteType(object value)
{
if (value == null)
{
return SqliteType.Text;
}
var type = value.GetType().UnwrapNullableType().UnwrapEnumType();
if (_sqliteTypeMapping.TryGetValue(type, out var sqliteType))
{
return sqliteType;
}
else
{
throw new InvalidOperationException(Resources.UnknownDataType(type));
}
}
private static double ToJulianDate(DateTime dateTime)
{
// computeJD
var Y = dateTime.Year;
var M = dateTime.Month;
var D = dateTime.Day;
if (M <= 2)
{
Y--;
M += 12;
}
var A = Y / 100;
var B = 2 - A + (A / 4);
var X1 = 36525 * (Y + 4716) / 100;
var X2 = 306001 * (M + 1) / 10000;
var iJD = (long)((X1 + X2 + D + B - 1524.5) * 86400000);
iJD += dateTime.Hour * 3600000 + dateTime.Minute * 60000 + (long)((dateTime.Second + dateTime.Millisecond / 1000.0) * 1000);
return iJD / 86400000.0;
}
}
}

Просмотреть файл

@ -0,0 +1,311 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
namespace Microsoft.Data.Sqlite
{
internal abstract class SqliteValueReader
{
public abstract int FieldCount { get; }
protected abstract int GetSqliteType(int ordinal);
public virtual bool IsDBNull(int ordinal)
=> GetSqliteType(ordinal) == raw.SQLITE_NULL;
public virtual bool GetBoolean(int ordinal)
=> GetInt64(ordinal) != 0;
public virtual byte GetByte(int ordinal)
=> (byte)GetInt64(ordinal);
public virtual char GetChar(int ordinal)
{
var sqliteType = GetSqliteType(ordinal);
if (sqliteType == raw.SQLITE_TEXT)
{
var val = GetString(ordinal);
if (val.Length == 1)
{
return val[0];
}
}
return (char)GetInt64(ordinal);
}
public virtual DateTime GetDateTime(int ordinal)
{
var sqliteType = GetSqliteType(ordinal);
switch (sqliteType)
{
case raw.SQLITE_FLOAT:
case raw.SQLITE_INTEGER:
return FromJulianDate(GetDouble(ordinal));
default:
return DateTime.Parse(GetString(ordinal), CultureInfo.InvariantCulture);
}
}
public virtual DateTimeOffset GetDateTimeOffset(int ordinal)
{
var sqliteType = GetSqliteType(ordinal);
switch (sqliteType)
{
case raw.SQLITE_FLOAT:
case raw.SQLITE_INTEGER:
return new DateTimeOffset(FromJulianDate(GetDouble(ordinal)));
default:
return DateTimeOffset.Parse(GetString(ordinal), CultureInfo.InvariantCulture);
}
}
public virtual decimal GetDecimal(int ordinal)
=> decimal.Parse(GetString(ordinal), NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture);
public virtual double GetDouble(int ordinal)
=> IsDBNull(ordinal)
? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal))
: GetDoubleCore(ordinal);
protected abstract double GetDoubleCore(int ordinal);
public virtual float GetFloat(int ordinal)
=> (float)GetDouble(ordinal);
public virtual Guid GetGuid(int ordinal)
{
var sqliteType = GetSqliteType(ordinal);
switch (sqliteType)
{
case raw.SQLITE_BLOB:
var bytes = GetBlob(ordinal);
return bytes.Length == 16
? new Guid(bytes)
: new Guid(Encoding.UTF8.GetString(bytes, 0, bytes.Length));
default:
return new Guid(GetString(ordinal));
}
}
public virtual TimeSpan GetTimeSpan(int ordinal)
{
var sqliteType = GetSqliteType(ordinal);
switch (sqliteType)
{
case raw.SQLITE_FLOAT:
case raw.SQLITE_INTEGER:
return TimeSpan.FromDays(GetDouble(ordinal));
default:
return TimeSpan.Parse(GetString(ordinal));
}
}
public virtual short GetInt16(int ordinal)
=> (short)GetInt64(ordinal);
public virtual int GetInt32(int ordinal)
=> (int)GetInt64(ordinal);
public virtual long GetInt64(int ordinal)
=> IsDBNull(ordinal)
? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal))
: GetInt64Core(ordinal);
protected abstract long GetInt64Core(int ordinal);
public virtual string GetString(int ordinal)
=> IsDBNull(ordinal)
? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal))
: GetStringCore(ordinal);
protected abstract string GetStringCore(int ordinal);
public virtual T GetFieldValue<T>(int ordinal)
{
if (IsDBNull(ordinal)
&& typeof(T).IsNullable())
{
return GetNull<T>(ordinal);
}
var type = typeof(T).UnwrapNullableType().UnwrapEnumType();
if (type == typeof(bool))
{
return (T)(object)GetBoolean(ordinal);
}
if (type == typeof(byte))
{
return (T)(object)GetByte(ordinal);
}
if (type == typeof(byte[]))
{
return (T)(object)GetBlob(ordinal);
}
if (type == typeof(char))
{
return (T)(object)GetChar(ordinal);
}
if (type == typeof(DateTime))
{
return (T)(object)GetDateTime(ordinal);
}
if (type == typeof(DateTimeOffset))
{
return (T)(object)GetDateTimeOffset(ordinal);
}
if (type == typeof(DBNull))
{
// NB: NULL values handled above
throw new InvalidCastException();
}
if (type == typeof(decimal))
{
return (T)(object)GetDecimal(ordinal);
}
if (type == typeof(double))
{
return (T)(object)GetDouble(ordinal);
}
if (type == typeof(float))
{
return (T)(object)GetFloat(ordinal);
}
if (type == typeof(Guid))
{
return (T)(object)GetGuid(ordinal);
}
if (type == typeof(int))
{
return (T)(object)GetInt32(ordinal);
}
if (type == typeof(long))
{
return (T)(object)GetInt64(ordinal);
}
if (type == typeof(sbyte))
{
return (T)(object)((sbyte)GetInt64(ordinal));
}
if (type == typeof(short))
{
return (T)(object)GetInt16(ordinal);
}
if (type == typeof(string))
{
return (T)(object)GetString(ordinal);
}
if (type == typeof(TimeSpan))
{
return (T)(object)GetTimeSpan(ordinal);
}
if (type == typeof(uint))
{
return (T)(object)((uint)GetInt64(ordinal));
}
if (type == typeof(ulong))
{
return (T)(object)((ulong)GetInt64(ordinal));
}
if (type == typeof(ushort))
{
return (T)(object)((ushort)GetInt64(ordinal));
}
return (T)GetValue(ordinal);
}
public virtual object GetValue(int ordinal)
{
var sqliteType = GetSqliteType(ordinal);
switch (sqliteType)
{
case raw.SQLITE_INTEGER:
return GetInt64(ordinal);
case raw.SQLITE_FLOAT:
return GetDouble(ordinal);
case raw.SQLITE_TEXT:
return GetString(ordinal);
case raw.SQLITE_BLOB:
return GetBlob(ordinal);
case raw.SQLITE_NULL:
return GetNull<object>(ordinal);
default:
Debug.Assert(false, "Unexpected column type: " + sqliteType);
return GetInt32(ordinal);
}
}
public virtual int GetValues(object[] values)
{
int i;
for (i = 0; i < FieldCount; i++)
{
values[i] = GetValue(i);
}
return i;
}
protected byte[] GetBlob(int ordinal)
=> IsDBNull(ordinal)
? GetNull<byte[]>(ordinal)
: GetBlobCore(ordinal) ?? Array.Empty<byte>();
protected abstract byte[] GetBlobCore(int ordinal);
protected virtual T GetNull<T>(int ordinal)
=> typeof(T) == typeof(DBNull)
? (T)(object)DBNull.Value
: default;
protected virtual string GetOnNullErrorMsg(int ordinal)
=> Resources.CalledOnNullValue(ordinal);
private static DateTime FromJulianDate(double julianDate)
{
// computeYMD
var iJD = (long)(julianDate * 86400000.0 + 0.5);
var Z = (int)((iJD + 43200000) / 86400000);
var A = (int)((Z - 1867216.25) / 36524.25);
A = Z + 1 + A - (A / 4);
var B = A + 1524;
var C = (int)((B - 122.1) / 365.25);
var D = (36525 * (C & 32767)) / 100;
var E = (int)((B - D) / 30.6001);
var X1 = (int)(30.6001 * E);
var day = B - D - X1;
var month = E < 14 ? E - 1 : E - 13;
var year = month > 2 ? C - 4716 : C - 4715;
// computeHMS
var s = (int)((iJD + 43200000) % 86400000);
var fracSecond = s / 1000.0;
s = (int)fracSecond;
fracSecond -= s;
var hour = s / 3600;
s -= hour * 3600;
var minute = s / 60;
fracSecond += s - minute * 60;
var second = (int)fracSecond;
var millisecond = (int)Math.Round((fracSecond - second) * 1000.0);
return new DateTime(year, month, day, hour, minute, second, millisecond);
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
namespace Microsoft.Data.Sqlite.Utilities
{
internal static class BundleInitializer
{
public static void Initialize()
{
Assembly assembly;
try
{
assembly = Assembly.Load(new AssemblyName("SQLitePCLRaw.batteries_v2"));
}
catch
{
return;
}
assembly.GetType("SQLitePCL.Batteries_V2").GetTypeInfo().GetDeclaredMethod("Init")
.Invoke(null, null);
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>SQLite implementation of the System.Data.Common provider model.
Commonly Used Types:
Microsoft.Data.Sqlite.SqliteCommand
Microsoft.Data.Sqlite.SqliteConnection
Microsoft.Data.Sqlite.SqliteConnectionStringBuilder
Microsoft.Data.Sqlite.SqliteDataReader
Microsoft.Data.Sqlite.SqliteException
Microsoft.Data.Sqlite.SqliteFactory
Microsoft.Data.Sqlite.SqliteParameter
Microsoft.Data.Sqlite.SqliteTransaction</Description>
<IncludeBuildOutput>false</IncludeBuildOutput>
<EnableApiCheck>false</EnableApiCheck>
<TargetFramework>netstandard2.0</TargetFramework>
<MinClientVersion>3.6</MinClientVersion>
<PackageTags>SQLite;Data;ADO.NET</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)">
<PrivateAssets>None</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="lib\**\*">
<Pack>True</Pack>
<PackagePath>lib</PackagePath>
</None>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,4 @@
Microsoft.Data.Sqlite
=====================
Contains SQLite implementations of the System.Data.Common interfaces.

Просмотреть файл

Просмотреть файл

@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Data.Sqlite
{
internal static class SqliteConnectionExtensions
{
public static SqliteDataReader ExecuteReader(this SqliteConnection connection, string commandText)
{
var command = connection.CreateCommand();
command.CommandText = commandText;
return command.ExecuteReader();
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Data.Sqlite.Core\Microsoft.Data.Sqlite.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawBundleGreenPackageVersion)" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,883 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
using Xunit;
namespace Microsoft.Data.Sqlite
{
public class SqliteCommandTest
{
[Fact]
public void Ctor_sets_values()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.DefaultTimeout = 1;
connection.Open();
using (var transaction = connection.BeginTransaction())
{
var command = new SqliteCommand("SELECT 1;", connection, transaction);
Assert.Equal("SELECT 1;", command.CommandText);
Assert.Same(connection, command.Connection);
Assert.Equal(1, command.CommandTimeout);
Assert.Same(transaction, command.Transaction);
}
}
}
[Fact]
public void CommandText_throws_when_set_when_open_reader()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
using (var reader = command.ExecuteReader())
{
reader.Read();
var ex = Assert.Throws<InvalidOperationException>(() => command.CommandText = "SELECT 2;");
Assert.Equal(Resources.SetRequiresNoOpenReader("CommandText"), ex.Message);
}
}
}
[Fact]
public void Connection_can_be_unset()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
command.Prepare();
command.Connection = null;
Assert.Null(command.Connection);
}
}
[Fact]
public void Connection_throws_when_set_when_open_reader()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
using (var reader = command.ExecuteReader())
{
reader.Read();
var ex = Assert.Throws<InvalidOperationException>(() => command.Connection = new SqliteConnection());
Assert.Equal(Resources.SetRequiresNoOpenReader("Connection"), ex.Message);
}
}
}
[Fact]
public void CommandType_text_by_default()
{
Assert.Equal(CommandType.Text, new SqliteCommand().CommandType);
}
[Theory]
[InlineData(CommandType.StoredProcedure)]
[InlineData(CommandType.TableDirect)]
public void CommandType_validates_value(CommandType commandType)
{
var ex = Assert.Throws<ArgumentException>(() => new SqliteCommand().CommandType = commandType);
Assert.Equal(Resources.InvalidCommandType(commandType), ex.Message);
}
[Fact]
public void Parameters_works()
{
var command = new SqliteCommand();
var result = command.Parameters;
Assert.NotNull(result);
Assert.Same(result, command.Parameters);
}
[Fact]
public void CreateParameter_works()
{
Assert.NotNull(new SqliteCommand().CreateParameter());
}
[Fact]
public void Prepare_throws_when_no_connection()
{
var ex = Assert.Throws<InvalidOperationException>(() => new SqliteCommand().Prepare());
Assert.Equal(Resources.CallRequiresOpenConnection("Prepare"), ex.Message);
}
[Fact]
public void Prepare_throws_when_connection_closed()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().Prepare());
Assert.Equal(Resources.CallRequiresOpenConnection("Prepare"), ex.Message);
}
}
[Fact]
public void Prepare_throws_when_no_command_text()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().Prepare());
Assert.Equal(Resources.CallRequiresSetCommandText("Prepare"), ex.Message);
}
}
[Fact]
public void Prepare_throws_when_command_text_contains_dependent_commands()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "CREATE TABLE Data (Value); SELECT * FROM Data;";
var ex = Assert.Throws<SqliteException>(() => command.Prepare());
Assert.Equal(1, ex.SqliteErrorCode);
}
}
[Fact]
private void Multiple_command_executes_works()
{
const int INSERTS = 3;
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
connection.ExecuteNonQuery("CREATE TABLE Data (ID integer PRIMARY KEY, Value integer);");
using (var command = connection.CreateCommand())
{
command.CommandText = "INSERT INTO Data (Value) VALUES (@value);";
var valueParam = command.Parameters.AddWithValue("@value", -1);
Assert.Equal(1, command.ExecuteNonQuery());
for (var i = 0; i < INSERTS; i++)
{
valueParam.Value = i;
Assert.Equal(1, command.ExecuteNonQuery());
}
Assert.Equal(1, command.ExecuteNonQuery());
command.CommandText = "SELECT Value FROM Data ORDER BY ID";
using (var reader = command.ExecuteReader())
{
Assert.True(reader.Read());
Assert.Equal(-1, reader.GetInt32(0));
for (var i = 0; i < INSERTS; i++)
{
Assert.True(reader.Read());
Assert.Equal(i, reader.GetInt32(0));
}
Assert.True(reader.Read());
Assert.Equal(INSERTS - 1, reader.GetInt32(0));
}
}
}
}
[Fact]
public void ExecuteReader_throws_when_no_connection()
{
var ex = Assert.Throws<InvalidOperationException>(() => new SqliteCommand().ExecuteReader());
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteReader"), ex.Message);
}
[Fact]
public void ExecuteReader_throws_when_connection_closed()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteReader());
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteReader"), ex.Message);
}
}
[Fact]
public void ExecuteReader_throws_when_no_command_text()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteReader());
Assert.Equal(Resources.CallRequiresSetCommandText("ExecuteReader"), ex.Message);
}
}
[Fact]
public void ExecuteReader_throws_on_error()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "INVALID";
connection.Open();
var ex = Assert.Throws<SqliteException>(() => command.ExecuteReader());
Assert.Equal(raw.SQLITE_ERROR, ex.SqliteErrorCode);
}
}
[Fact]
public void ExecuteScalar_throws_when_no_connection()
{
var ex = Assert.Throws<InvalidOperationException>(() => new SqliteCommand().ExecuteScalar());
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteScalar"), ex.Message);
}
[Fact]
public void ExecuteScalar_throws_when_connection_closed()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteScalar());
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteScalar"), ex.Message);
}
}
[Fact]
public void ExecuteReader_throws_when_transaction_required()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
connection.Open();
using (connection.BeginTransaction())
{
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteReader());
Assert.Equal(Resources.TransactionRequired, ex.Message);
}
}
}
[Fact]
public void ExecuteScalar_throws_when_no_command_text()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteScalar());
Assert.Equal(Resources.CallRequiresSetCommandText("ExecuteScalar"), ex.Message);
}
}
[Fact]
public void ExecuteScalar_processes_dependent_commands()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "CREATE TABLE Data (Value); SELECT * FROM Data;";
Assert.Null(command.ExecuteScalar());
}
}
[Fact]
public void ExecuteScalar_returns_null_when_empty()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 1 WHERE 0 = 1;";
connection.Open();
Assert.Null(command.ExecuteScalar());
}
}
[Fact]
public void ExecuteScalar_returns_long_when_integer()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
connection.Open();
Assert.Equal(1L, command.ExecuteScalar());
}
}
[Fact]
public void ExecuteScalar_returns_double_when_real()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 3.14;";
connection.Open();
Assert.Equal(3.14, command.ExecuteScalar());
}
}
[Fact]
public void ExecuteScalar_returns_string_when_text()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 'test';";
connection.Open();
Assert.Equal("test", command.ExecuteScalar());
}
}
[Fact]
public void ExecuteScalar_returns_byte_array_when_blob()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT x'7e57';";
connection.Open();
Assert.Equal(new byte[] { 0x7e, 0x57 }, command.ExecuteScalar());
}
}
[Fact]
public void ExecuteScalar_returns_DBNull_when_null()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT NULL;";
connection.Open();
Assert.Equal(DBNull.Value, command.ExecuteScalar());
}
}
[Fact]
public void ExecuteReader_binds_parameters()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Parameter;";
command.Parameters.AddWithValue("@Parameter", 1);
connection.Open();
Assert.Equal(1L, command.ExecuteScalar());
}
}
[Fact]
public void ExecuteReader_throws_when_parameter_unset()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Parameter;";
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteScalar());
Assert.Equal(Resources.MissingParameters("@Parameter"), ex.Message);
}
}
[Fact]
public void ExecuteReader_throws_when_reader_open()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
connection.Open();
using (var reader = command.ExecuteReader())
{
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteReader());
Assert.Equal(Resources.DataReaderOpen, ex.Message);
}
}
}
[Fact]
public void ExecuteScalar_returns_long_when_batching()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 42; SELECT 43;";
connection.Open();
Assert.Equal(42L, command.ExecuteScalar());
}
}
[Fact]
public void ExecuteScalar_returns_long_when_multiple_columns()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 42, 43;";
connection.Open();
Assert.Equal(42L, command.ExecuteScalar());
}
}
[Fact]
public void ExecuteScalar_returns_long_when_multiple_rows()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 42 UNION SELECT 43;";
connection.Open();
Assert.Equal(42L, command.ExecuteScalar());
}
}
[Fact]
public void ExecuteNonQuery_throws_when_no_connection()
{
var ex = Assert.Throws<InvalidOperationException>(() => new SqliteCommand().ExecuteNonQuery());
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteNonQuery"), ex.Message);
}
[Fact]
public void ExecuteNonQuery_throws_when_connection_closed()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteNonQuery());
Assert.Equal(Resources.CallRequiresOpenConnection("ExecuteNonQuery"), ex.Message);
}
}
[Fact]
public void ExecuteNonQuery_throws_when_no_command_text()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => connection.CreateCommand().ExecuteNonQuery());
Assert.Equal(Resources.CallRequiresSetCommandText("ExecuteNonQuery"), ex.Message);
}
}
[Fact]
public void ExecuteReader_throws_when_transaction_mismatched()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
connection.Open();
using (var otherConnection = new SqliteConnection("Data Source=:memory:"))
{
otherConnection.Open();
using (var transction = otherConnection.BeginTransaction())
{
command.Transaction = transction;
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteReader());
Assert.Equal(Resources.TransactionConnectionMismatch, ex.Message);
}
}
}
}
[Fact]
public void ExecuteReader_throws_when_transaction_completed_externally()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
connection.ExecuteNonQuery("ROLLBACK;");
var ex = Assert.Throws<InvalidOperationException>(() => connection.ExecuteNonQuery("SELECT 1;"));
Assert.Equal(Resources.TransactionCompleted, ex.Message);
}
}
}
[Fact]
public void ExecuteNonQuery_works()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
connection.Open();
Assert.Equal(-1, command.ExecuteNonQuery());
}
}
[Fact]
public void ExecuteReader_works()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
connection.Open();
using (var reader = command.ExecuteReader())
{
Assert.NotNull(reader);
}
}
}
[Fact]
public void ExecuteReader_skips_DML_statements()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
connection.ExecuteNonQuery("CREATE TABLE Test(Value);");
var command = connection.CreateCommand();
command.CommandText = @"
INSERT INTO Test VALUES(1);
SELECT 1;";
using (var reader = command.ExecuteReader())
{
var hasData = reader.Read();
Assert.True(hasData);
Assert.Equal(1L, reader.GetInt64(0));
}
}
}
[Fact]
public void ExecuteReader_works_when_comments()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "-- TODO: Write SQL";
connection.Open();
using (var reader = command.ExecuteReader())
{
Assert.False(reader.HasRows);
Assert.Equal(-1, reader.RecordsAffected);
}
}
}
[Fact]
public void ExecuteReader_works_when_trailing_comments()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 0; -- My favorite number";
connection.Open();
using (var reader = command.ExecuteReader())
{
var hasResult = reader.NextResult();
Assert.False(hasResult);
}
}
}
[Fact]
public void Cancel_does_nothing()
{
new SqliteCommand().Cancel();
}
[Fact]
public void ExecuteReader_supports_SequentialAccess()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 0;";
connection.Open();
using (var reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
{
var hasResult = reader.NextResult();
Assert.False(hasResult);
}
}
}
[Fact]
public void ExecuteReader_supports_SingleResult()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 0;";
connection.Open();
using (var reader = command.ExecuteReader(CommandBehavior.SingleResult))
{
var hasResult = reader.NextResult();
Assert.False(hasResult);
}
}
}
[Fact]
public void ExecuteReader_supports_SingleRow()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 0;";
connection.Open();
using (var reader = command.ExecuteReader(CommandBehavior.SingleRow))
{
var hasResult = reader.NextResult();
Assert.False(hasResult);
}
}
}
[Fact]
public void ExecuteReader_supports_CloseConnection()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 0;";
connection.Open();
using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
var hasResult = reader.NextResult();
Assert.False(hasResult);
}
Assert.Equal(ConnectionState.Closed, connection.State);
}
}
[Theory]
[InlineData(CommandBehavior.KeyInfo)]
[InlineData(CommandBehavior.SchemaOnly)]
public void ExecuteReader_throws_for_unsupported_CommandBehavior(CommandBehavior behavior)
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 0;";
connection.Open();
var ex = Assert.Throws<ArgumentException>(() => command.ExecuteReader(behavior));
Assert.Equal(Resources.InvalidCommandBehavior(behavior), ex.Message);
}
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public Task ExecuteReader_retries_when_locked(bool extendedErrorCode)
{
const string connectionString = "Data Source=locked;Mode=Memory;Cache=Shared";
var selectedSignal = new AutoResetEvent(initialState: false);
return Task.WhenAll(
Task.Run(
async () =>
{
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
if (extendedErrorCode)
{
raw.sqlite3_extended_result_codes(connection.Handle, 1);
}
connection.ExecuteNonQuery(
"CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
using (connection.ExecuteReader("SELECT * FROM Data;"))
{
selectedSignal.Set();
await Task.Delay(1000);
}
}
}),
Task.Run(
() =>
{
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
if (extendedErrorCode)
{
raw.sqlite3_extended_result_codes(connection.Handle, 1);
}
selectedSignal.WaitOne();
var command = connection.CreateCommand();
command.CommandText = "DROP TABLE Data;";
command.ExecuteNonQuery();
}
}));
}
[Fact]
public async Task ExecuteReader_retries_when_busy()
{
const string connectionString = "Data Source=busy.db";
var selectedSignal = new AutoResetEvent(initialState: false);
try
{
await Task.WhenAll(
Task.Run(
async () =>
{
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
connection.ExecuteNonQuery(
"CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
using (connection.ExecuteReader("SELECT * FROM Data;"))
{
selectedSignal.Set();
await Task.Delay(1000);
}
}
}),
Task.Run(
() =>
{
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
selectedSignal.WaitOne();
var command = connection.CreateCommand();
command.CommandText = "DROP TABLE Data;";
command.ExecuteNonQuery();
}
}));
}
finally
{
File.Delete("busy.db");
}
}
[Fact]
public void ExecuteReader_honors_CommandTimeout()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
connection.ExecuteNonQuery("CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
using (connection.ExecuteReader("SELECT * FROM Data;"))
{
var command = connection.CreateCommand();
command.CommandText = "DROP TABLE Data;";
command.CommandTimeout = 1;
var stopwatch = Stopwatch.StartNew();
Assert.Throws<SqliteException>(() => command.ExecuteNonQuery());
stopwatch.Stop();
Assert.InRange(stopwatch.ElapsedMilliseconds, 1000, 1999);
}
}
}
[Fact]
public void Can_get_results_from_nonreadonly_statements()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var result = connection.ExecuteScalar<string>("PRAGMA journal_mode;");
Assert.NotNull(result);
}
}
}
}

Просмотреть файл

@ -0,0 +1,281 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.Data.Sqlite.Properties;
using Xunit;
namespace Microsoft.Data.Sqlite
{
public class SqliteConnectionStringBuilderTest
{
[Fact]
public void Ctor_parses_options()
{
var builder = new SqliteConnectionStringBuilder("Data Source=test.db");
Assert.Equal("test.db", builder.DataSource);
}
[Fact]
public void Ctor_parses_SharedCache()
{
Assert.Equal(SqliteCacheMode.Private, new SqliteConnectionStringBuilder("Cache=Private").Cache);
Assert.Equal(SqliteCacheMode.Shared, new SqliteConnectionStringBuilder("Cache=Shared").Cache);
}
[Fact]
public void Ctor_parses_mode()
{
var builder = new SqliteConnectionStringBuilder("Mode=Memory");
Assert.Equal(SqliteOpenMode.Memory, builder.Mode);
}
[Fact]
public void Filename_is_alias_for_DataSource()
{
var builder = new SqliteConnectionStringBuilder("Filename=inline.db");
Assert.Equal("inline.db", builder.DataSource);
}
[Fact]
public void It_takes_last_alias_specified()
{
var builder = new SqliteConnectionStringBuilder("Filename=ignore me.db; Data Source=and me too.db; DataSource=this_one.db");
Assert.Equal("this_one.db", builder.DataSource);
}
[Fact]
public void DataSource_works()
{
var builder = new SqliteConnectionStringBuilder();
builder.DataSource = "test.db";
Assert.Equal("test.db", builder.DataSource);
}
[Fact]
public void DataSource_defaults_to_empty()
{
Assert.Empty(new SqliteConnectionStringBuilder().DataSource);
}
[Fact]
public void Mode_works()
{
var builder = new SqliteConnectionStringBuilder();
builder.Mode = SqliteOpenMode.Memory;
Assert.Equal(SqliteOpenMode.Memory, builder.Mode);
}
[Fact]
public void Mode_defaults_to_ReadWriteCreate()
{
Assert.Equal(SqliteOpenMode.ReadWriteCreate, new SqliteConnectionStringBuilder().Mode);
}
[Fact]
public void Cache_defaults()
{
Assert.Equal(SqliteCacheMode.Default, new SqliteConnectionStringBuilder().Cache);
}
[Fact]
public void Keys_works()
{
var keys = (ICollection<string>)new SqliteConnectionStringBuilder().Keys;
Assert.True(keys.IsReadOnly);
Assert.Equal(3, keys.Count);
Assert.Contains("Data Source", keys);
Assert.Contains("Mode", keys);
Assert.Contains("Cache", keys);
}
[Fact]
public void Values_works()
{
var values = (ICollection<object>)new SqliteConnectionStringBuilder().Values;
Assert.True(values.IsReadOnly);
Assert.Equal(3, values.Count);
}
[Fact]
public void Item_validates_argument()
{
var ex = Assert.Throws<ArgumentException>(() => new SqliteConnectionStringBuilder()["Invalid"]);
Assert.Equal(Resources.KeywordNotSupported("Invalid"), ex.Message);
ex = Assert.Throws<ArgumentException>(() => new SqliteConnectionStringBuilder()["Invalid"] = 0);
Assert.Equal(Resources.KeywordNotSupported("Invalid"), ex.Message);
}
[Fact]
public void Item_resets_value_when_null()
{
var builder = new SqliteConnectionStringBuilder();
builder.DataSource = "test.db";
builder["Data Source"] = null;
Assert.Empty(builder.DataSource);
}
[Fact]
public void Item_gets_value()
{
var builder = new SqliteConnectionStringBuilder();
builder.DataSource = "test.db";
Assert.Equal("test.db", builder["Data Source"]);
}
[Fact]
public void Item_sets_value()
{
var builder = new SqliteConnectionStringBuilder();
builder["Data Source"] = "test.db";
Assert.Equal("test.db", builder.DataSource);
}
[Theory]
[InlineData("Shared")]
[InlineData("SHARED")]
[InlineData(SqliteCacheMode.Shared)]
[InlineData((int)SqliteCacheMode.Shared)]
public void Item_converts_to_enum_on_set(object value)
{
var builder = new SqliteConnectionStringBuilder();
builder["Cache"] = value;
Assert.Equal(SqliteCacheMode.Shared, builder["Cache"]);
}
[Theory]
[InlineData(42)]
[InlineData("Unknown")]
[InlineData((SqliteCacheMode)42)]
[InlineData(SqliteOpenMode.ReadOnly)]
public void Item_throws_when_cannot_convert_to_enum_on_set(object value)
{
var builder = new SqliteConnectionStringBuilder();
Assert.ThrowsAny<ArgumentException>(() => builder["Cache"] = value);
}
[Fact]
public void Clear_resets_everything()
{
var builder = new SqliteConnectionStringBuilder("Data Source=test.db;Mode=Memory;Cache=Shared");
builder.Clear();
Assert.Empty(builder.DataSource);
Assert.Equal(SqliteOpenMode.ReadWriteCreate, builder.Mode);
Assert.Equal(SqliteCacheMode.Default, builder.Cache);
}
[Fact]
public void ContainsKey_returns_true_when_exists()
{
Assert.True(new SqliteConnectionStringBuilder().ContainsKey("Data Source"));
}
[Fact]
public void ContainsKey_returns_false_when_not_exists()
{
Assert.False(new SqliteConnectionStringBuilder().ContainsKey("Invalid"));
}
[Fact]
public void Remove_returns_false_when_not_exists()
{
Assert.False(new SqliteConnectionStringBuilder().Remove("Invalid"));
}
[Fact]
public void Remove_resets_option()
{
var builder = new SqliteConnectionStringBuilder("Data Source=test.db");
var removed = builder.Remove("Data Source");
Assert.True(removed);
Assert.Empty(builder.DataSource);
}
[Fact]
public void ShouldSerialize_returns_false_when_not_exists()
{
Assert.False(new SqliteConnectionStringBuilder().ShouldSerialize("Invalid"));
}
[Fact]
public void ShouldSerialize_returns_false_when_unset()
{
Assert.False(new SqliteConnectionStringBuilder().ShouldSerialize("Data Source"));
}
[Fact]
public void ShouldSerialize_returns_true_when_set()
{
var builder = new SqliteConnectionStringBuilder("Data Source=test.db");
Assert.True(builder.ShouldSerialize("Data Source"));
}
[Fact]
public void TryGetValue_returns_false_when_not_exists()
{
var retrieved = new SqliteConnectionStringBuilder().TryGetValue("Invalid", out var value);
Assert.False(retrieved);
Assert.Null(value);
}
[Fact]
public void TryGetValue_returns_true_when_exists()
{
var builder = new SqliteConnectionStringBuilder("Data Source=test.db");
var retrieved = builder.TryGetValue("Data Source", out var value);
Assert.True(retrieved);
Assert.Equal("test.db", value);
}
[Fact]
public void ToString_builds_string()
{
var builder = new SqliteConnectionStringBuilder
{
DataSource = "test.db",
Cache = SqliteCacheMode.Shared,
Mode = SqliteOpenMode.Memory
};
Assert.Equal("Data Source=test.db;Mode=Memory;Cache=Shared", builder.ToString());
}
[Fact]
public void ToString_builds_minimal_string()
{
var builder = new SqliteConnectionStringBuilder
{
DataSource = "test.db"
};
Assert.Equal("Data Source=test.db", builder.ToString());
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,29 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using SQLitePCL;
using Xunit;
namespace Microsoft.Data.Sqlite
{
public class SqliteExceptionTest
{
[Fact]
public void Ctor_sets_message_and_errorCode()
{
var ex = new SqliteException("test", 1);
Assert.Equal("test", ex.Message);
Assert.Equal(1, ex.SqliteErrorCode);
}
[Theory]
[InlineData(raw.SQLITE_OK)]
[InlineData(raw.SQLITE_ROW)]
[InlineData(raw.SQLITE_DONE)]
public void ThrowExceptionForRC_does_nothing_when_non_error(int rc)
{
SqliteException.ThrowExceptionForRC(rc, null);
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Xunit;
namespace Microsoft.Data.Sqlite.Tests
{
public class SqliteFactoryTest
{
[Fact]
public void CreateConnection_works()
{
Assert.IsType<SqliteConnection>(SqliteFactory.Instance.CreateConnection());
}
[Fact]
public void CreateConnectionStringBuilder_works()
{
Assert.IsType<SqliteConnectionStringBuilder>(SqliteFactory.Instance.CreateConnectionStringBuilder());
}
[Fact]
public void CreateCommand_works()
{
Assert.IsType<SqliteCommand>(SqliteFactory.Instance.CreateCommand());
}
[Fact]
public void CreateParameter_works()
{
Assert.IsType<SqliteParameter>(SqliteFactory.Instance.CreateParameter());
}
}
}

Просмотреть файл

@ -0,0 +1,526 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Data;
using System.Data.Common;
using Microsoft.Data.Sqlite.Properties;
using Microsoft.Data.Sqlite.TestUtilities;
using Xunit;
namespace Microsoft.Data.Sqlite
{
public class SqliteParameterTest
{
[Fact]
public void Ctor_validates_arguments()
{
var ex = Assert.Throws<ArgumentNullException>(() => new SqliteParameter(null, 1));
Assert.Equal("name", ex.ParamName);
}
[Fact]
public void Ctor_sets_name_and_value()
{
var result = new SqliteParameter("@Parameter", 1);
Assert.Equal("@Parameter", result.ParameterName);
Assert.Equal(1, result.Value);
}
[Fact]
public void Ctor_sets_other_values()
{
var result = new SqliteParameter("@Parameter", SqliteType.Integer, 8, "Column");
Assert.Equal("@Parameter", result.ParameterName);
Assert.Equal(SqliteType.Integer, result.SqliteType);
Assert.Equal(8, result.Size);
Assert.Equal("Column", result.SourceColumn);
}
[Fact]
public void DbType_defaults_to_string()
{
Assert.Equal(DbType.String, new SqliteParameter().DbType);
}
[Fact]
public void Size_validates_argument()
{
var parameter = new SqliteParameter();
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => parameter.Size = -2);
Assert.Equal("value", ex.ParamName);
Assert.Equal(-2, ex.ActualValue);
}
[Fact]
public void SqliteType_defaults_to_text()
{
Assert.Equal(SqliteType.Text, new SqliteParameter().SqliteType);
}
[Fact]
public void Direction_input_by_default()
{
Assert.Equal(ParameterDirection.Input, new SqliteParameter().Direction);
}
[Fact]
public void Direction_validates_value()
{
var ex = Assert.Throws<ArgumentException>(() => new SqliteParameter().Direction = ParameterDirection.Output);
Assert.Equal(Resources.InvalidParameterDirection(ParameterDirection.Output), ex.Message);
}
[Fact]
public void ParameterName_validates_value()
{
var ex = Assert.Throws<ArgumentNullException>(() => new SqliteParameter().ParameterName = null);
Assert.Equal("value", ex.ParamName);
}
[Fact]
public void ResetDbType_works()
{
var parameter = new SqliteParameter
{
DbType = DbType.Int64,
SqliteType = SqliteType.Integer
};
parameter.ResetDbType();
Assert.Equal(DbType.String, parameter.DbType);
Assert.Equal(SqliteType.Text, parameter.SqliteType);
}
[Fact]
public void ResetSqliteType_works()
{
var parameter = new SqliteParameter
{
DbType = DbType.Int64,
SqliteType = SqliteType.Integer
};
parameter.ResetSqliteType();
Assert.Equal(DbType.String, parameter.DbType);
Assert.Equal(SqliteType.Text, parameter.SqliteType);
}
[Fact]
public void Bind_requires_set_name()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Parameter;";
command.Parameters.Add(new SqliteParameter { Value = 1 });
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteNonQuery());
Assert.Equal(Resources.RequiresSet("ParameterName"), ex.Message);
}
}
[Fact]
public void Bind_requires_set_value()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Parameter;";
command.Parameters.Add(new SqliteParameter { ParameterName = "@Parameter" });
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteNonQuery());
Assert.Equal(Resources.RequiresSet("Value"), ex.Message);
}
}
[Fact]
public void Bind_is_noop_on_unknown_parameter()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT 1;";
command.Parameters.AddWithValue("@Unknown", 1);
connection.Open();
command.ExecuteNonQuery();
}
}
[Theory]
[InlineData(true, 1L)]
[InlineData((byte)1, 1L)]
[InlineData('A', 65L)]
[InlineData('A', "A", SqliteType.Text)]
[InlineData(3.14, 3.14)]
[InlineData(3f, 3.0)]
[InlineData(1, 1L)]
[InlineData(1L, 1L)]
[InlineData((sbyte)1, 1L)]
[InlineData((short)1, 1L)]
[InlineData("test", "test")]
[InlineData(1u, 1L)]
[InlineData(1ul, 1L)]
[InlineData((ushort)1, 1L)]
[InlineData("测试测试测试", "测试测试测试")]
[InlineData(double.NegativeInfinity, double.NegativeInfinity)]
[InlineData(double.PositiveInfinity, double.PositiveInfinity)]
[InlineData(float.NegativeInfinity, double.NegativeInfinity)]
[InlineData(float.PositiveInfinity, double.PositiveInfinity)]
public void Bind_works(object value, object coercedValue, SqliteType? sqliteType = null)
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Parameter;";
var sqliteParameter = command.Parameters.AddWithValue("@Parameter", value);
if (sqliteType.HasValue)
{
sqliteParameter.SqliteType = sqliteType.Value;
}
connection.Open();
var result = command.ExecuteScalar();
Assert.Equal(coercedValue, result);
}
}
[Theory]
[InlineData(double.NaN)]
[InlineData(float.NaN)]
public void Bind_throws_for_nan(object value)
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Parameter;";
command.Parameters.AddWithValue("@Parameter", value);
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteScalar());
Assert.Equal(Resources.CannotStoreNaN, ex.Message);
}
}
[Fact]
public void Bind_works_when_byte_array()
{
var bytes = new byte[] { 0x7E, 0x57 };
Bind_works(bytes, bytes);
}
[Fact]
public void Bind_works_when_DateTime()
=> Bind_works(new DateTime(2014, 4, 14, 11, 13, 59), "2014-04-14 11:13:59");
[Fact]
public void Bind_works_when_DateTime_with_SqliteType_Real()
=> Bind_works(new DateTime(2014, 4, 14, 11, 13, 59), 2456761.9680439816, SqliteType.Real);
[Fact]
public void Bind_works_when_DateTimeOffset()
=> Bind_works(new DateTimeOffset(2014, 4, 14, 11, 13, 59, new TimeSpan(-8, 0, 0)), "2014-04-14 11:13:59-08:00");
[Fact]
public void Bind_works_when_DateTimeOffset_with_SqliteType_Real()
=> Bind_works(
new DateTimeOffset(new DateTime(2014, 4, 14, 11, 13, 59)),
2456761.9680439816,
SqliteType.Real);
[Fact]
public void Bind_works_when_DBNull()
=> Bind_works(DBNull.Value, DBNull.Value);
[Fact]
public void Bind_works_when_decimal()
=> Bind_works(3.14m, "3.14");
[Fact]
public void Bind_works_when_decimal_with_integral_value()
=> Bind_works(3m, "3.0");
[Fact]
public void Bind_works_when_Enum()
=> Bind_works(MyEnum.One, 1L);
[Fact]
public void Bind_works_when_Guid()
=> Bind_works(
new Guid("1c902ddb-f4b6-4945-af38-0dc1b0760465"),
new byte[] { 0xDB, 0x2D, 0x90, 0x1C, 0xB6, 0xF4, 0x45, 0x49, 0xAF, 0x38, 0x0D, 0xC1, 0xB0, 0x76, 0x04, 0x65 });
[Fact]
public void Bind_works_when_Guid_with_SqliteType_Text()
=> Bind_works(
new Guid("1c902ddb-f4b6-4945-af38-0dc1b0760465"),
"1C902DDB-F4B6-4945-AF38-0DC1B0760465",
SqliteType.Text);
[Fact]
public void Bind_works_when_Nullable()
=> Bind_works((int?)1, 1L);
[Fact]
public void Bind_works_when_TimeSpan()
=> Bind_works(new TimeSpan(11, 19, 32), "11:19:32");
[Fact]
public void Bind_works_when_TimeSpan_with_SqliteType_Real()
=> Bind_works(new TimeSpan(11, 19, 32), 0.47189814814814812, SqliteType.Real);
[Fact]
public void Bind_throws_when_unknown()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Parameter;";
command.Parameters.AddWithValue("@Parameter", new object());
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteScalar());
Assert.Equal(Resources.UnknownDataType(typeof(object)), ex.Message);
}
}
[Fact]
public void Bind_binds_string_values_without_embedded_nulls()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Text || 'ing';";
command.Parameters.AddWithValue("@Text", "test");
connection.Open();
var result = command.ExecuteScalar();
Assert.Equal("testing", result);
}
}
[Fact]
public void Bind_with_restricted_size_works_on_string_values()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Text;";
command.Parameters.AddWithValue("@Text", "ABCDE").Size = 3;
connection.Open();
var result = command.ExecuteScalar();
Assert.Equal("ABC", result);
}
}
[Fact]
public void Bind_with_sentinel_size_works_on_string_values()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT $value;";
command.Parameters.AddWithValue("$value", "TEST").Size = -1;
connection.Open();
var result = command.ExecuteScalar();
Assert.Equal("TEST", result);
}
}
[Fact]
public void Bind_with_restricted_size_works_on_blob_values()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Blob;";
command.Parameters.AddWithValue("@Blob", new byte[] { 1, 2, 3, 4, 5 }).Size = 3;
connection.Open();
var result = command.ExecuteScalar();
Assert.Equal(new byte[] { 1, 2, 3 }, result);
}
}
[Fact]
public void Bind_with_sentinel_size_works_on_blob_values()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT $value;";
command.Parameters.AddWithValue("$value", new byte[] { 0x7E, 0x57 }).Size = -1;
connection.Open();
var result = command.ExecuteScalar();
Assert.Equal(new byte[] { 0x7E, 0x57 }, result);
}
}
[Theory]
[InlineData("@Parameter")]
[InlineData("$Parameter")]
[InlineData(":Parameter")]
public void Bind_does_not_require_prefix(string parameterName)
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT " + parameterName;
command.Parameters.AddWithValue("Parameter", "harvest");
connection.Open();
var result = command.ExecuteScalar();
Assert.Equal("harvest", result);
}
}
[Fact]
public void Bind_throws_for_ambiguous_parameters()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Param, $Param";
command.Parameters.AddWithValue("Param", 1);
connection.Open();
var ex = Assert.Throws<InvalidOperationException>(() => command.ExecuteScalar());
Assert.Equal(Resources.AmbiguousParameterName("Param"), ex.Message);
}
}
[Fact]
public void Bind_with_prefixed_names()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "SELECT @Param, $Param, :Param";
command.Parameters.AddWithValue("@Param", 1);
command.Parameters.AddWithValue("$Param", 2);
command.Parameters.AddWithValue(":Param", 3);
connection.Open();
using (var reader = command.ExecuteReader())
{
Assert.True(reader.Read());
Assert.Equal(1, reader.GetFieldValue<int>(0));
Assert.Equal(2, reader.GetFieldValue<int>(1));
Assert.Equal(3, reader.GetFieldValue<int>(2));
}
}
}
[Fact, UseCulture("ar-SA")]
public void Bind_DateTime_with_Arabic_Culture()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
connection.ExecuteNonQuery("CREATE TABLE Person(DateOfBirth datetime);");
var command = connection.CreateCommand();
command.CommandText = "INSERT INTO Person(DateOfBirth) VALUES (@DateOfBirth);";
var date = new DateTime(2018, 3, 25);
command.Parameters.AddWithValue("DateOfBirth", date);
Assert.Equal(1, command.ExecuteNonQuery());
command.CommandText = "SELECT DateOfBirth FROM Person;";
var result = command.ExecuteScalar();
Assert.Equal("2018-03-25 00:00:00", (string)result);
using (var reader = command.ExecuteReader())
{
Assert.True(reader.Read());
Assert.Equal("2018-03-25 00:00:00", reader.GetString(0));
Assert.Equal(date, reader.GetDateTime(0));
}
}
}
[Fact, UseCulture("ar-SA")]
public void Bind_DateTimeOffset_with_Arabic_Culture()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
connection.ExecuteNonQuery("CREATE TABLE Test(date TEXT);");
var command = connection.CreateCommand();
command.CommandText = "INSERT INTO Test(date) VALUES (@date);";
var date = new DateTimeOffset(new DateTime(2018, 3, 25), new TimeSpan());
command.Parameters.AddWithValue("date", date);
Assert.Equal(1, command.ExecuteNonQuery());
command.CommandText = "SELECT date FROM Test;";
var result = command.ExecuteScalar();
Assert.Equal("2018-03-25 00:00:00+00:00", (string)result);
using (var reader = command.ExecuteReader())
{
Assert.True(reader.Read());
Assert.Equal("2018-03-25 00:00:00+00:00", reader.GetString(0));
Assert.Equal(date, reader.GetDateTimeOffset(0));
}
}
}
[Fact]
public void Add_range_of_parameters_using_DbCommand_base_class()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand() as DbCommand;
command.CommandText = "SELECT @Value1, @Value2;";
var parameterValue1 = new SqliteParameter("@Value1", SqliteType.Text);
parameterValue1.Value = "ABCDE";
var parameterValue2 = new SqliteParameter("@Value2", SqliteType.Text);
parameterValue2.Value = "FGHIJ";
var parameters = new[] { parameterValue1, parameterValue2 };
command.Parameters.AddRange(parameters);
connection.Open();
using (var reader = command.ExecuteReader())
{
Assert.True(reader.Read());
Assert.Equal(parameterValue1.Value, reader.GetString(0));
Assert.Equal(parameterValue2.Value, reader.GetString(1));
}
}
}
private enum MyEnum
{
One = 1
}
}
}

Просмотреть файл

@ -0,0 +1,340 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Data;
using Microsoft.Data.Sqlite.Properties;
using SQLitePCL;
using Xunit;
namespace Microsoft.Data.Sqlite
{
public class SqliteTransactionTest
{
[Fact]
public void Ctor_sets_read_uncommitted()
{
using (var connection = new SqliteConnection("Data Source=:memory:;Cache=Shared"))
{
connection.Open();
using (connection.BeginTransaction(IsolationLevel.ReadUncommitted))
{
Assert.Equal(1L, connection.ExecuteScalar<long>("PRAGMA read_uncommitted;"));
}
}
}
[Fact]
public void Ctor_unsets_read_uncommitted_when_serializable()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
using (connection.BeginTransaction(IsolationLevel.Serializable))
{
Assert.Equal(0L, connection.ExecuteScalar<long>("PRAGMA read_uncommitted;"));
}
}
}
[Theory]
[InlineData(IsolationLevel.Chaos)]
[InlineData(IsolationLevel.Snapshot)]
public void Ctor_throws_when_invalid_isolation_level(IsolationLevel isolationLevel)
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var ex = Assert.Throws<ArgumentException>(() => connection.BeginTransaction(isolationLevel));
Assert.Equal(Resources.InvalidIsolationLevel(isolationLevel), ex.Message);
}
}
[Fact]
public void ReadUncommitted_allows_dirty_reads()
{
const string connectionString = "Data Source=read-uncommitted;Mode=Memory;Cache=Shared";
using (var connection1 = new SqliteConnection(connectionString))
using (var connection2 = new SqliteConnection(connectionString))
{
connection1.Open();
connection2.Open();
connection1.ExecuteNonQuery("CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
using (connection1.BeginTransaction())
using (connection2.BeginTransaction(IsolationLevel.ReadUncommitted))
{
connection1.ExecuteNonQuery("UPDATE Data SET Value = 1;");
var value = connection2.ExecuteScalar<long>("SELECT * FROM Data;");
Assert.Equal(1, value);
}
}
}
[Fact]
public void Serialized_disallows_dirty_reads()
{
const string connectionString = "Data Source=serialized;Mode=Memory;Cache=Shared";
using (var connection1 = new SqliteConnection(connectionString))
using (var connection2 = new SqliteConnection(connectionString))
{
connection1.Open();
connection2.Open();
connection1.ExecuteNonQuery("CREATE TABLE Data (Value); INSERT INTO Data VALUES (0);");
using (connection1.BeginTransaction())
{
connection1.ExecuteNonQuery("UPDATE Data SET Value = 1;");
connection2.DefaultTimeout = 0;
var ex = Assert.Throws<SqliteException>(
() =>
{
using (connection2.BeginTransaction(IsolationLevel.Serializable))
{
connection2.ExecuteScalar<long>("SELECT * FROM Data;");
}
});
Assert.Equal(raw.SQLITE_LOCKED, ex.SqliteErrorCode);
Assert.Equal(raw.SQLITE_LOCKED_SHAREDCACHE, ex.SqliteExtendedErrorCode);
}
}
}
[Fact]
public void IsolationLevel_throws_when_completed()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var transaction = connection.BeginTransaction();
transaction.Dispose();
var ex = Assert.Throws<InvalidOperationException>(() => transaction.IsolationLevel);
Assert.Equal(Resources.TransactionCompleted, ex.Message);
}
}
[Fact]
public void IsolationLevel_is_inferred_when_unspecified()
{
using (var connection = new SqliteConnection("Data Source=:memory:;Cache=Shared"))
{
connection.Open();
connection.ExecuteNonQuery("PRAGMA read_uncommitted = 1;");
using (var transaction = connection.BeginTransaction())
{
Assert.Equal(IsolationLevel.ReadUncommitted, transaction.IsolationLevel);
}
}
}
[Theory]
[InlineData(IsolationLevel.ReadUncommitted)]
[InlineData(IsolationLevel.ReadCommitted)]
[InlineData(IsolationLevel.RepeatableRead)]
public void IsolationLevel_is_increased_when_unsupported(IsolationLevel isolationLevel)
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
using (var transaction = connection.BeginTransaction(isolationLevel))
{
Assert.Equal(IsolationLevel.Serializable, transaction.IsolationLevel);
}
}
}
[Fact]
public void Commit_throws_when_completed()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var transaction = connection.BeginTransaction();
transaction.Dispose();
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Commit());
Assert.Equal(Resources.TransactionCompleted, ex.Message);
}
}
[Fact]
public void Commit_throws_when_completed_externally()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
connection.ExecuteNonQuery("ROLLBACK;");
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Commit());
Assert.Equal(Resources.TransactionCompleted, ex.Message);
}
}
}
[Fact]
public void Commit_throws_when_connection_closed()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
connection.Close();
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Commit());
Assert.Equal(Resources.TransactionCompleted, ex.Message);
}
}
}
[Fact]
public void Commit_works()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
CreateTestTable(connection);
using (var transaction = connection.BeginTransaction())
{
connection.ExecuteNonQuery("INSERT INTO TestTable VALUES (1);");
transaction.Commit();
Assert.Null(connection.Transaction);
Assert.Null(transaction.Connection);
}
Assert.Equal(1L, connection.ExecuteScalar<long>("SELECT COUNT(*) FROM TestTable;"));
}
}
[Fact]
public void Rollback_noops_once_when_completed_externally()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
connection.ExecuteNonQuery("ROLLBACK;");
transaction.Rollback();
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Rollback());
Assert.Equal(Resources.TransactionCompleted, ex.Message);
}
}
}
[Fact]
public void Rollback_throws_when_completed()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var transaction = connection.BeginTransaction();
transaction.Dispose();
var ex = Assert.Throws<InvalidOperationException>(() => transaction.Rollback());
Assert.Equal(Resources.TransactionCompleted, ex.Message);
}
}
[Fact]
public void Rollback_works()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
CreateTestTable(connection);
using (var transaction = connection.BeginTransaction())
{
connection.ExecuteNonQuery("INSERT INTO TestTable VALUES (1);");
transaction.Rollback();
Assert.Null(connection.Transaction);
Assert.Null(transaction.Connection);
}
Assert.Equal(0L, connection.ExecuteScalar<long>("SELECT COUNT(*) FROM TestTable;"));
}
}
[Fact]
public void Dispose_works()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
CreateTestTable(connection);
using (var transaction = connection.BeginTransaction())
{
connection.ExecuteNonQuery("INSERT INTO TestTable VALUES (1);");
transaction.Dispose();
Assert.Null(connection.Transaction);
Assert.Null(transaction.Connection);
}
Assert.Equal(0L, connection.ExecuteScalar<long>("SELECT COUNT(*) FROM TestTable;"));
}
}
[Fact]
public void Dispose_can_be_called_more_than_once()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();
var transaction = connection.BeginTransaction();
transaction.Dispose();
transaction.Dispose();
}
}
private static void CreateTestTable(SqliteConnection connection)
{
connection.ExecuteNonQuery(
@"
CREATE TABLE TestTable (
TestColumn INTEGER
)");
}
}
}

Просмотреть файл

@ -0,0 +1,46 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Reflection;
using Xunit.Sdk;
namespace Microsoft.Data.Sqlite.TestUtilities
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class UseCultureAttribute : BeforeAfterTestAttribute
{
private CultureInfo _originalCulture;
private CultureInfo _originalUICulture;
public UseCultureAttribute(string culture)
: this(culture, culture)
{
}
public UseCultureAttribute(string culture, string uiCulture)
{
Culture = new CultureInfo(culture);
UICulture = new CultureInfo(uiCulture);
}
public CultureInfo Culture { get; }
public CultureInfo UICulture { get; }
public override void Before(MethodInfo methodUnderTest)
{
_originalCulture = CultureInfo.CurrentCulture;
_originalUICulture = CultureInfo.CurrentUICulture;
CultureInfo.CurrentCulture = Culture;
CultureInfo.CurrentUICulture = UICulture;
}
public override void After(MethodInfo methodUnderTest)
{
CultureInfo.CurrentCulture = _originalCulture;
CultureInfo.CurrentUICulture = _originalUICulture;
}
}
}

149
tools/SqliteResources.tt Normal file
Просмотреть файл

@ -0,0 +1,149 @@
<#@ template hostspecific="true" #>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Windows.Forms" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Resources" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="EnvDTE" #>
<#
var model = LoadResources();
#>
// <auto-generated />
using System.Reflection;
using System.Resources;
namespace <#= model.Namespace #>
{
internal static class <#= model.Class #>
{
private static readonly ResourceManager _resourceManager
= new ResourceManager("<#= model.ResourceName #>", typeof(<#= model.Class #>).GetTypeInfo().Assembly);
<#
foreach (var resource in model.Resources)
{
#>
/// <summary>
<#
foreach (var line in Lines(resource.Value))
{
#>
/// <#= Xml(line) #>
<#
}
#>
/// </summary>
<#
if (resource.Parameters.Any())
{
#>
public static string <#= resource.Name #>(<#= List("object ", resource.Parameters) #>)
=> string.Format(
GetString("<#= resource.Name #>", <#= List("nameof(", resource.Parameters, ")") #>),
<#= List(resource.Parameters) #>);
<#
}
else
{
#>
public static string <#= resource.Name #>
=> GetString("<#= resource.Name #>");
<#
}
}
#>
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);
for (var i = 0; i < formatterNames.Length; i++)
{
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
}
return value;
}
}
}
<#+
ResourceFile LoadResources()
{
var result = new ResourceFile();
var services = (IServiceProvider)Host;
var dte = (DTE)services.GetService(typeof(DTE));
var resourceFile = (string)Session["ResourceFile"];
if (!Path.IsPathRooted(resourceFile))
{
resourceFile = Host.ResolvePath(resourceFile);
}
var resourceProjectItem = dte.Solution.FindProjectItem(resourceFile);
var templateProjectItem = dte.Solution.FindProjectItem(Host.TemplateFile);
var project = templateProjectItem.ContainingProject;
var rootNamespace = (string)project.Properties.Item("RootNamespace").Value;
var resourceDir = Path.GetDirectoryName(resourceFile);
var projectDir = (string)project.Properties.Item("FullPath").Value;
var resourceNamespace = rootNamespace + "." + resourceDir.Substring(projectDir.Length)
.Replace(Path.DirectorySeparatorChar, '.');
result.Namespace = (string)resourceProjectItem.Properties.Item("CustomToolNamespace")?.Value;
if (string.IsNullOrEmpty(result.Namespace))
{
result.Namespace = resourceNamespace;
}
result.Class = Path.GetFileNameWithoutExtension(resourceFile);
result.ResourceName = resourceNamespace + "." + result.Class;
using (var reader = new ResXResourceReader(resourceFile))
{
result.Resources = Enumerable.ToList(
from DictionaryEntry r in reader
let value = (string)r.Value
select new Resource
{
Name = (string)r.Key,
Value = value,
Parameters = Regex.Matches(value, @"\{(\w+)\}").Cast<Match>().Select(m => m.Groups[1].Value)
.Distinct().ToList()
});
}
return result;
}
IEnumerable<string> Lines(string value)
=> value.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
string Xml(string value)
=> value.Replace("<", "&lt;").Replace(">", "&gt;");
string List(IEnumerable<string> items)
=> List(null, items);
string List(string prefix, IEnumerable<string> items, string suffix = null)
=> string.Join(", ", items.Select(i => prefix + i + suffix));
class ResourceFile
{
public string Namespace { get; set; }
public string Class { get; set; }
public string ResourceName { get; set; }
public IEnumerable<Resource> Resources { get; set; }
}
class Resource
{
public string Name { get; set; }
public string Value { get; set; }
public IEnumerable<string> Parameters { get; set; }
}
#>