From af22225f70d28d111cb5430470e952947a8f6c88 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Tue, 12 Aug 2025 18:29:31 -0700 Subject: [PATCH] Code cleanup for src Part of #35884 --- src/Directory.Build.props | 2 +- .../Internal/ObservableBackedBindingList.cs | 4 +- .../Internal/SortableBindingList.cs | 30 +- .../ObservableCollectionListSource.cs | 22 +- .../EntityTypeConfigurationAttribute.cs | 5 +- .../ObservableCollectionExtensions.cs | 4 +- src/EFCore.Analyzers/EFCore.Analyzers.nuspec | 3 +- .../InternalUsageDiagnosticAnalyzer.cs | 12 +- ...dStringUsageInRawQueriesCodeFixProvider.cs | 6 +- ...ringUsageInRawQueriesDiagnosticAnalyzer.cs | 3 +- .../Internal/StringDictionaryComparer.cs | 5 +- .../Internal/CosmosLoggerExtensions.cs | 25 +- .../Extensions/CosmosDbFunctionsExtensions.cs | 6 +- .../CosmosEntityTypeBuilderExtensions.cs | 12 +- .../Extensions/CosmosEntityTypeExtensions.cs | 2 +- .../CosmosIndexBuilderExtensions.cs | 9 +- .../Extensions/CosmosIndexExtensions.cs | 9 +- .../CosmosPropertyBuilderExtensions.cs | 29 +- .../CosmosServiceCollectionExtensions.cs | 32 +- .../CosmosTriggerBuilderExtensions.cs | 1 - .../Extensions/CosmosTriggerExtensions.cs | 3 +- .../CosmosShapedQueryExpressionExtensions.cs | 4 +- ...osmosPartitionKeyInPrimaryKeyConvention.cs | 2 +- .../Internal/CosmosConventionSetBuilder.cs | 7 +- .../Query/Internal/CosmosAliasManager.cs | 8 +- ...osmosProjectionBindingExpressionVisitor.cs | 2 +- .../Internal/CosmosQueryCompilationContext.cs | 2 +- .../Query/Internal/CosmosQuerySqlGenerator.cs | 4 +- ...yableMethodTranslatingExpressionVisitor.cs | 48 +- ...CosmosReadItemAndPartitionKeysExtractor.cs | 4 +- ...ionBindingRemovingExpressionVisitorBase.cs | 5 +- ...ilingExpressionVisitor.ParameterInliner.cs | 28 +- ...osShapedQueryCompilingExpressionVisitor.cs | 4 +- .../CosmosSqlTranslatingExpressionVisitor.cs | 47 +- .../Expressions/FragmentExpression.cs | 3 +- .../Internal/Expressions/PagingExpression.cs | 1 + .../Internal/Expressions/SelectExpression.cs | 8 +- .../Query/Internal/ISqlExpressionFactory.cs | 6 +- .../Query/Internal/SqlExpressionFactory.cs | 8 +- .../CosmosFullTextSearchTranslator.cs | 54 +- .../Translators/CosmosRandomTranslator.cs | 2 +- .../Translators/CosmosRegexTranslator.cs | 4 +- .../CosmosStringMemberTranslator.cs | 2 +- .../CosmosStringMethodTranslator.cs | 10 +- .../CosmosTypeCheckingTranslator.cs | 1 + .../CosmosVectorSearchTranslator.cs | 12 +- .../Query/VectorDistanceOptions.cs | 5 +- .../Storage/Internal/CosmosClientWrapper.cs | 28 +- .../Storage/Internal/CosmosDatabaseCreator.cs | 6 +- .../Internal/CosmosTypeMappingSource.cs | 3 +- .../Update/Internal/DocumentSource.cs | 3 +- .../DesignTimeServiceCollectionExtensions.cs | 65 +- .../Design/Internal/DatabaseOperations.cs | 2 +- .../Design/Internal/DbContextOperations.cs | 12 +- .../Design/Internal/MigrationsOperations.cs | 2 +- src/EFCore.Design/Design/OperationExecutor.cs | 68 +- .../Extensions/ScaffoldingModelExtensions.cs | 10 +- .../Design/CSharpMigrationsGenerator.cs | 15 +- .../Design/CSharpSnapshotGenerator.cs | 64 +- .../Migrations/Design/MigrationsBundle.cs | 17 +- .../Design/MigrationsCodeGenerator.cs | 20 +- .../Migrations/Design/MigrationsScaffolder.cs | 4 +- .../Internal/SnapshotModelProcessor.cs | 5 +- .../Query/Internal/CSharpToLinqTranslator.cs | 136 +- .../Internal/LinqToCSharpSyntaxTranslator.cs | 122 +- .../Internal/PrecompiledQueryCodeGenerator.cs | 38 +- .../Query/Internal/QueryLocator.cs | 2 +- ...untimeModelLinqToCSharpSyntaxTranslator.cs | 13 +- .../CSharpRuntimeModelCodeGenerator.cs | 38 +- .../RelationalScaffoldingModelFactory.cs | 11 +- .../Internal/TextTemplatingEngineHost.cs | 8 +- ...Microsoft.EntityFrameworkCore.Design.props | 2 +- .../InMemoryServiceCollectionExtensions.cs | 13 +- .../InMemoryConventionSetBuilder.cs | 7 +- ...yExpressionTranslatingExpressionVisitor.cs | 47 +- .../Query/Internal/InMemoryQueryExpression.cs | 71 +- ...yableMethodTranslatingExpressionVisitor.cs | 33 +- ...erExpressionProcessingExpressionVisitor.cs | 2 +- .../Storage/Internal/InMemoryStoreProvider.cs | 5 +- .../Storage/Internal/InMemoryTable.cs | 9 +- .../Proxies/Internal/IProxyLazyLoader.cs | 3 +- .../ProxiesServiceCollectionExtensions.cs | 3 +- .../Design/AnnotationCodeGenerator.cs | 14 +- ...nalCSharpRuntimeAnnotationCodeGenerator.cs | 16 +- .../Diagnostics/RelationalLoggerExtensions.cs | 69 +- src/EFCore.Relational/EFExtensions.cs | 3 +- ...CollectionTypePropertyBuilderExtensions.cs | 3 +- .../RelationalDatabaseFacadeExtensions.cs | 2 +- .../RelationalEntityTypeExtensions.cs | 18 +- .../RelationalForeignKeyExtensions.cs | 2 +- .../Extensions/RelationalIndexExtensions.cs | 2 +- .../Extensions/RelationalKeyExtensions.cs | 2 +- .../RelationalPropertyExtensions.cs | 64 +- .../RelationalTypeBaseExtensions.cs | 34 +- ...ntityFrameworkRelationalServicesBuilder.cs | 4 +- .../RelationalDbContextOptionsBuilder.cs | 6 +- .../RelationalModelValidator.cs | 89 +- .../Conventions/CheckConstraintConvention.cs | 2 +- .../Conventions/EntitySplittingConvention.cs | 7 +- .../EntityTypeHierarchyMappingConvention.cs | 7 +- .../RelationalKeyDiscoveryConvention.cs | 6 +- .../Conventions/SharedTableConvention.cs | 26 +- .../TableSharingConcurrencyTokenConvention.cs | 10 +- src/EFCore.Relational/Metadata/ITableIndex.cs | 17 +- .../Metadata/Internal/DbFunction.cs | 2 +- .../RelationalEntityTypeExtensions.cs | 2 +- .../RelationalForeignKeyExtensions.cs | 9 +- .../Metadata/Internal/RelationalModel.cs | 33 +- .../Internal/RelationalTypeBaseExtensions.cs | 2 +- .../Metadata/Internal/Sequence.cs | 34 +- .../Metadata/Internal/TableBase.cs | 4 +- .../Metadata/RelationalAnnotationProvider.cs | 38 +- .../Metadata/RuntimeStoredProcedure.cs | 25 +- .../Migrations/HistoryRepository.cs | 25 +- .../Migrations/IHistoryRepository.cs | 2 + .../Migrations/IMigrationCommandExecutor.cs | 4 +- .../IMigrationsAnnotationProvider.cs | 8 +- .../Migrations/IMigrationsDatabaseLock.cs | 14 +- src/EFCore.Relational/Migrations/IMigrator.cs | 12 +- .../Internal/MigrationCommandExecutor.cs | 27 +- .../Internal/MigrationsModelDiffer.cs | 95 +- .../Migrations/Internal/Migrator.cs | 82 +- .../Migrations/MigrationExecutionState.cs | 2 +- .../MigrationsAnnotationProvider.cs | 28 +- .../Migrations/MigrationsSqlGenerator.cs | 2 +- .../QueryableAggregateMethodTranslator.cs | 16 +- .../Query/Internal/RelationalCommandCache.cs | 3 +- .../Internal/RelationalParameterProcessor.cs | 10 +- ...ionalProjectionBindingExpressionVisitor.cs | 7 +- ...ationalStructuralTypeMaterializerSource.cs | 4 +- ...lExpressionSimplifyingExpressionVisitor.cs | 96 +- .../Query/Internal/TpcTablesExpression.cs | 5 +- .../Translators/ComparisonTranslator.cs | 5 +- .../Translators/EnumMethodTranslator.cs | 9 +- .../Internal/Translators/RandomTranslator.cs | 4 +- .../Query/JsonQueryExpression.cs | 22 +- src/EFCore.Relational/Query/PathSegment.cs | 4 +- .../Query/QuerySqlGenerator.cs | 16 +- ...alAggregateMethodCallTranslatorProvider.cs | 2 +- .../RelationalExpressionQuotingUtilities.cs | 20 +- ...nalParameterBasedSqlProcessorParameters.cs | 4 +- ...anslatingExpressionVisitor.CreateSelect.cs | 31 +- ...nslatingExpressionVisitor.ExecuteUpdate.cs | 29 +- ...yableMethodTranslatingExpressionVisitor.cs | 96 +- ...ocessingExpressionVisitor.ClientMethods.cs | 6 +- ...sitor.ShaperProcessingExpressionVisitor.cs | 127 +- ...alShapedQueryCompilingExpressionVisitor.cs | 36 +- ...ingExpressionVisitor.StructuralEquality.cs | 88 +- ...lationalSqlTranslatingExpressionVisitor.cs | 37 +- ...elationalStructuralTypeShaperExpression.cs | 16 +- .../RelationalTypeMappingPostprocessor.cs | 8 +- .../Query/SqlAliasManager.cs | 6 +- .../Query/SqlExpressionFactory.cs | 39 +- .../Query/SqlExpressions/CaseExpression.cs | 11 +- .../SqlExpressions/SelectExpression.Helper.cs | 9 +- .../Query/SqlExpressions/SelectExpression.cs | 126 +- .../SqlExpressions/SqlConstantExpression.cs | 2 +- .../SqlExpressions/TableExpressionBase.cs | 4 +- .../Query/SqlExpressions/UpdateExpression.cs | 11 +- .../Query/SqlNullabilityProcessor.cs | 92 +- src/EFCore.Relational/Query/SqlTreePruner.cs | 6 +- .../DatabaseModelFactoryOptions.cs | 4 +- .../Internal/RawRelationalParameter.cs | 3 +- .../Storage/JsonTypePlaceholder.cs | 2 +- .../Storage/RelationalConnection.cs | 2 +- .../Storage/RelationalDatabaseCreator.cs | 6 +- .../RelationalDatabaseCreatorDependencies.cs | 2 +- .../Storage/RelationalTypeMappingSource.cs | 4 +- .../AffectedCountModificationCommandBatch.cs | 12 +- .../Update/ColumnModification.cs | 27 +- .../Update/Internal/CommandBatchPreparer.cs | 38 +- .../Update/ModificationCommand.cs | 52 +- .../Update/ReaderModificationCommandBatch.cs | 9 +- ...rHierarchyIdServiceCollectionExtensions.cs | 1 - .../SqlServerHierarchyIdOptionsExtension.cs | 1 - ...erHierarchyIdMethodCallTranslatorPlugin.cs | 4 +- .../SqlServerHierarchyIdMethodTranslator.cs | 1 - ...rameworkCore.SqlServer.HierarchyId.targets | 5 +- ...erverGeometryCollectionMemberTranslator.cs | 4 +- ...erverGeometryCollectionMethodTranslator.cs | 2 +- .../SqlServerGeometryMemberTranslator.cs | 8 +- .../SqlServerGeometryMethodTranslator.cs | 7 +- .../SqlServerLineStringMemberTranslator.cs | 4 +- .../SqlServerLineStringMethodTranslator.cs | 5 +- ...qlServerMultiLineStringMemberTranslator.cs | 4 +- ...uiteAggregateMethodCallTranslatorPlugin.cs | 6 +- ...tTopologySuiteAggregateMethodTranslator.cs | 2 +- ...ogySuiteDbFunctionsMethodCallTranslator.cs | 4 +- ...rNetTopologySuiteMemberTranslatorPlugin.cs | 6 +- ...TopologySuiteMethodCallTranslatorPlugin.cs | 6 +- .../SqlServerPolygonMemberTranslator.cs | 10 +- .../SqlServerPolygonMethodTranslator.cs | 10 +- ...orkCore.SqlServer.NetTopologySuite.targets | 5 +- .../SqlServerAnnotationCodeGenerator.cs | 43 +- ...verComplexTypePropertyBuilderExtensions.cs | 6 +- .../SqlServerDbFunctionsExtensions.cs | 8 +- .../SqlServerEntityTypeExtensions.cs | 2 +- ...verPrimitiveCollectionBuilderExtensions.cs | 6 +- .../SqlServerPropertyBuilderExtensions.cs | 28 +- .../Extensions/SqlServerPropertyExtensions.cs | 22 +- .../SqlServerServiceCollectionExtensions.cs | 46 +- .../Extensions/SqlServerTableExtensions.cs | 4 +- .../Internal/SqlServerModelValidator.cs | 27 +- .../Internal/SqlServerOptionsExtension.cs | 6 +- .../SqlServerConventionSetBuilder.cs | 7 +- .../SqlServerOnDeleteConvention.cs | 5 +- .../SqlServerOutputClauseConvention.cs | 4 +- .../SqlServerTemporalConvention.cs | 6 +- .../Internal/SqlServerAnnotationProvider.cs | 36 +- .../Internal/SqlServerIndexExtensions.cs | 12 +- .../Internal/SqlServerHistoryRepository.cs | 3 +- .../SqlServerMigrationDatabaseLock.cs | 3 +- .../SqlServerMigrationsSqlGenerator.cs | 9 +- .../SqlServerOpenJsonExpression.cs | 31 +- ...erverAggregateOverSubqueryPostprocessor.cs | 12 +- .../Internal/SqlServerJsonPostprocessor.cs | 17 +- ...rNavigationExpansionExtensibilityHelper.cs | 4 +- .../Internal/SqlServerQuerySqlGenerator.cs | 28 +- ...yableMethodTranslatingExpressionVisitor.cs | 167 +- .../SqlServerSqlNullabilityProcessor.cs | 97 +- ...qlServerSqlTranslatingExpressionVisitor.cs | 28 +- .../Query/Internal/SqlServerSqlTreePruner.cs | 2 +- .../SqlServerTypeMappingPostprocessor.cs | 6 +- .../Translators/SqlServerConvertTranslator.cs | 16 +- .../SqlServerDateDiffFunctionsTranslator.cs | 4 +- .../SqlServerDateTimeMemberTranslator.cs | 9 +- .../SqlServerIsDateFunctionTranslator.cs | 2 +- .../SqlServerIsNumericFunctionTranslator.cs | 2 +- .../SqlServerLongCountMethodTranslator.cs | 4 +- .../Translators/SqlServerMathTranslator.cs | 16 +- .../Translators/SqlServerNewGuidTranslator.cs | 4 +- .../SqlServerObjectToStringTranslator.cs | 12 +- ...rverStatisticsAggregateMethodTranslator.cs | 2 +- ...qlServerStringAggregateMethodTranslator.cs | 5 +- .../SqlServerStringMemberTranslator.cs | 2 +- .../SqlServerStringMethodTranslator.cs | 58 +- .../SqlServerTimeOnlyMethodTranslator.cs | 2 +- .../Translators/SqlServerVectorTranslator.cs | 4 +- .../Internal/SqlServerDatabaseModelFactory.cs | 112 +- .../Storage/Internal/SqlServerConnection.cs | 6 +- .../Internal/SqlServerDatabaseCreator.cs | 26 +- .../SqlServerStructuralJsonTypeMapping.cs | 4 +- .../Internal/SqlServerTypeMappingSource.cs | 22 +- .../Internal/SqlServerVectorTypeMapping.cs | 2 +- .../Internal/SqlServerUpdateSqlGenerator.cs | 31 +- .../SqliteServiceCollectionExtensions.cs | 14 +- .../Extensions/SqliteTableExtensions.cs | 4 +- .../Internal/SqliteModelValidator.cs | 11 +- .../Infrastructure/SpatialiteLoader.cs | 9 +- .../Conventions/SqliteConventionSetBuilder.cs | 7 +- .../Internal/SqliteAnnotationProvider.cs | 3 +- .../Internal/SqliteHistoryRepository.cs | 11 +- .../Internal/SqliteMigrationDatabaseLock.cs | 3 +- .../SqlExpressions/JsonEachExpression.cs | 2 +- .../SqliteParameterBasedSqlProcessor.cs | 1 - .../Query/Internal/SqliteQuerySqlGenerator.cs | 15 +- ...yableMethodTranslatingExpressionVisitor.cs | 94 +- .../Internal/SqliteSqlExpressionFactory.cs | 4 +- .../Internal/SqliteSqlNullabilityProcessor.cs | 2 +- .../SqliteSqlTranslatingExpressionVisitor.cs | 42 +- .../SqliteByteArrayMethodTranslator.cs | 4 +- .../SqliteDateTimeMemberTranslator.cs | 12 +- .../SqliteDateTimeMethodTranslator.cs | 10 +- .../Translators/SqliteHexMethodTranslator.cs | 2 +- .../Translators/SqliteMathTranslator.cs | 5 +- .../SqliteObjectToStringTranslator.cs | 10 +- ...qliteQueryableAggregateMethodTranslator.cs | 6 +- .../Translators/SqliteRandomTranslator.cs | 9 +- .../SqliteStringAggregateMethodTranslator.cs | 5 +- .../SqliteStringLengthTranslator.cs | 2 +- .../SqliteStringMethodTranslator.cs | 64 +- .../Internal/SqliteDatabaseModelFactory.cs | 13 +- .../Storage/Internal/SqliteJsonTypeMapping.cs | 1 - .../Internal/SqliteRelationalConnection.cs | 8 +- .../Internal/SqliteModificationCommand.cs | 2 +- ...qliteGeometryCollectionMemberTranslator.cs | 2 +- .../SqliteGeometryMemberTranslator.cs | 33 +- .../SqliteGeometryMethodTranslator.cs | 12 +- .../SqliteLineStringMemberTranslator.cs | 9 +- .../SqliteLineStringMethodTranslator.cs | 5 +- .../SqliteMultiLineStringMemberTranslator.cs | 7 +- ...uiteAggregateMethodCallTranslatorPlugin.cs | 2 +- ...tTopologySuiteAggregateMethodTranslator.cs | 9 +- ...eNetTopologySuiteMemberTranslatorPlugin.cs | 6 +- ...TopologySuiteMethodCallTranslatorPlugin.cs | 6 +- .../Internal/SqlitePointMemberTranslator.cs | 2 +- .../Internal/SqlitePolygonMemberTranslator.cs | 2 +- .../Internal/SqlitePolygonMethodTranslator.cs | 2 +- ...meworkCore.Sqlite.NetTopologySuite.targets | 5 +- src/EFCore.Tasks/EFCore.Tasks.nuspec | 2 +- src/EFCore.Tasks/Tasks/OptimizeDbContext.cs | 2 +- .../Microsoft.EntityFrameworkCore.Tasks.props | 10 +- ...icrosoft.EntityFrameworkCore.Tasks.targets | 26 +- src/EFCore.Tools/EFCore.Tools.nuspec | 2 +- .../Internal/ExpressionExtensions.cs | 3 +- .../Extensions/SQLitePCLExtensions.cs | 39 +- .../Extensions/SqliteConnectionExtensions.cs | 53 +- .../Extensions/TypeExtensions.cs | 18 +- src/Microsoft.Data.Sqlite.Core/SqliteBlob.cs | 561 ++-- .../SqliteCacheMode.cs | 37 +- .../SqliteCommand.cs | 869 +++--- .../SqliteConnection.CreateAggregate.cs | 2568 ++++++++++------- .../SqliteConnection.CreateFunction.cs | 1721 ++++++----- .../SqliteConnection.cs | 1574 +++++----- .../SqliteConnectionFactory.cs | 234 +- .../SqliteConnectionInternal.cs | 364 ++- .../SqliteConnectionPool.cs | 219 +- .../SqliteConnectionPoolGroup.cs | 131 +- .../SqliteConnectionStringBuilder.cs | 815 +++--- .../SqliteDataReader.cs | 1373 +++++---- .../SqliteDataRecord.cs | 734 +++-- .../SqliteException.cs | 131 +- .../SqliteFactory.cs | 81 +- .../SqliteOpenMode.cs | 43 +- .../SqliteParameter.cs | 416 ++- .../SqliteParameterBinder.cs | 85 +- .../SqliteParameterCollection.cs | 623 ++-- .../SqliteParameterReader.cs | 35 +- .../SqliteResultBinder.cs | 27 +- .../SqliteTransaction.cs | 371 ++- src/Microsoft.Data.Sqlite.Core/SqliteType.cs | 43 +- .../SqliteValueBinder.cs | 493 ++-- .../SqliteValueReader.cs | 709 +++-- .../Utilities/AllowNullAttribute.cs | 1 - .../Utilities/MemberNotNullAttribute.cs | 1 - .../Utilities/SharedStopwatch.cs | 9 +- src/Shared/DictionaryExtensions.cs | 4 +- src/dotnet-ef/Project.cs | 5 +- src/dotnet-ef/dotnet-ef.csproj | 21 +- src/dotnet-ef/dotnet-ef.nuspec | 3 +- src/ef/AppDomainOperationExecutor.cs | 8 +- src/ef/CommandException.cs | 2 - src/ef/CommandLineUtils/CommandArgument.cs | 2 +- .../CommandLineApplication.cs | 9 +- src/ef/Commands/CommandBase.cs | 17 +- src/ef/Commands/ProjectCommandBase.cs | 216 +- src/ef/IOperationExecutor.cs | 1 + src/ef/NotNullIfNotNullAttribute.cs | 4 +- src/ef/OperationExecutorBase.cs | 2 +- src/ef/Program.cs | 1 - src/ef/ReflectionOperationExecutor.cs | 12 +- .../Design/SnapshotModelProcessorTest.cs | 2 +- .../RelationalModelValidatorTest.cs | 3 - .../SqlServerModelBuilderTestBase.cs | 2 - .../StoreGeneratedSentinelSqlServerTest.cs | 2 - 345 files changed, 10217 insertions(+), 9527 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e65be73b154..adcdae77f74 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -13,4 +13,4 @@ - + \ No newline at end of file diff --git a/src/EFCore.Abstractions/ChangeTracking/Internal/ObservableBackedBindingList.cs b/src/EFCore.Abstractions/ChangeTracking/Internal/ObservableBackedBindingList.cs index d7ea5c99571..148be762cac 100644 --- a/src/EFCore.Abstractions/ChangeTracking/Internal/ObservableBackedBindingList.cs +++ b/src/EFCore.Abstractions/ChangeTracking/Internal/ObservableBackedBindingList.cs @@ -14,8 +14,8 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal; /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [RequiresUnreferencedCode( - "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] -[RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] + "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code."), + RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] public class ObservableBackedBindingList<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T> : SortableBindingList { private bool _addingNewInstance; diff --git a/src/EFCore.Abstractions/ChangeTracking/Internal/SortableBindingList.cs b/src/EFCore.Abstractions/ChangeTracking/Internal/SortableBindingList.cs index 1af38c18074..1df4cc6908e 100644 --- a/src/EFCore.Abstractions/ChangeTracking/Internal/SortableBindingList.cs +++ b/src/EFCore.Abstractions/ChangeTracking/Internal/SortableBindingList.cs @@ -13,8 +13,8 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking.Internal; /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// -[RequiresUnreferencedCode("Raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] -[RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] +[RequiresUnreferencedCode("Raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code."), + RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] public class SortableBindingList<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T> : BindingList { private bool _isSorted; @@ -39,18 +39,16 @@ public SortableBindingList(List list) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - [RequiresUnreferencedCode("Requires accessing property 'Default' on the property descriptor's type")] - [RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] - [UnconditionalSuppressMessage( - "ReflectionAnalysis", - "IL2046", - Justification = - "This method is an override, and the base method isn't annotated with RequiresUnreferencedCode. " - + "The entire type is marked with RequiresUnreferencedCode.")] - [SuppressMessage( - "AOT", "IL3051:'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.", - Justification = "This method is an override, and the base method isn't annotated with RequiresDynamicCode. " - + "The entire type is marked with RequiresDynamicCode.")] + [RequiresUnreferencedCode("Requires accessing property 'Default' on the property descriptor's type"), + RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type"), UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2046", + Justification = + "This method is an override, and the base method isn't annotated with RequiresUnreferencedCode. " + + "The entire type is marked with RequiresUnreferencedCode."), SuppressMessage( + "AOT", "IL3051:'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.", + Justification = "This method is an override, and the base method isn't annotated with RequiresDynamicCode. " + + "The entire type is marked with RequiresDynamicCode.")] protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) { if (PropertyComparer.CanSort(prop.PropertyType)) @@ -117,8 +115,8 @@ private sealed class PropertyComparer : Comparer private readonly ListSortDirection _direction; private readonly PropertyDescriptor _prop; - [RequiresUnreferencedCode("Requires accessing property 'Default' on the property descriptor's type")] - [RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] + [RequiresUnreferencedCode("Requires accessing property 'Default' on the property descriptor's type"), + RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] public PropertyComparer(PropertyDescriptor prop, ListSortDirection direction) { if (!prop.ComponentType.IsAssignableFrom(typeof(T))) diff --git a/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs b/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs index 5b4ace5447f..029a97ab26e 100644 --- a/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs +++ b/src/EFCore.Abstractions/ChangeTracking/ObservableCollectionListSource.cs @@ -75,18 +75,16 @@ bool IListSource.ContainsListCollection /// An in sync with the ObservableCollection. /// [RequiresUnreferencedCode( - "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] - [RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] - [UnconditionalSuppressMessage( - "ReflectionAnalysis", - "IL2046", - Justification = - "This method is an interface implementation, and the interface method isn't annotated with RequiresUnreferencedCode. " - + "The entire type is marked with RequiresUnreferencedCode.")] - [SuppressMessage( - "AOT", "IL3051:'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.", - Justification = "This method is an override, and the base method isn't annotated with RequiresDynamicCode. " - + "The entire type is marked with RequiresDynamicCode.")] + "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code."), + RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type"), UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2046", + Justification = + "This method is an interface implementation, and the interface method isn't annotated with RequiresUnreferencedCode. " + + "The entire type is marked with RequiresUnreferencedCode."), SuppressMessage( + "AOT", "IL3051:'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.", + Justification = "This method is an override, and the base method isn't annotated with RequiresDynamicCode. " + + "The entire type is marked with RequiresDynamicCode.")] IList IListSource.GetList() => _bindingList ??= this.ToBindingList(); } diff --git a/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs b/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs index 9f59eccfb1d..9dde465b7b4 100644 --- a/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs +++ b/src/EFCore.Abstractions/EntityTypeConfigurationAttribute.cs @@ -19,7 +19,10 @@ public class EntityTypeConfigurationAttribute : Attribute /// Initializes a new instance of the class. /// /// The IEntityTypeConfiguration<> type to use. - public EntityTypeConfigurationAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.Interfaces)] Type entityConfigurationType) + public EntityTypeConfigurationAttribute( + [DynamicallyAccessedMembers( + DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.Interfaces)] + Type entityConfigurationType) { Check.NotNull(entityConfigurationType); diff --git a/src/EFCore.Abstractions/ObservableCollectionExtensions.cs b/src/EFCore.Abstractions/ObservableCollectionExtensions.cs index 211eb90c443..d40f5a39dc3 100644 --- a/src/EFCore.Abstractions/ObservableCollectionExtensions.cs +++ b/src/EFCore.Abstractions/ObservableCollectionExtensions.cs @@ -25,8 +25,8 @@ public static class ObservableCollectionExtensions /// The collection that the binding list will stay in sync with. /// The binding list. [RequiresUnreferencedCode( - "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code.")] - [RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] + "BindingList raises ListChanged events with PropertyDescriptors. PropertyDescriptors require unreferenced code."), + RequiresDynamicCode("Requires calling MakeGenericType on the property descriptor's type")] public static BindingList ToBindingList(this ObservableCollection source) where T : class => new ObservableBackedBindingList(source); diff --git a/src/EFCore.Analyzers/EFCore.Analyzers.nuspec b/src/EFCore.Analyzers/EFCore.Analyzers.nuspec index 17bf4bb98f2..0a1bd7e678d 100644 --- a/src/EFCore.Analyzers/EFCore.Analyzers.nuspec +++ b/src/EFCore.Analyzers/EFCore.Analyzers.nuspec @@ -1,4 +1,5 @@  + $CommonMetadataElements$ @@ -14,4 +15,4 @@ - + \ No newline at end of file diff --git a/src/EFCore.Analyzers/InternalUsageDiagnosticAnalyzer.cs b/src/EFCore.Analyzers/InternalUsageDiagnosticAnalyzer.cs index 2f6579ef1ef..b2b194f3834 100644 --- a/src/EFCore.Analyzers/InternalUsageDiagnosticAnalyzer.cs +++ b/src/EFCore.Analyzers/InternalUsageDiagnosticAnalyzer.cs @@ -23,7 +23,8 @@ private static readonly DiagnosticDescriptor Descriptor defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true); - public override ImmutableArray SupportedDiagnostics => [Descriptor]; + public override ImmutableArray SupportedDiagnostics + => [Descriptor]; public override void Initialize(AnalysisContext context) { @@ -308,14 +309,13 @@ private static bool IsInternal(OperationAnalysisContext context, ITypeSymbol sym && (IsInInternalNamespace(symbol) || HasInternalAttribute(symbol)); private static bool HasInternalAttribute(ISymbol symbol) - => symbol.GetAttributes().Any( - a => - a.AttributeClass!.ToDisplayString() - == "Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkInternalAttribute"); + => symbol.GetAttributes().Any(a => + a.AttributeClass!.ToDisplayString() + == "Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkInternalAttribute"); private static bool IsInInternalNamespace(ISymbol symbol) { - if (symbol?.ContainingNamespace?.ToDisplayString() is string ns) + if (symbol?.ContainingNamespace?.ToDisplayString() is { } ns) { var i = ns.IndexOf("EntityFrameworkCore", StringComparison.Ordinal); diff --git a/src/EFCore.Analyzers/InterpolatedStringUsageInRawQueriesCodeFixProvider.cs b/src/EFCore.Analyzers/InterpolatedStringUsageInRawQueriesCodeFixProvider.cs index adcd46f5371..e5b7da68834 100644 --- a/src/EFCore.Analyzers/InterpolatedStringUsageInRawQueriesCodeFixProvider.cs +++ b/src/EFCore.Analyzers/InterpolatedStringUsageInRawQueriesCodeFixProvider.cs @@ -11,11 +11,11 @@ namespace Microsoft.EntityFrameworkCore; -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(InterpolatedStringUsageInRawQueriesCodeFixProvider))] -[Shared] +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(InterpolatedStringUsageInRawQueriesCodeFixProvider)), Shared] public sealed class InterpolatedStringUsageInRawQueriesCodeFixProvider : CodeFixProvider { - public override ImmutableArray FixableDiagnosticIds => [EFDiagnostics.InterpolatedStringUsageInRawQueries]; + public override ImmutableArray FixableDiagnosticIds + => [EFDiagnostics.InterpolatedStringUsageInRawQueries]; public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; diff --git a/src/EFCore.Analyzers/InterpolatedStringUsageInRawQueriesDiagnosticAnalyzer.cs b/src/EFCore.Analyzers/InterpolatedStringUsageInRawQueriesDiagnosticAnalyzer.cs index 5d7f07b5523..e4a0ea8f28d 100644 --- a/src/EFCore.Analyzers/InterpolatedStringUsageInRawQueriesDiagnosticAnalyzer.cs +++ b/src/EFCore.Analyzers/InterpolatedStringUsageInRawQueriesDiagnosticAnalyzer.cs @@ -21,7 +21,8 @@ private static readonly DiagnosticDescriptor Descriptor defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true); - public override ImmutableArray SupportedDiagnostics => [Descriptor]; + public override ImmutableArray SupportedDiagnostics + => [Descriptor]; public override void Initialize(AnalysisContext context) { diff --git a/src/EFCore.Cosmos/ChangeTracking/Internal/StringDictionaryComparer.cs b/src/EFCore.Cosmos/ChangeTracking/Internal/StringDictionaryComparer.cs index 865f95f73ca..200c12c890b 100644 --- a/src/EFCore.Cosmos/ChangeTracking/Internal/StringDictionaryComparer.cs +++ b/src/EFCore.Cosmos/ChangeTracking/Internal/StringDictionaryComparer.cs @@ -15,7 +15,8 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.ChangeTracking.Internal; public sealed class StringDictionaryComparer : ValueComparer, IInfrastructure { private static readonly MethodInfo CompareMethod = typeof(StringDictionaryComparer).GetMethod( - nameof(Compare), BindingFlags.Static | BindingFlags.NonPublic, [typeof(object), typeof(object), typeof(Func)])!; + nameof(Compare), BindingFlags.Static | BindingFlags.NonPublic, + [typeof(object), typeof(object), typeof(Func)])!; private static readonly MethodInfo GetHashCodeMethod = typeof(StringDictionaryComparer).GetMethod( nameof(GetHashCode), BindingFlags.Static | BindingFlags.NonPublic, [typeof(IEnumerable), typeof(Func)])!; @@ -72,7 +73,7 @@ private static Expression> GetHashCodeLambda(ValueComparer ele Expression.Convert( prm, typeof(IEnumerable)), - elementComparer.HashCodeExpression), + elementComparer.HashCodeExpression), prm); } diff --git a/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs b/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs index bf458d70a81..94219fc57a9 100644 --- a/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs +++ b/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs @@ -205,19 +205,18 @@ private static string ExecutedReadNext(EventDefinitionBase definition, EventData { var d = (FallbackEventDefinition)definition; var p = (CosmosQueryExecutedEventData)payload; - return d.GenerateMessage( - l => l.Log( - d.Level, - d.EventId, - d.MessageFormat, - p.Elapsed.TotalMilliseconds, - p.RequestCharge, - p.ActivityId, - p.ContainerId, - p.LogSensitiveData ? p.PartitionKeyValue.ToString() : "?", - FormatParameters(p.Parameters, p is { LogSensitiveData: true, Parameters.Count: > 0 }), - Environment.NewLine, - p.QuerySql)); + return d.GenerateMessage(l => l.Log( + d.Level, + d.EventId, + d.MessageFormat, + p.Elapsed.TotalMilliseconds, + p.RequestCharge, + p.ActivityId, + p.ContainerId, + p.LogSensitiveData ? p.PartitionKeyValue.ToString() : "?", + FormatParameters(p.Parameters, p is { LogSensitiveData: true, Parameters.Count: > 0 }), + Environment.NewLine, + p.QuerySql)); } /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosDbFunctionsExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosDbFunctionsExtensions.cs index 88be60b6540..a9f144d61ad 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosDbFunctionsExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosDbFunctionsExtensions.cs @@ -109,7 +109,7 @@ public static double Rrf(this DbFunctions _, params double[] scores) /// The second vector. /// /// An optional boolean specifying how the computed value is used in an ORDER BY expression. - /// If , then brute force is used. A value of uses any index defined on the vector + /// If , then brute force is used. A value of uses any index defined on the vector /// property, if it exists. Default value is . /// /// An optional object used to specify options for the vector distance calculation. @@ -129,7 +129,7 @@ public static double VectorDistance( /// The second vector. /// /// An optional boolean specifying how the computed value is used in an ORDER BY expression. - /// If , then brute force is used. A value of uses any index defined on the vector + /// If , then brute force is used. A value of uses any index defined on the vector /// property, if it exists. Default value is . /// /// An optional object used to specify options for the vector distance calculation. @@ -149,7 +149,7 @@ public static double VectorDistance( /// The second vector. /// /// An optional boolean specifying how the computed value is used in an ORDER BY expression. - /// If , then brute force is used. A value of uses any index defined on the vector + /// If , then brute force is used. A value of uses any index defined on the vector /// property, if it exists. Default value is . /// /// An optional object used to specify options for the vector distance calculation. diff --git a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs index 3ea42adeda6..80d0452bc1a 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs @@ -1020,7 +1020,11 @@ public static bool CanSetThroughput( /// /// See Database triggers for more information and examples. /// - public static TriggerBuilder HasTrigger(this EntityTypeBuilder entityTypeBuilder, string modelName, TriggerType triggerType, TriggerOperation triggerOperation) + public static TriggerBuilder HasTrigger( + this EntityTypeBuilder entityTypeBuilder, + string modelName, + TriggerType triggerType, + TriggerOperation triggerOperation) { var triggerBuilder = EntityTypeBuilder.HasTrigger(entityTypeBuilder.Metadata, modelName); triggerBuilder.Metadata.SetTriggerType(triggerType); @@ -1039,7 +1043,11 @@ public static TriggerBuilder HasTrigger(this EntityTypeBuilder entityTypeBuilder /// /// See Database triggers for more information and examples. /// - public static TriggerBuilder HasTrigger(this EntityTypeBuilder entityTypeBuilder, string modelName, TriggerType triggerType, TriggerOperation triggerOperation) + public static TriggerBuilder HasTrigger( + this EntityTypeBuilder entityTypeBuilder, + string modelName, + TriggerType triggerType, + TriggerOperation triggerOperation) where TEntity : class { var triggerBuilder = EntityTypeBuilder.HasTrigger(entityTypeBuilder.Metadata, modelName); diff --git a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs index 02f86c605e1..8bd4c77e728 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs @@ -80,7 +80,7 @@ public static void SetContainer(this IMutableEntityType entityType, string? name } private static string? GetDefaultContainingPropertyName(IReadOnlyEntityType entityType) - => entityType.FindOwnership() is IReadOnlyForeignKey ownership + => entityType.FindOwnership() is { } ownership ? ownership.PrincipalToDependent!.Name : null; diff --git a/src/EFCore.Cosmos/Extensions/CosmosIndexBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosIndexBuilderExtensions.cs index 3edbb250a1a..44d93d11285 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosIndexBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosIndexBuilderExtensions.cs @@ -103,7 +103,8 @@ public static bool CanSetVectorIndexType( /// /// Configures the index as a full-text index. - /// See Full-text search in Azure Cosmos DB for NoSQL for more information. + /// See Full-text search in Azure Cosmos DB for NoSQL + /// for more information. /// /// /// See Modeling entity types and relationships, and @@ -121,7 +122,8 @@ public static IndexBuilder IsFullTextIndex(this IndexBuilder indexBuilder, bool /// /// Configures the index as a full-text index. - /// See Full-text search in Azure Cosmos DB for NoSQL for more information. + /// See Full-text search in Azure Cosmos DB for NoSQL + /// for more information. /// /// /// See Modeling entity types and relationships, and @@ -137,7 +139,8 @@ public static IndexBuilder IsFullTextIndex( /// /// Configures the index as a full-text index. - /// See Full-text search in Azure Cosmos DB for NoSQL for more information. + /// See Full-text search in Azure Cosmos DB for NoSQL + /// for more information. /// /// /// See Modeling entity types and relationships, and diff --git a/src/EFCore.Cosmos/Extensions/CosmosIndexExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosIndexExtensions.cs index 078262d9f69..184742b86a2 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosIndexExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosIndexExtensions.cs @@ -74,7 +74,8 @@ public static void SetVectorIndexType(this IMutableIndex index, VectorIndexType? /// /// Returns the value indicating whether the index is configured for full-text search. - /// See Full-text search in Azure Cosmos DB for NoSQL for more information. + /// See Full-text search in Azure Cosmos DB for NoSQL + /// for more information. /// /// The index. /// The index type to use, or if none is set. @@ -85,7 +86,8 @@ public static void SetVectorIndexType(this IMutableIndex index, VectorIndexType? /// /// Configures the index for full-text search. - /// See Full-text search in Azure Cosmos DB for NoSQL for more information. + /// See Full-text search in Azure Cosmos DB for NoSQL + /// for more information. /// /// The index. /// The value indicating whether the index is configured for full-text search. @@ -94,7 +96,8 @@ public static void SetIsFullTextIndex(this IMutableIndex index, bool? fullTextIn /// /// Configures the index for full-text search. - /// See Full-text search in Azure Cosmos DB for NoSQL for more information. + /// See Full-text search in Azure Cosmos DB for NoSQL + /// for more information. /// /// The index. /// The value indicating whether the index is configured for full-text search. diff --git a/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs index 8a3161e694f..ba3c2b815ee 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosPropertyBuilderExtensions.cs @@ -198,13 +198,13 @@ public static bool CanSetIsVectorProperty( int dimensions, bool fromDataAnnotation = false) => propertyBuilder.CanSetAnnotation( - CosmosAnnotationNames.VectorDistanceFunction, - ValidateVectorDistanceFunction(distanceFunction), - fromDataAnnotation) - && propertyBuilder.CanSetAnnotation( - CosmosAnnotationNames.VectorDimensions, - dimensions, - fromDataAnnotation); + CosmosAnnotationNames.VectorDistanceFunction, + ValidateVectorDistanceFunction(distanceFunction), + fromDataAnnotation) + && propertyBuilder.CanSetAnnotation( + CosmosAnnotationNames.VectorDimensions, + dimensions, + fromDataAnnotation); private static DistanceFunction ValidateVectorDistanceFunction(DistanceFunction distanceFunction) => Enum.IsDefined(distanceFunction) @@ -256,7 +256,10 @@ public static PropertyBuilder IsETagConcurrency( /// Accessing Azure Cosmos DB with EF Core for more information and examples. /// /// The builder for the property being configured. - /// The language used for full-text search. Setting this to ( will use the default language for the container, or "en-US" if default language was not specified. + /// + /// The language used for full-text search. Setting this to ( will use the default language for + /// the container, or "en-US" if default language was not specified. + /// /// The value indicating whether full-text search should be enabled for this property. /// The same builder instance so that multiple calls can be chained. public static PropertyBuilder EnableFullTextSearch( @@ -283,7 +286,10 @@ public static PropertyBuilder EnableFullTextSearch( /// /// The type of the property being configured. /// The builder for the property being configured. - /// The language used for full-text search. Setting this to ( will use the default language for the container, or "en-US" if default language was not specified. + /// + /// The language used for full-text search. Setting this to ( will use the default language for + /// the container, or "en-US" if default language was not specified. + /// /// The value indicating whether full-text search should be enabled for this property. /// The same builder instance so that multiple calls can be chained. public static PropertyBuilder EnableFullTextSearch( @@ -300,7 +306,10 @@ public static PropertyBuilder EnableFullTextSearch( /// Accessing Azure Cosmos DB with EF Core for more information and examples. /// /// The builder for the property being configured. - /// The language used for full-text search. Setting this to ( will use the default language for the container, or "en-US" if default language was not specified. + /// + /// The language used for full-text search. Setting this to ( will use the default language for + /// the container, or "en-US" if default language was not specified. + /// /// The value indicating whether full-text search should be enabled for this property. /// Indicates whether the configuration was specified using a data annotation. /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs index 6169e54ca44..cfff8a16aa9 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosServiceCollectionExtensions.cs @@ -63,12 +63,11 @@ public static IServiceCollection AddCosmos( Action? cosmosOptionsAction = null, Action? optionsAction = null) where TContext : DbContext - => serviceCollection.AddDbContext( - (serviceProvider, options) => - { - optionsAction?.Invoke(options); - options.UseCosmos(connectionString, databaseName, cosmosOptionsAction); - }); + => serviceCollection.AddDbContext((serviceProvider, options) => + { + optionsAction?.Invoke(options); + options.UseCosmos(connectionString, databaseName, cosmosOptionsAction); + }); /// /// @@ -113,17 +112,16 @@ public static IServiceCollection AddEntityFrameworkCosmos(this IServiceCollectio .TryAdd() .TryAdd() .TryAdd() - .TryAddProviderSpecificServices( - b => b - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddScoped() - .TryAddScoped() - .TryAddScoped() - .TryAddScoped()); + .TryAddProviderSpecificServices(b => b + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddScoped() + .TryAddScoped() + .TryAddScoped() + .TryAddScoped()); builder.TryAddCoreServices(); diff --git a/src/EFCore.Cosmos/Extensions/CosmosTriggerBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosTriggerBuilderExtensions.cs index e5743c73d0d..f2507ebe114 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosTriggerBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosTriggerBuilderExtensions.cs @@ -15,7 +15,6 @@ namespace Microsoft.EntityFrameworkCore; /// public static class CosmosTriggerBuilderExtensions { - /// /// Configures the Cosmos DB trigger type for this trigger. /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosTriggerExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosTriggerExtensions.cs index f7a7e314d2e..8eb4c5a810c 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosTriggerExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosTriggerExtensions.cs @@ -79,7 +79,8 @@ public static void SetTriggerOperation(this IMutableTrigger trigger, TriggerOper this IConventionTrigger trigger, TriggerOperation? triggerOperation, bool fromDataAnnotation = false) - => (TriggerOperation?)trigger.SetOrRemoveAnnotation(CosmosAnnotationNames.TriggerOperation, triggerOperation, fromDataAnnotation)?.Value; + => (TriggerOperation?)trigger.SetOrRemoveAnnotation(CosmosAnnotationNames.TriggerOperation, triggerOperation, fromDataAnnotation) + ?.Value; /// /// Gets the for the Cosmos DB trigger operation. diff --git a/src/EFCore.Cosmos/Extensions/Internal/CosmosShapedQueryExpressionExtensions.cs b/src/EFCore.Cosmos/Extensions/Internal/CosmosShapedQueryExpressionExtensions.cs index 586f11b0529..be295279ee4 100644 --- a/src/EFCore.Cosmos/Extensions/Internal/CosmosShapedQueryExpressionExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/Internal/CosmosShapedQueryExpressionExtensions.cs @@ -166,7 +166,7 @@ public static bool TryExtractArray( { projectedStructuralTypeShaper = shaper; projection = shaper.ValueBufferExpression; - if (projection is ProjectionBindingExpression { ProjectionMember: ProjectionMember projectionMember } + if (projection is ProjectionBindingExpression { ProjectionMember: { } projectionMember } && select.GetMappedProjection(projectionMember) is EntityProjectionExpression entityProjection) { projection = entityProjection.Object; @@ -261,7 +261,7 @@ private static bool TryGetProjection(ShapedQueryExpression shapedQueryExpression switch (shaperExpression) { - case ProjectionBindingExpression { ProjectionMember: ProjectionMember projectionMember } + case ProjectionBindingExpression { ProjectionMember: { } projectionMember } when shapedQueryExpression.QueryExpression is SelectExpression selectExpression: { projection = selectExpression.GetMappedProjection(projectionMember); diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosPartitionKeyInPrimaryKeyConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosPartitionKeyInPrimaryKeyConvention.cs index 67861f51a66..8662af0361c 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosPartitionKeyInPrimaryKeyConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosPartitionKeyInPrimaryKeyConvention.cs @@ -97,7 +97,7 @@ private static void ProcessJObjectProperty(IConventionEntityTypeBuilder entityTy var jObjectProperty = entityType.FindDeclaredProperty(JObjectPropertyName); if (jObjectProperty != null) { - entityType.Builder.RemoveUnusedImplicitProperties(new[] { jObjectProperty }); + entityType.Builder.RemoveUnusedImplicitProperties([jObjectProperty]); } } } diff --git a/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs b/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs index 6756b34abf2..160f4bdeb29 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs @@ -81,10 +81,9 @@ private static IServiceScope CreateServiceScope() { var serviceProvider = new ServiceCollection() .AddEntityFrameworkCosmos() - .AddDbContext( - (p, o) => - o.UseCosmos("localhost", "_", "_") - .UseInternalServiceProvider(p)) + .AddDbContext((p, o) => + o.UseCosmos("localhost", "_", "_") + .UseInternalServiceProvider(p)) .BuildServiceProvider(); return serviceProvider.GetRequiredService().CreateScope(); diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosAliasManager.cs b/src/EFCore.Cosmos/Query/Internal/CosmosAliasManager.cs index bb43035c4f0..6227029eae3 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosAliasManager.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosAliasManager.cs @@ -51,7 +51,7 @@ public virtual string GenerateSourceAlias(Expression expression, string? fallbac => GenerateSourceAlias( expression switch { - IAccessExpression { PropertyName: string propertyName } => propertyName, + IAccessExpression { PropertyName: { } propertyName } => propertyName, FromSqlExpression => "sql", SqlFunctionExpression { Name: "ARRAY_SLICE", Arguments: [var array, ..] } => GenerateSourceAlias(array), ObjectFunctionExpression { Name: "ARRAY_SLICE", Arguments: [var array, ..] } => GenerateSourceAlias(array), @@ -185,7 +185,7 @@ public virtual Expression PostprocessAliases(Expression expression) private sealed class SourceAliasCollector : ExpressionVisitor { - private readonly HashSet _sourceAliases = new(); + private readonly HashSet _sourceAliases = []; internal static HashSet Collect(Expression expression) { @@ -201,7 +201,7 @@ protected override Expression VisitExtension(Expression node) case ShapedQueryExpression shapedQuery: return shapedQuery.UpdateQueryExpression(Visit(shapedQuery.QueryExpression)); - case SourceExpression { Alias: string alias }: + case SourceExpression { Alias: { } alias }: _sourceAliases.Add(alias); return base.VisitExtension(node); @@ -221,7 +221,7 @@ protected override Expression VisitExtension(Expression node) { ShapedQueryExpression shapedQuery => shapedQuery.UpdateQueryExpression(Visit(shapedQuery.QueryExpression)), - SourceExpression { Alias: string alias } source when aliasRewritingMap.TryGetValue(alias, out var newAlias) + SourceExpression { Alias: { } alias } source when aliasRewritingMap.TryGetValue(alias, out var newAlias) => base.VisitExtension(new SourceExpression(source.Expression, newAlias, source.WithIn)), ScalarReferenceExpression reference when aliasRewritingMap.TryGetValue(reference.Name, out var newAlias) => new ScalarReferenceExpression(newAlias, reference.Type, reference.TypeMapping), diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs index 38ceb4f0942..72abbf75413 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosProjectionBindingExpressionVisitor.cs @@ -577,7 +577,7 @@ UnaryExpression unaryExpression && methodCallExpression.Arguments is [var argument] && argument.Type.TryGetElementType(typeof(IQueryable<>)) != null) { - if (_queryableMethodTranslatingExpressionVisitor.TranslateSubquery(argument) is not ShapedQueryExpression subquery + if (_queryableMethodTranslatingExpressionVisitor.TranslateSubquery(argument) is not { } subquery || !subquery.TryConvertToArray(_typeMappingSource, out var array)) { throw new InvalidOperationException(CoreStrings.TranslationFailed(methodCallExpression.Print())); diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryCompilationContext.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryCompilationContext.cs index 2673f87de42..bc804f1f869 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryCompilationContext.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryCompilationContext.cs @@ -29,7 +29,7 @@ public class CosmosQueryCompilationContext(QueryCompilationContextDependencies d /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual List PartitionKeyPropertyValues { get; internal set; } = new(); + public virtual List PartitionKeyPropertyValues { get; internal set; } = []; /// /// A manager for aliases, capable of generate uniquified source aliases. diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQuerySqlGenerator.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQuerySqlGenerator.cs index cf0c28cd552..53466ffa814 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQuerySqlGenerator.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQuerySqlGenerator.cs @@ -347,7 +347,9 @@ protected override Expression VisitSelect(SelectExpression selectExpression) _sqlBuilder.Append("RANK "); } - Check.DebugAssert(orderByScoringFunction || selectExpression.Orderings.All(x => x.Expression is not SqlFunctionExpression { IsScoringFunction: true }), + Check.DebugAssert( + orderByScoringFunction + || selectExpression.Orderings.All(x => x.Expression is not SqlFunctionExpression { IsScoringFunction: true }), "Scoring function can only appear as first (and only) ordering, or not at all."); GenerateList(selectExpression.Orderings, e => Visit(e)); diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs index 7083e6978ea..3f826412a13 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs @@ -206,10 +206,10 @@ when methodCallExpression.Arguments[0] is MethodCallExpression var returnDefault = method.Name == nameof(Queryable.ElementAtOrDefault); if (Visit(innerMethodCall) is ShapedQueryExpression translatedSelect && translatedSelect.TryExtractArray(out _, out _, out _, out var boundMember) - && boundMember is IAccessExpression { PropertyName: string boundPropertyName } + && boundMember is IAccessExpression { PropertyName: { } boundPropertyName } && Visit(innerMethodCall.Arguments[0]) is ShapedQueryExpression innerSource && TranslateElementAtOrDefault( - innerSource, methodCallExpression.Arguments[1], returnDefault) is ShapedQueryExpression elementAtTranslation) + innerSource, methodCallExpression.Arguments[1], returnDefault) is { } elementAtTranslation) { #pragma warning disable EF1001 // Internal EF Core API usage. var translation = _sqlTranslator.Translate( @@ -330,8 +330,8 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis selectExpression, _sqlExpressionFactory.In( (SqlExpression)discriminatorColumn, - concreteEntityTypes.Select( - et => _sqlExpressionFactory.Constant(et.GetDiscriminatorValue(), discriminatorColumn.Type)) + concreteEntityTypes.Select(et => _sqlExpressionFactory.Constant( + et.GetDiscriminatorValue(), discriminatorColumn.Type)) .ToArray())); Check.DebugAssert(success, "Couldn't apply predicate when creating a new ShapedQueryExpression"); } @@ -412,7 +412,7 @@ private ShapedQueryExpression CreateShapedQueryExpression(SelectExpression selec { var simplifiedTranslation = _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( - "ARRAY_LENGTH", new[] { array }, typeof(int), _typeMappingSource.FindMapping(typeof(int))), + "ARRAY_LENGTH", [array], typeof(int), _typeMappingSource.FindMapping(typeof(int))), _sqlExpressionFactory.Constant(0)); var select = new SelectExpression(simplifiedTranslation); @@ -476,7 +476,7 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou // Simplify x.Array.Contains[1] => ARRAY_CONTAINS(x.Array, 1) insert of IN+subquery if (source.TryExtractArray(out var array, ignoreOrderings: true) && array is SqlExpression scalarArray // TODO: Contains over arrays of structural types, #34027 - && TranslateExpression(item) is SqlExpression translatedItem) + && TranslateExpression(item) is { } translatedItem) { if (array is ArrayConstantExpression arrayConstant) { @@ -548,7 +548,7 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou Expression index, bool returnDefault) { - if (TranslateExpression(index) is not SqlExpression translatedIndex) + if (TranslateExpression(index) is not { } translatedIndex) { return null; } @@ -669,7 +669,7 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou { if (predicate != null) { - if (TranslateWhere(source, predicate) is not ShapedQueryExpression translatedSource) + if (TranslateWhere(source, predicate) is not { } translatedSource) { return null; } @@ -769,7 +769,7 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou { if (predicate != null) { - if (TranslateWhere(source, predicate) is not ShapedQueryExpression translatedSource) + if (TranslateWhere(source, predicate) is not { } translatedSource) { return null; } @@ -925,7 +925,7 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou return null; } - if (TranslateLambdaExpression(source, keySelector) is SqlExpression translation) + if (TranslateLambdaExpression(source, keySelector) is { } translation) { ((SelectExpression)source.QueryExpression).ApplyOrdering(new OrderingExpression(translation, ascending)); @@ -1052,7 +1052,7 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s { if (predicate != null) { - if (TranslateWhere(source, predicate) is not ShapedQueryExpression translatedSource) + if (TranslateWhere(source, predicate) is not { } translatedSource) { return null; } @@ -1087,7 +1087,7 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s /// protected override ShapedQueryExpression? TranslateSkip(ShapedQueryExpression source, Expression count) { - if (TranslateExpression(count) is not SqlExpression translatedCount) + if (TranslateExpression(count) is not { } translatedCount) { return null; } @@ -1200,7 +1200,7 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s var serverOutputType = resultType.UnwrapNullableType(); var projection = (SqlExpression)selectExpression.GetMappedProjection(new ProjectionMember()); - projection = _sqlExpressionFactory.Function("SUM", new[] { projection }, serverOutputType, projection.TypeMapping); + projection = _sqlExpressionFactory.Function("SUM", [projection], serverOutputType, projection.TypeMapping); return AggregateResultShaper(source, projection, resultType); } @@ -1213,7 +1213,7 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s /// protected override ShapedQueryExpression? TranslateTake(ShapedQueryExpression source, Expression count) { - if (TranslateExpression(count) is not SqlExpression translatedCount) + if (TranslateExpression(count) is not { } translatedCount) { return null; } @@ -1323,7 +1323,7 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s /// protected override ShapedQueryExpression? TranslateThenBy(ShapedQueryExpression source, LambdaExpression keySelector, bool ascending) { - if (TranslateLambdaExpression(source, keySelector) is SqlExpression translation) + if (TranslateLambdaExpression(source, keySelector) is { } translation) { ((SelectExpression)source.QueryExpression).AppendOrdering(new OrderingExpression(translation, ascending)); @@ -1426,7 +1426,7 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s for (var i = 0; i < values.Count; i++) { - if (TranslateExpression(values[i]) is not SqlExpression translatedItem) + if (TranslateExpression(values[i]) is not { } translatedItem) { return null; } @@ -1476,7 +1476,11 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s #endregion Queryable collection support - private ShapedQueryExpression? TranslateAggregate(ShapedQueryExpression source, LambdaExpression? selector, Type resultType, string functionName) + private ShapedQueryExpression? TranslateAggregate( + ShapedQueryExpression source, + LambdaExpression? selector, + Type resultType, + string functionName) { var selectExpression = (SelectExpression)source.QueryExpression; if (selectExpression.IsDistinct @@ -1515,7 +1519,7 @@ private bool TryApplyPredicate(ShapedQueryExpression source, LambdaExpression pr return false; } - if (TranslateLambdaExpression(source, predicate) is SqlExpression translation) + if (TranslateLambdaExpression(source, predicate) is { } translation) { if (translation is not SqlConstantExpression { Value: true }) { @@ -1582,7 +1586,7 @@ private bool TryPushdownIntoSubquery(SelectExpression select) if (predicate is null && source.TryExtractArray(out var array, ignoreOrderings: true)) { var simplifiedTranslation = _sqlExpressionFactory.Function( - "ARRAY_LENGTH", new[] { array }, typeof(int), _typeMappingSource.FindMapping(typeof(int))); + "ARRAY_LENGTH", [array], typeof(int), _typeMappingSource.FindMapping(typeof(int))); var select = new SelectExpression(simplifiedTranslation); return source.Update(select, new ProjectionBindingExpression(select, new ProjectionMember(), typeof(int))); @@ -1600,7 +1604,7 @@ private bool TryPushdownIntoSubquery(SelectExpression select) if (predicate != null) { - if (TranslateWhere(source, predicate) is not ShapedQueryExpression translatedSource) + if (TranslateWhere(source, predicate) is not { } translatedSource) { return null; } @@ -1609,7 +1613,7 @@ private bool TryPushdownIntoSubquery(SelectExpression select) } var translation = _sqlExpressionFactory.ApplyDefaultTypeMapping( - _sqlExpressionFactory.Function("COUNT", new[] { _sqlExpressionFactory.Constant(1) }, typeof(int))); + _sqlExpressionFactory.Function("COUNT", [_sqlExpressionFactory.Constant(1)], typeof(int))); var projectionMapping = new Dictionary { { new ProjectionMember(), translation } }; @@ -1714,7 +1718,7 @@ private ShapedQueryExpression TranslateTwoParameterSelector(ShapedQueryExpressio var replacement2 = AccessField(transparentIdentifierType, transparentIdentifierParameter, "Inner"); var newResultSelector = Expression.Lambda( new ReplacingExpressionVisitor( - new[] { original1, original2 }, new[] { replacement1, replacement2 }) + [original1, original2], [replacement1, replacement2]) .Visit(resultSelector.Body), transparentIdentifierParameter); diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosReadItemAndPartitionKeysExtractor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosReadItemAndPartitionKeysExtractor.cs index a0311a5c457..43225c4823f 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosReadItemAndPartitionKeysExtractor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosReadItemAndPartitionKeysExtractor.cs @@ -46,7 +46,7 @@ public virtual Expression ExtractPartitionKeysAndId( QueryExpression: SelectExpression { Sources: [{ Expression: ObjectReferenceExpression } rootSource, ..], - Predicate: SqlExpression predicate + Predicate: { } predicate } select } shapedQuery) { @@ -98,7 +98,7 @@ public virtual Expression ExtractPartitionKeysAndId( var liftPartitionKeys = queryCompilationContext.PartitionKeyPropertyValues.Count == 0; foreach (var property in partitionKeyProperties) { - if (liftPartitionKeys && _partitionKeyPropertyValues[property].ValueExpression is Expression valueExpression) + if (liftPartitionKeys && _partitionKeyPropertyValues[property].ValueExpression is { } valueExpression) { queryCompilationContext.PartitionKeyPropertyValues.Add(valueExpression); } diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs index 6e434aee428..de333edebc8 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs @@ -797,7 +797,7 @@ var body else { replaceExpression = isNonNullableScalar - ? Expression.Convert( + ? Convert( Default(originalBodyType), type) : Default(type); @@ -820,7 +820,8 @@ var body jTokenExpression, (isNonNullableScalar ? typeMapping?.ClrType - : typeMapping?.ClrType.MakeNullable()) ?? type); + : typeMapping?.ClrType.MakeNullable()) + ?? type); if (valueExpression.Type != type) { diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ParameterInliner.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ParameterInliner.cs index 723c8206a38..0c588614ea6 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ParameterInliner.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.ParameterInliner.cs @@ -27,13 +27,13 @@ protected override Expression VisitExtension(Expression expression) switch (inExpression) { - case { Values: IReadOnlyList values2 }: + case { Values: { } values2 }: values = values2; break; // TODO: IN with subquery (return immediately, nothing to do here) - case { ValuesParameter: SqlParameterExpression valuesParameter }: + case { ValuesParameter: { } valuesParameter }: { var typeMapping = valuesParameter.TypeMapping; var mutableValues = new List(); @@ -57,7 +57,11 @@ protected override Expression VisitExtension(Expression expression) // Converts Offset and Limit parameters to constants when ORDER BY RANK is detected in the SelectExpression (i.e. we order by scoring function) // Cosmos only supports constants in Offset and Limit for this scenario currently (ORDER BY RANK limitation) - case SelectExpression { Orderings: [{ Expression: SqlFunctionExpression { IsScoringFunction: true } }], Limit: var limit, Offset: var offset } hybridSearch + case SelectExpression + { + Orderings: [{ Expression: SqlFunctionExpression { IsScoringFunction: true } }], Limit: var limit, + Offset: var offset + } hybridSearch when limit is SqlParameterExpression || offset is SqlParameterExpression: { if (hybridSearch.Limit is SqlParameterExpression limitPrm) @@ -79,15 +83,19 @@ protected override Expression VisitExtension(Expression expression) return base.VisitExtension(expression); } - // Inlines array parameter of full-text functions, transforming FullTextContainsAll(x, @keywordsArray) to FullTextContainsAll(x, keyword1, keyword2)) + // Inlines array parameter of full-text functions, transforming FullTextContainsAll(x, @keywordsArray) to FullTextContainsAll(x, keyword1, keyword2)) // we do this for FullTextContainsAll, FullTextContainsAny and FullTextScore case SqlFunctionExpression - { - Name: string name, - IsScoringFunction: bool scoringFunction, - Arguments: [var property, SqlParameterExpression { TypeMapping: { ElementTypeMapping: var elementTypeMapping }, Type: Type type } keywords] - } fullTextContainsAllAnyFunction - when (name is "FullTextContainsAny" or "FullTextContainsAll" or "FullTextScore") && type == typeof(string[]): + { + Name: { } name, + IsScoringFunction: var scoringFunction, + Arguments: + [ + var property, + SqlParameterExpression { TypeMapping: { ElementTypeMapping: var elementTypeMapping }, Type: { } type } keywords + ] + } fullTextContainsAllAnyFunction + when (name is "FullTextContainsAny" or "FullTextContainsAll" or "FullTextScore") && type == typeof(string[]): { var keywordValues = new List(); foreach (var value in (IEnumerable)parametersValues[keywords.Name]) diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs index 224dbf03151..f79539eb0b7 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.cs @@ -33,7 +33,7 @@ public partial class CosmosShapedQueryCompilingExpressionVisitor( /// protected override Expression VisitShapedQuery(ShapedQueryExpression shapedQueryExpression) { - if (cosmosQueryCompilationContext.RootEntityType is not IEntityType rootEntityType) + if (cosmosQueryCompilationContext.RootEntityType is not { } rootEntityType) { throw new UnreachableException("No root entity type was set during query processing."); } @@ -88,7 +88,7 @@ protected override Expression VisitShapedQuery(ShapedQueryExpression shapedQuery return selectExpression switch { - { ReadItemInfo: ReadItemInfo readItemInfo } => New( + { ReadItemInfo: { } readItemInfo } => New( typeof(ReadItemQueryingEnumerable<>).MakeGenericType(shaperLambda.ReturnType).GetConstructors()[0], cosmosQueryContextConstant, rootEntityTypeConstant, diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs index 18583a1d262..f963e03ee06 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs @@ -418,7 +418,7 @@ protected override Expression VisitExtension(Expression extensionExpression) var subquery = (SelectExpression)shapedQuery.QueryExpression; - var projection = mappedProjectionBindingExpression.ProjectionMember is ProjectionMember projectionMember + var projection = mappedProjectionBindingExpression.ProjectionMember is { } projectionMember ? subquery.GetMappedProjection(projectionMember) : throw new NotImplementedException("Subquery with index projection binding"); if (projection is not SqlExpression sqlExpression) @@ -768,7 +768,7 @@ protected override Expression VisitNewArray(NewArrayExpression newArrayExpressio for (var i = 0; i < expressions.Count; i++) { - if (Translate(expressions[i]) is not SqlExpression translatedItem) + if (Translate(expressions[i]) is not { } translatedItem) { return QueryCompilationContext.NotTranslatedExpression; } @@ -907,17 +907,17 @@ public virtual bool TryBindMember( switch (typeReference) { - case { Parameter: StructuralTypeShaperExpression shaper }: + case { Parameter: { } shaper }: var valueBufferExpression = Visit(shaper.ValueBufferExpression); var entityProjection = (EntityProjectionExpression)valueBufferExpression; expression = member switch { - { MemberInfo: MemberInfo memberInfo } + { MemberInfo: { } memberInfo } => entityProjection.BindMember( memberInfo, typeReference.Type, clientEval: false, out property), - { Name: string name } + { Name: { } name } => entityProjection.BindMember( name, typeReference.Type, clientEval: false, out property), @@ -926,7 +926,7 @@ public virtual bool TryBindMember( break; - case { Subquery: ShapedQueryExpression }: + case { Subquery: not null }: throw new NotImplementedException("Bind property on structural type coming out of scalar subquery"); default: @@ -1094,11 +1094,10 @@ private bool TryRewriteEntityEquality( } result = Visit( - primaryKeyProperties1.Select( - p => - Expression.MakeBinary( - nodeType, CreatePropertyAccessExpression(nonNullEntityReference, p), - Expression.Constant(null, p.ClrType.MakeNullable()))) + primaryKeyProperties1.Select(p => + Expression.MakeBinary( + nodeType, CreatePropertyAccessExpression(nonNullEntityReference, p), + Expression.Constant(null, p.ClrType.MakeNullable()))) .Aggregate((l, r) => nodeType == ExpressionType.Equal ? Expression.OrElse(l, r) : Expression.AndAlso(l, r))); return true; @@ -1132,16 +1131,14 @@ private bool TryRewriteEntityEquality( } result = Visit( - primaryKeyProperties.Select( - p => - Expression.MakeBinary( - nodeType, - CreatePropertyAccessExpression(left, p), - CreatePropertyAccessExpression(right, p))) - .Aggregate( - (l, r) => nodeType == ExpressionType.Equal - ? Expression.AndAlso(l, r) - : Expression.OrElse(l, r))); + primaryKeyProperties.Select(p => + Expression.MakeBinary( + nodeType, + CreatePropertyAccessExpression(left, p), + CreatePropertyAccessExpression(right, p))) + .Aggregate((l, r) => nodeType == ExpressionType.Equal + ? Expression.AndAlso(l, r) + : Expression.OrElse(l, r))); return true; } @@ -1168,8 +1165,8 @@ private Expression CreatePropertyAccessExpression(Expression target, IProperty p return queryCompilationContext.RegisterRuntimeParameter(newParameterName, lambda); case MemberInitExpression memberInitExpression - when memberInitExpression.Bindings.SingleOrDefault( - mb => mb.Member.Name == property.Name) is MemberAssignment memberAssignment: + when memberInitExpression.Bindings.SingleOrDefault(mb => mb.Member.Name == property.Name) is MemberAssignment + memberAssignment: return memberAssignment.Expression; default: @@ -1283,8 +1280,8 @@ public Expression Convert(Type type) return this; } - return EntityType is IEntityType entityType - && entityType.GetDerivedTypes().FirstOrDefault(et => et.ClrType == type) is IEntityType derivedEntityType + return EntityType is { } entityType + && entityType.GetDerivedTypes().FirstOrDefault(et => et.ClrType == type) is { } derivedEntityType ? new EntityReferenceExpression(this, derivedEntityType) : QueryCompilationContext.NotTranslatedExpression; } diff --git a/src/EFCore.Cosmos/Query/Internal/Expressions/FragmentExpression.cs b/src/EFCore.Cosmos/Query/Internal/Expressions/FragmentExpression.cs index 3efd431ca2f..3770033be34 100644 --- a/src/EFCore.Cosmos/Query/Internal/Expressions/FragmentExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/Expressions/FragmentExpression.cs @@ -1,9 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - - // ReSharper disable once CheckNamespace + namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal; /// diff --git a/src/EFCore.Cosmos/Query/Internal/Expressions/PagingExpression.cs b/src/EFCore.Cosmos/Query/Internal/Expressions/PagingExpression.cs index 5c929e6461f..0f7ba437e26 100644 --- a/src/EFCore.Cosmos/Query/Internal/Expressions/PagingExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/Expressions/PagingExpression.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // ReSharper disable once CheckNamespace + namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal; /// diff --git a/src/EFCore.Cosmos/Query/Internal/Expressions/SelectExpression.cs b/src/EFCore.Cosmos/Query/Internal/Expressions/SelectExpression.cs index 6b11c765be5..622f4a8c72f 100644 --- a/src/EFCore.Cosmos/Query/Internal/Expressions/SelectExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/Expressions/SelectExpression.cs @@ -21,7 +21,7 @@ public sealed class SelectExpression : Expression, IPrintableExpression private readonly List _projection = []; private readonly List _orderings = []; - private readonly List<(Expression ValueExpression, IProperty Property)> _partitionKeyValues = new(); + private readonly List<(Expression ValueExpression, IProperty Property)> _partitionKeyValues = []; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -407,8 +407,8 @@ public void AppendOrdering(OrderingExpression orderingExpression) { throw new InvalidOperationException( appendingScoringFunctionOrdering && existingScoringFunctionOrdering - ? CosmosStrings.OrderByMultipleScoringFunctionWithoutRrf(nameof(CosmosDbFunctionsExtensions.Rrf)) - : CosmosStrings.OrderByScoringFunctionMixedWithRegularOrderby); + ? CosmosStrings.OrderByMultipleScoringFunctionWithoutRrf(nameof(CosmosDbFunctionsExtensions.Rrf)) + : CosmosStrings.OrderByScoringFunctionMixedWithRegularOrderby); } } @@ -535,7 +535,7 @@ public Expression AddJoin(ShapedQueryExpression inner, Expression outerShaper, C return New( transparentIdentifierType.GetTypeInfo().DeclaredConstructors.Single(), - new[] { outerShaper, innerShaper }, outerMemberInfo, innerMemberInfo); + [outerShaper, innerShaper], outerMemberInfo, innerMemberInfo); } /// diff --git a/src/EFCore.Cosmos/Query/Internal/ISqlExpressionFactory.cs b/src/EFCore.Cosmos/Query/Internal/ISqlExpressionFactory.cs index f462c37ff0f..8763c2ba674 100644 --- a/src/EFCore.Cosmos/Query/Internal/ISqlExpressionFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/ISqlExpressionFactory.cs @@ -249,7 +249,11 @@ public interface ISqlExpressionFactory /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - SqlExpression ScoringFunction(string functionName, IEnumerable arguments, Type returnType, CoreTypeMapping? typeMapping = null); + SqlExpression ScoringFunction( + string functionName, + IEnumerable arguments, + Type returnType, + CoreTypeMapping? typeMapping = null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs b/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs index 52e5dcdcae3..951ab06cf82 100644 --- a/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs +++ b/src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs @@ -198,11 +198,11 @@ private InExpression ApplyTypeMappingOnIn(InExpression inExpression) CoreTypeMapping? valuesTypeMapping = null; switch (inExpression) { - case { ValuesParameter: SqlParameterExpression parameter }: + case { ValuesParameter: { } parameter }: valuesTypeMapping = parameter.TypeMapping; break; - case { Values: IReadOnlyList values }: + case { Values: { } values }: // Note: there could be conflicting type mappings inside the values; we take the first. foreach (var value in values) { @@ -228,11 +228,11 @@ private InExpression ApplyTypeMappingOnIn(InExpression inExpression) switch (inExpression) { - case { ValuesParameter: SqlParameterExpression parameter }: + case { ValuesParameter: { } parameter }: inExpression = inExpression.Update(item, (SqlParameterExpression)ApplyTypeMapping(parameter, item.TypeMapping)); break; - case { Values: IReadOnlyList values }: + case { Values: { } values }: SqlExpression[]? newValues = null; if (missingTypeMappingInValues) diff --git a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs index b1edf94d67f..c4b511c0998 100644 --- a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs @@ -39,23 +39,24 @@ public class CosmosFullTextSearchTranslator(ISqlExpressionFactory sqlExpressionF typeMappingSource.FindMapping(typeof(bool))), nameof(CosmosDbFunctionsExtensions.FullTextScore) - when arguments is [_, SqlExpression property, SqlConstantExpression { Type: var keywordClrType, Value: string[] values } keywords] - && keywordClrType == typeof(string[]) => sqlExpressionFactory.ScoringFunction( - "FullTextScore", - [property, .. values.Select(x => sqlExpressionFactory.Constant(x))], - typeof(double), - typeMappingSource.FindMapping(typeof(double))), + when arguments is + [_, { } property, SqlConstantExpression { Type: var keywordClrType, Value: string[] values } keywords] + && keywordClrType == typeof(string[]) => sqlExpressionFactory.ScoringFunction( + "FullTextScore", + [property, .. values.Select(x => sqlExpressionFactory.Constant(x))], + typeof(double), + typeMappingSource.FindMapping(typeof(double))), nameof(CosmosDbFunctionsExtensions.FullTextScore) - when arguments is [_, SqlExpression property, SqlParameterExpression { Type: var keywordClrType } keywords] - && keywordClrType == typeof(string[]) => sqlExpressionFactory.ScoringFunction( - "FullTextScore", - [property, keywords], - typeof(double), - typeMappingSource.FindMapping(typeof(double))), + when arguments is [_, { } property, SqlParameterExpression { Type: var keywordClrType } keywords] + && keywordClrType == typeof(string[]) => sqlExpressionFactory.ScoringFunction( + "FullTextScore", + [property, keywords], + typeof(double), + typeMappingSource.FindMapping(typeof(double))), nameof(CosmosDbFunctionsExtensions.FullTextScore) - when arguments is [_, SqlExpression property, ArrayConstantExpression keywords] => sqlExpressionFactory.ScoringFunction( + when arguments is [_, { } property, ArrayConstantExpression keywords] => sqlExpressionFactory.ScoringFunction( "FullTextScore", [property, .. keywords.Items], typeof(double), @@ -69,23 +70,24 @@ public class CosmosFullTextSearchTranslator(ISqlExpressionFactory sqlExpressionF typeMappingSource.FindMapping(typeof(double))), nameof(CosmosDbFunctionsExtensions.FullTextContainsAny) or nameof(CosmosDbFunctionsExtensions.FullTextContainsAll) - when arguments is [_, SqlExpression property, SqlConstantExpression { Type: var keywordClrType, Value: string[] values } keywords] - && keywordClrType == typeof(string[]) => sqlExpressionFactory.Function( - method.Name == nameof(CosmosDbFunctionsExtensions.FullTextContainsAny) ? "FullTextContainsAny" : "FullTextContainsAll", - [property, .. values.Select(x => sqlExpressionFactory.Constant(x))], - typeof(bool), - typeMappingSource.FindMapping(typeof(bool))), + when arguments is + [_, { } property, SqlConstantExpression { Type: var keywordClrType, Value: string[] values }] + && keywordClrType == typeof(string[]) => sqlExpressionFactory.Function( + method.Name == nameof(CosmosDbFunctionsExtensions.FullTextContainsAny) ? "FullTextContainsAny" : "FullTextContainsAll", + [property, .. values.Select(x => sqlExpressionFactory.Constant(x))], + typeof(bool), + typeMappingSource.FindMapping(typeof(bool))), nameof(CosmosDbFunctionsExtensions.FullTextContainsAny) or nameof(CosmosDbFunctionsExtensions.FullTextContainsAll) - when arguments is [_, SqlExpression property, SqlParameterExpression { Type: var keywordClrType } keywords] - && keywordClrType == typeof(string[]) => sqlExpressionFactory.Function( - method.Name == nameof(CosmosDbFunctionsExtensions.FullTextContainsAny) ? "FullTextContainsAny" : "FullTextContainsAll", - [property, keywords], - typeof(bool), - typeMappingSource.FindMapping(typeof(bool))), + when arguments is [_, { } property, SqlParameterExpression { Type: var keywordClrType } keywords] + && keywordClrType == typeof(string[]) => sqlExpressionFactory.Function( + method.Name == nameof(CosmosDbFunctionsExtensions.FullTextContainsAny) ? "FullTextContainsAny" : "FullTextContainsAll", + [property, keywords], + typeof(bool), + typeMappingSource.FindMapping(typeof(bool))), nameof(CosmosDbFunctionsExtensions.FullTextContainsAny) or nameof(CosmosDbFunctionsExtensions.FullTextContainsAll) - when arguments is [_, SqlExpression property, ArrayConstantExpression keywords] => sqlExpressionFactory.Function( + when arguments is [_, { } property, ArrayConstantExpression keywords] => sqlExpressionFactory.Function( method.Name == nameof(CosmosDbFunctionsExtensions.FullTextContainsAny) ? "FullTextContainsAny" : "FullTextContainsAll", [property, .. keywords.Items], typeof(bool), diff --git a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosRandomTranslator.cs b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosRandomTranslator.cs index 5269e7d3ba5..eaa785c1534 100644 --- a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosRandomTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosRandomTranslator.cs @@ -30,7 +30,7 @@ public class CosmosRandomTranslator(ISqlExpressionFactory sqlExpressionFactory) => MethodInfo.Equals(method) ? sqlExpressionFactory.Function( "RAND", - Enumerable.Empty(), + [], method.ReturnType) : null; } diff --git a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosRegexTranslator.cs b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosRegexTranslator.cs index 6177d4dcd5c..7b11562abb3 100644 --- a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosRegexTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosRegexTranslator.cs @@ -46,7 +46,7 @@ public class CosmosRegexTranslator(ISqlExpressionFactory sqlExpressionFactory) if (method == IsMatch || arguments[2] is SqlConstantExpression { Value: RegexOptions.None }) { - return sqlExpressionFactory.Function("RegexMatch", new[] { input, pattern }, typeof(bool)); + return sqlExpressionFactory.Function("RegexMatch", [input, pattern], typeof(bool)); } if (arguments[2] is SqlConstantExpression { Value: RegexOptions regexOptions }) @@ -80,7 +80,7 @@ public class CosmosRegexTranslator(ISqlExpressionFactory sqlExpressionFactory) return regexOptions == 0 ? sqlExpressionFactory.Function( "RegexMatch", - new[] { input, pattern, sqlExpressionFactory.Constant(modifier) }, + [input, pattern, sqlExpressionFactory.Constant(modifier)], typeof(bool)) : null; // TODO: Report unsupported RegexOption, #26410 } diff --git a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosStringMemberTranslator.cs b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosStringMemberTranslator.cs index ab59359ce7b..b915b571203 100644 --- a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosStringMemberTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosStringMemberTranslator.cs @@ -30,7 +30,7 @@ public class CosmosStringMemberTranslator(ISqlExpressionFactory sqlExpressionFac { return sqlExpressionFactory.Function( "LENGTH", - new[] { instance! }, + [instance!], returnType); } diff --git a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosStringMethodTranslator.cs b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosStringMethodTranslator.cs index a9d0b80b5f8..2cbd2b84231 100644 --- a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosStringMethodTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosStringMethodTranslator.cs @@ -92,14 +92,12 @@ private static readonly MethodInfo SubstringMethodInfoWithTwoArgs = typeof(string).GetRuntimeMethod(nameof(string.Substring), [typeof(int), typeof(int)])!; private static readonly MethodInfo FirstOrDefaultMethodInfoWithoutArgs - = typeof(Enumerable).GetRuntimeMethods().Single( - m => m.Name == nameof(Enumerable.FirstOrDefault) - && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); + = typeof(Enumerable).GetRuntimeMethods().Single(m => m.Name == nameof(Enumerable.FirstOrDefault) + && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); private static readonly MethodInfo LastOrDefaultMethodInfoWithoutArgs - = typeof(Enumerable).GetRuntimeMethods().Single( - m => m.Name == nameof(Enumerable.LastOrDefault) - && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); + = typeof(Enumerable).GetRuntimeMethods().Single(m => m.Name == nameof(Enumerable.LastOrDefault) + && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); private static readonly MethodInfo StringConcatWithTwoArguments = typeof(string).GetRuntimeMethod(nameof(string.Concat), [typeof(string), typeof(string)])!; diff --git a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosTypeCheckingTranslator.cs b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosTypeCheckingTranslator.cs index f53efbee3d2..b5aaea6ec19 100644 --- a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosTypeCheckingTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosTypeCheckingTranslator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // ReSharper disable once CheckNamespace + namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal; /// diff --git a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosVectorSearchTranslator.cs b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosVectorSearchTranslator.cs index 47fd91fd15a..e942bee082d 100644 --- a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosVectorSearchTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosVectorSearchTranslator.cs @@ -58,14 +58,12 @@ public class CosmosVectorSearchTranslator(ISqlExpressionFactory sqlExpressionFac ?? vector2.TypeMapping as CosmosVectorTypeMapping ?? throw new InvalidOperationException(CosmosStrings.VectorSearchRequiresVector); - var vectorType = vectorMapping.VectorType; - List newArguments = new() - { - sqlExpressionFactory.ApplyTypeMapping(vector1, vectorMapping), - sqlExpressionFactory.ApplyTypeMapping(vector2, vectorMapping), - }; + List newArguments = + [ + sqlExpressionFactory.ApplyTypeMapping(vector1, vectorMapping), sqlExpressionFactory.ApplyTypeMapping(vector2, vectorMapping) + ]; if (useBruteForceValue is not null) { @@ -85,7 +83,7 @@ public class CosmosVectorSearchTranslator(ISqlExpressionFactory sqlExpressionFac var requireComma = false; - if (options.DistanceFunction is DistanceFunction distanceFunction) + if (options.DistanceFunction is { } distanceFunction) { optionsBuilder .Append("'distanceFunction': '") diff --git a/src/EFCore.Cosmos/Query/VectorDistanceOptions.cs b/src/EFCore.Cosmos/Query/VectorDistanceOptions.cs index 60baf1d0a2c..0417385c115 100644 --- a/src/EFCore.Cosmos/Query/VectorDistanceOptions.cs +++ b/src/EFCore.Cosmos/Query/VectorDistanceOptions.cs @@ -2,10 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // ReSharper disable once CheckNamespace + namespace Microsoft.EntityFrameworkCore; /// -/// Options to be passed to +/// Options to be passed to +/// /// public sealed class VectorDistanceOptions { diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs index e9dd8ed71a0..439fff3f856 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs @@ -6,10 +6,10 @@ using System.Net; using System.Runtime.CompilerServices; using System.Text; +using Microsoft.Azure.Cosmos.Scripts; using Microsoft.EntityFrameworkCore.Cosmos.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.Cosmos.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.Cosmos.Internal; -using Microsoft.Azure.Cosmos.Scripts; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; using Microsoft.EntityFrameworkCore.Internal; using Newtonsoft.Json; @@ -322,19 +322,14 @@ private static async Task CreateContainerIfNotExistsOnceAsync( if (vectorIndexes.Count != 0 || fullTextIndexPaths.Count != 0) { - containerProperties.IndexingPolicy = new IndexingPolicy - { - VectorIndexes = vectorIndexes, - FullTextIndexes = fullTextIndexPaths - }; + containerProperties.IndexingPolicy = new IndexingPolicy { VectorIndexes = vectorIndexes, FullTextIndexes = fullTextIndexPaths }; } if (fullTextPaths.Count != 0) { containerProperties.FullTextPolicy = new FullTextPolicy { - DefaultLanguage = parameters.DefaultFullTextLanguage, - FullTextPaths = fullTextPaths + DefaultLanguage = parameters.DefaultFullTextLanguage, FullTextPaths = fullTextPaths }; } @@ -355,16 +350,16 @@ private static string GetPathFromRoot(IReadOnlyEntityType entityType) if (entityType.IsOwned()) { var ownership = entityType.FindOwnership()!; - var resultPath = GetPathFromRoot(ownership.PrincipalEntityType) + "/" + ownership.GetNavigation(pointsToPrincipal: false)!.TargetEntityType.GetContainingPropertyName(); + var resultPath = GetPathFromRoot(ownership.PrincipalEntityType) + + "/" + + ownership.GetNavigation(pointsToPrincipal: false)!.TargetEntityType.GetContainingPropertyName(); return !ownership.IsUnique ? throw new NotSupportedException(CosmosStrings.CreatingContainerWithFullTextOrVectorOnCollectionNotSupported(resultPath)) : resultPath; } - else - { - return ""; - } + + return ""; } /// @@ -429,6 +424,7 @@ private static async Task CreateItemOnceAsync( { itemRequestOptions.PreTriggers = preTriggers; } + if (postTriggers != null) { itemRequestOptions.PostTriggers = postTriggers; @@ -519,6 +515,7 @@ private static async Task ReplaceItemOnceAsync( { itemRequestOptions.PreTriggers = preTriggers; } + if (postTriggers != null) { itemRequestOptions.PostTriggers = postTriggers; @@ -600,6 +597,7 @@ private static async Task DeleteItemOnceAsync( { itemRequestOptions.PreTriggers = preTriggers; } + if (postTriggers != null) { itemRequestOptions.PostTriggers = postTriggers; @@ -684,9 +682,7 @@ private static async Task DeleteItemOnceAsync( private static bool ShouldExecuteTrigger(ITrigger trigger, TriggerOperation currentOperation) { var triggerOperation = trigger.GetTriggerOperation(); - return triggerOperation == null || - triggerOperation == TriggerOperation.All || - triggerOperation == currentOperation; + return triggerOperation == null || triggerOperation == TriggerOperation.All || triggerOperation == currentOperation; } private static PartitionKey ExtractPartitionKeyValue(IUpdateEntry entry) diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs index 8d475d7268d..0e38528d301 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs @@ -120,7 +120,7 @@ private static IEnumerable GetContainersToCreate(IModel mod var defaultFullTextLanguage = model.GetDefaultFullTextSearchLanguage(); foreach (var (containerName, mappedTypes) in containers) { - IReadOnlyList partitionKeyStoreNames = Array.Empty(); + IReadOnlyList partitionKeyStoreNames = []; int? analyticalTtl = null; int? defaultTtl = null; ThroughputProperties? throughput = null; @@ -176,8 +176,8 @@ static void ProcessEntityType( } foreach (var ownedType in entityType.GetNavigations() - .Where(x => x.ForeignKey.IsOwnership && !x.IsOnDependent && !x.TargetEntityType.IsDocumentRoot()) - .Select(x => x.TargetEntityType)) + .Where(x => x.ForeignKey.IsOwnership && !x.IsOnDependent && !x.TargetEntityType.IsDocumentRoot()) + .Select(x => x.TargetEntityType)) { ProcessEntityType(ownedType, indexes, vectors, fullTextProperties); } diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs index 14d088b1d9b..4464928a038 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs @@ -51,7 +51,8 @@ public CosmosTypeMappingSource(TypeMappingSourceDependencies dependencies) => base.FindMapping(property) switch { CosmosTypeMapping mapping - when property.GetVectorDistanceFunction() is DistanceFunction distanceFunction && property.GetVectorDimensions() is int dimensions + when property.GetVectorDistanceFunction() is { } distanceFunction + && property.GetVectorDimensions() is { } dimensions => new CosmosVectorTypeMapping(mapping, new CosmosVectorType(distanceFunction, dimensions)), var other => other }; diff --git a/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs b/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs index a2c782407f8..75b9a7f415a 100644 --- a/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs +++ b/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs @@ -310,8 +310,7 @@ private static void SetTemporaryOrdinals( } private static IProperty? FindOrdinalKeyProperty(IEntityType entityType) - => entityType.FindPrimaryKey()!.Properties.FirstOrDefault( - p => p.GetJsonPropertyName().Length == 0 && p.IsOrdinalKeyProperty()); + => entityType.FindPrimaryKey()!.Properties.FirstOrDefault(p => p.GetJsonPropertyName().Length == 0 && p.IsOrdinalKeyProperty()); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs b/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs index 38f6ca6242a..12e2a75f27f 100644 --- a/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs +++ b/src/EFCore.Design/Design/DesignTimeServiceCollectionExtensions.cs @@ -35,41 +35,40 @@ public static IServiceCollection AddEntityFrameworkDesignTimeServices( reporter ??= new OperationReporter(handler: null); new EntityFrameworkRelationalDesignServicesBuilder(services) - .TryAddProviderSpecificServices( - services => services - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton(reporter) - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingletonEnumerable() - .TryAddSingletonEnumerable() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton( - new DesignTimeConnectionStringResolver(applicationServiceProviderAccessor)) - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddScoped() - .TryAddScoped() - .TryAddScoped() - .TryAddScoped()); + .TryAddProviderSpecificServices(services => services + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton(reporter) + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingletonEnumerable() + .TryAddSingletonEnumerable() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton( + new DesignTimeConnectionStringResolver(applicationServiceProviderAccessor)) + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddScoped() + .TryAddScoped() + .TryAddScoped() + .TryAddScoped()); var loggerFactory = new LoggerFactory( - new[] { new OperationLoggerProvider(reporter) }, new LoggerFilterOptions { MinLevel = LogLevel.Debug }); + [new OperationLoggerProvider(reporter)], new LoggerFilterOptions { MinLevel = LogLevel.Debug }); services.AddScoped(_ => loggerFactory); return services; diff --git a/src/EFCore.Design/Design/Internal/DatabaseOperations.cs b/src/EFCore.Design/Design/Internal/DatabaseOperations.cs index f02f26bf4ed..db8f590e435 100644 --- a/src/EFCore.Design/Design/Internal/DatabaseOperations.cs +++ b/src/EFCore.Design/Design/Internal/DatabaseOperations.cs @@ -135,7 +135,7 @@ public virtual SavedModelFiles ScaffoldContext( ? string.Join( ".", subPath.Split( - new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries)) + [Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar], StringSplitOptions.RemoveEmptyEntries)) : null; } diff --git a/src/EFCore.Design/Design/Internal/DbContextOperations.cs b/src/EFCore.Design/Design/Internal/DbContextOperations.cs index 2081d72c9bf..9e4e764a430 100644 --- a/src/EFCore.Design/Design/Internal/DbContextOperations.cs +++ b/src/EFCore.Design/Design/Internal/DbContextOperations.cs @@ -384,7 +384,7 @@ private IReadOnlyList PrecompileQueries( ? string.Join( ".", subPath.Split( - new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries)) + [Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar], StringSplitOptions.RemoveEmptyEntries)) : null; } @@ -551,8 +551,7 @@ where i.IsGenericType .Concat(_assembly.GetConstructibleTypes()) .ToList(); - var contextTypes = types.Where(t => typeof(DbContext).IsAssignableFrom(t)).Select( - t => t.AsType()) + var contextTypes = types.Where(t => typeof(DbContext).IsAssignableFrom(t)).Select(t => t.AsType()) .Concat( types.Where(t => typeof(Migration).IsAssignableFrom(t)) .Select(t => t.GetCustomAttribute()?.ContextType) @@ -719,9 +718,8 @@ private KeyValuePair> FindContextType(string? name) string name, StringComparison comparisonType) => types - .Where( - t => string.Equals(t.Key.Name, name, comparisonType) - || string.Equals(t.Key.FullName, name, comparisonType) - || string.Equals(t.Key.AssemblyQualifiedName, name, comparisonType)) + .Where(t => string.Equals(t.Key.Name, name, comparisonType) + || string.Equals(t.Key.FullName, name, comparisonType) + || string.Equals(t.Key.AssemblyQualifiedName, name, comparisonType)) .ToDictionary(); } diff --git a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs index 88a7603b5fa..b7729c1f716 100644 --- a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs +++ b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs @@ -123,7 +123,7 @@ public virtual MigrationFiles AddMigration( ? string.Join( ".", subPath.Split( - new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, + [Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar], StringSplitOptions.RemoveEmptyEntries)) : null; } diff --git a/src/EFCore.Design/Design/OperationExecutor.cs b/src/EFCore.Design/Design/OperationExecutor.cs index 947212a1db8..8c619b4cae0 100644 --- a/src/EFCore.Design/Design/OperationExecutor.cs +++ b/src/EFCore.Design/Design/OperationExecutor.cs @@ -434,18 +434,17 @@ private IEnumerable GetContextTypesImpl() var nameGroups = contextTypes.GroupBy(t => t.Name).ToList(); var fullNameGroups = contextTypes.GroupBy(t => t.FullName).ToList(); - return contextTypes.Select( - t => new Hashtable - { - ["AssemblyQualifiedName"] = t.AssemblyQualifiedName, - ["FullName"] = t.FullName, - ["Name"] = t.Name, - ["SafeName"] = nameGroups.Count(g => g.Key == t.Name) == 1 - ? t.Name - : fullNameGroups.Count(g => g.Key == t.FullName) == 1 - ? t.FullName - : t.AssemblyQualifiedName - }); + return contextTypes.Select(t => new Hashtable + { + ["AssemblyQualifiedName"] = t.AssemblyQualifiedName, + ["FullName"] = t.FullName, + ["Name"] = t.Name, + ["SafeName"] = nameGroups.Count(g => g.Key == t.Name) == 1 + ? t.Name + : fullNameGroups.Count(g => g.Key == t.FullName) == 1 + ? t.FullName + : t.AssemblyQualifiedName + }); } /// @@ -494,16 +493,15 @@ private IEnumerable GetMigrationsImpl( var migrations = MigrationsOperations.GetMigrations(contextType, connectionString, noConnect).ToList(); var nameGroups = migrations.GroupBy(m => m.Name).ToList(); - return migrations.Select( - m => new Hashtable - { - ["Id"] = m.Id, - ["Name"] = m.Name, - ["SafeName"] = nameGroups.Count(g => g.Key == m.Name) == 1 - ? m.Name - : m.Id, - ["Applied"] = m.Applied - }); + return migrations.Select(m => new Hashtable + { + ["Id"] = m.Id, + ["Name"] = m.Name, + ["SafeName"] = nameGroups.Count(g => g.Key == m.Name) == 1 + ? m.Name + : m.Id, + ["Applied"] = m.Applied + }); } /// @@ -543,15 +541,14 @@ public OptimizeContext( var precompileQueries = (bool)(args["precompileQueries"] ?? false); var nativeAot = (bool)(args["nativeAot"] ?? false); - Execute( - () => executor.OptimizeContextImpl( - outputDir, - modelNamespace, - contextType, - suffix, - scaffoldModel, - precompileQueries, - nativeAot)); + Execute(() => executor.OptimizeContextImpl( + outputDir, + modelNamespace, + contextType, + suffix, + scaffoldModel, + precompileQueries, + nativeAot)); } } @@ -616,11 +613,10 @@ public ScaffoldContext( var suppressOnConfiguring = (bool)(args["suppressOnConfiguring"] ?? false); var noPluralize = (bool)(args["noPluralize"] ?? false); - Execute( - () => executor.ScaffoldContextImpl( - provider, connectionString, outputDir, outputDbContextDir, dbContextClassName, - schemaFilters, tableFilters, modelNamespace, contextNamespace, useDataAnnotations, - overwriteFiles, useDatabaseNames, suppressOnConfiguring, noPluralize)); + Execute(() => executor.ScaffoldContextImpl( + provider, connectionString, outputDir, outputDbContextDir, dbContextClassName, + schemaFilters, tableFilters, modelNamespace, contextNamespace, useDataAnnotations, + overwriteFiles, useDatabaseNames, suppressOnConfiguring, noPluralize)); } } diff --git a/src/EFCore.Design/Extensions/ScaffoldingModelExtensions.cs b/src/EFCore.Design/Extensions/ScaffoldingModelExtensions.cs index d984178aba0..36b229d0656 100644 --- a/src/EFCore.Design/Extensions/ScaffoldingModelExtensions.cs +++ b/src/EFCore.Design/Extensions/ScaffoldingModelExtensions.cs @@ -134,13 +134,12 @@ public static IEnumerable GetDataAnnotations( tableNamedArgs.Add(nameof(TableAttribute.Schema), schema); } - yield return new AttributeCodeFragment(typeof(TableAttribute), new object?[] { tableName }, tableNamedArgs); + yield return new AttributeCodeFragment(typeof(TableAttribute), [tableName], tableNamedArgs); } foreach (var index in entityType.GetIndexes() - .Where( - i => ((IConventionIndex)i).GetConfigurationSource() != ConfigurationSource.Convention - && i.IsHandledByDataAnnotations(annotationCodeGenerator))) + .Where(i => ((IConventionIndex)i).GetConfigurationSource() != ConfigurationSource.Convention + && i.IsHandledByDataAnnotations(annotationCodeGenerator))) { var indexArgs = new List(); var indexNamedArgs = new Dictionary(); @@ -632,8 +631,7 @@ public static IEnumerable GetDataAnnotations( } var valueGenerated = property.ValueGenerated; - if (((IConventionProperty)property).GetValueGeneratedConfigurationSource() is ConfigurationSource - valueGeneratedConfigurationSource + if (((IConventionProperty)property).GetValueGeneratedConfigurationSource() is { } valueGeneratedConfigurationSource && valueGeneratedConfigurationSource != ConfigurationSource.Convention && ValueGenerationConvention.GetValueGenerated(property) != valueGenerated) { diff --git a/src/EFCore.Design/Migrations/Design/CSharpMigrationsGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpMigrationsGenerator.cs index 80222f83196..0dc7d93a83e 100644 --- a/src/EFCore.Design/Migrations/Design/CSharpMigrationsGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/CSharpMigrationsGenerator.cs @@ -324,14 +324,13 @@ public override string GenerateSnapshot( private bool HasMultidimensionalArray(IEnumerable operations) { - return operations.Any( - o => - (o is InsertDataOperation insertDataOperation - && IsMultidimensional(insertDataOperation.Values)) - || (o is UpdateDataOperation updateDataOperation - && (IsMultidimensional(updateDataOperation.Values) || IsMultidimensional(updateDataOperation.KeyValues))) - || (o is DeleteDataOperation deleteDataOperation - && IsMultidimensional(deleteDataOperation.KeyValues))); + return operations.Any(o => + (o is InsertDataOperation insertDataOperation + && IsMultidimensional(insertDataOperation.Values)) + || (o is UpdateDataOperation updateDataOperation + && (IsMultidimensional(updateDataOperation.Values) || IsMultidimensional(updateDataOperation.KeyValues))) + || (o is DeleteDataOperation deleteDataOperation + && IsMultidimensional(deleteDataOperation.KeyValues))); static bool IsMultidimensional(Array array) => array.GetLength(0) > 1 && array.GetLength(1) > 1; diff --git a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs index 9c178755547..9938ce572ea 100644 --- a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs @@ -92,17 +92,16 @@ protected virtual void GenerateEntityTypes( GenerateEntityType(modelBuilderName, entityType, stringBuilder); } - foreach (var entityType in nonOwnedTypes.Where( - e => e.GetDeclaredForeignKeys().Any() - || e.GetDeclaredReferencingForeignKeys().Any(fk => fk.IsOwnership))) + foreach (var entityType in nonOwnedTypes.Where(e => e.GetDeclaredForeignKeys().Any() + || e.GetDeclaredReferencingForeignKeys().Any(fk => fk.IsOwnership))) { stringBuilder.AppendLine(); GenerateEntityTypeRelationships(modelBuilderName, entityType, stringBuilder); } - foreach (var entityType in nonOwnedTypes.Where( - e => e.GetDeclaredNavigations().Any(n => n is { IsOnDependent: false, ForeignKey.IsOwnership: false }))) + foreach (var entityType in nonOwnedTypes.Where(e + => e.GetDeclaredNavigations().Any(n => n is { IsOnDependent: false, ForeignKey.IsOwnership: false }))) { stringBuilder.AppendLine(); @@ -131,7 +130,7 @@ protected virtual void GenerateEntityType( { entityTypeName = entityType.ClrType.DisplayName(); } - else if (entityTypeName == ownership!.PrincipalEntityType.GetOwnedName(entityType.ShortName(), ownerNavigation)) + else if (entityTypeName == ownership.PrincipalEntityType.GetOwnedName(entityType.ShortName(), ownerNavigation)) { entityTypeName = entityType.ShortName(); } @@ -514,7 +513,7 @@ protected virtual void GeneratePropertyAnnotations( if (annotations.ContainsKey(RelationalAnnotationNames.DefaultValue) && property.TryGetDefaultValue(out var defaultValue) && defaultValue != DBNull.Value - && FindValueConverter(property) is ValueConverter valueConverter) + && FindValueConverter(property) is { } valueConverter) { annotations[RelationalAnnotationNames.DefaultValue] = new Annotation( RelationalAnnotationNames.DefaultValue, @@ -661,13 +660,10 @@ protected virtual void GenerateComplexPropertyAnnotations( var discriminatorValue = property.ComplexType.GetDiscriminatorValue(); if (discriminatorValue != null) { - if (discriminatorProperty != null) + var valueConverter = FindValueConverter(discriminatorProperty); + if (valueConverter != null) { - var valueConverter = FindValueConverter(discriminatorProperty); - if (valueConverter != null) - { - discriminatorValue = valueConverter.ConvertToProvider(discriminatorValue); - } + discriminatorValue = valueConverter.ConvertToProvider(discriminatorValue); } stringBuilder @@ -718,10 +714,9 @@ protected virtual void GenerateKeys( if (primaryKey?.DeclaringEntityType.IsOwned() != true) { - foreach (var key in keys.Where( - key => key != primaryKey - && (!key.GetReferencingForeignKeys().Any() - || key.GetAnnotations().Any(a => a.Name != RelationalAnnotationNames.UniqueConstraintMappings)))) + foreach (var key in keys.Where(key => key != primaryKey + && (!key.GetReferencingForeignKeys().Any() + || key.GetAnnotations().Any(a => a.Name != RelationalAnnotationNames.UniqueConstraintMappings)))) { GenerateKey(entityTypeBuilderName, key, stringBuilder); } @@ -986,13 +981,10 @@ protected virtual void GenerateEntityTypeAnnotations( if (discriminatorValueAnnotation?.Value != null) { var value = discriminatorValueAnnotation.Value; - if (discriminatorProperty != null) + var valueConverter = FindValueConverter(discriminatorProperty); + if (valueConverter != null) { - var valueConverter = FindValueConverter(discriminatorProperty); - if (valueConverter != null) - { - value = valueConverter.ConvertToProvider(value); - } + value = valueConverter.ConvertToProvider(value); } stringBuilder @@ -1016,17 +1008,17 @@ private void GenerateTableMapping( IndentedStringBuilder stringBuilder, Dictionary annotations) { - annotations.TryGetAndRemove(RelationalAnnotationNames.TableName, out IAnnotation tableNameAnnotation); + annotations.TryGetAndRemove(RelationalAnnotationNames.TableName, out IAnnotation? tableNameAnnotation); var table = StoreObjectIdentifier.Create(entityType, StoreObjectType.Table); var tableName = (string?)tableNameAnnotation?.Value ?? table?.Name; - annotations.TryGetAndRemove(RelationalAnnotationNames.Schema, out IAnnotation schemaAnnotation); + annotations.TryGetAndRemove(RelationalAnnotationNames.Schema, out IAnnotation? schemaAnnotation); var schema = (string?)schemaAnnotation?.Value ?? table?.Schema; - annotations.TryGetAndRemove(RelationalAnnotationNames.IsTableExcludedFromMigrations, out IAnnotation isExcludedAnnotation); + annotations.TryGetAndRemove(RelationalAnnotationNames.IsTableExcludedFromMigrations, out IAnnotation? isExcludedAnnotation); var isExcludedFromMigrations = (isExcludedAnnotation?.Value as bool?) == true; - annotations.TryGetAndRemove(RelationalAnnotationNames.Comment, out IAnnotation commentAnnotation); + annotations.TryGetAndRemove(RelationalAnnotationNames.Comment, out IAnnotation? commentAnnotation); var comment = (string?)commentAnnotation?.Value; var hasTriggers = entityType.GetDeclaredTriggers().Any(t => t.GetTableName() == tableName! && t.GetTableSchema() == schema); @@ -1112,7 +1104,7 @@ private void GenerateTableMapping( { stringBuilder .AppendLine() - .AppendLine($"t.{nameof(TableBuilder.HasComment)}({Code.Literal(comment!)});"); + .AppendLine($"t.{nameof(TableBuilder.HasComment)}({Code.Literal(comment)});"); } if (hasTriggers) @@ -1177,8 +1169,8 @@ private void GenerateViewMapping( IndentedStringBuilder stringBuilder, Dictionary annotations) { - annotations.TryGetAndRemove(RelationalAnnotationNames.ViewName, out IAnnotation viewNameAnnotation); - annotations.TryGetAndRemove(RelationalAnnotationNames.ViewSchema, out IAnnotation viewSchemaAnnotation); + annotations.TryGetAndRemove(RelationalAnnotationNames.ViewName, out IAnnotation? viewNameAnnotation); + annotations.TryGetAndRemove(RelationalAnnotationNames.ViewSchema, out IAnnotation? viewSchemaAnnotation); annotations.Remove(RelationalAnnotationNames.ViewDefinitionSql); var view = StoreObjectIdentifier.Create(entityType, StoreObjectType.View); @@ -1435,7 +1427,7 @@ protected virtual void GenerateTriggerAnnotations( .FilterIgnoredAnnotations(trigger.GetAnnotations()) .ToDictionary(a => a.Name, a => a); - if (annotations.TryGetAndRemove(RelationalAnnotationNames.Name, out IAnnotation nameAnnotation)) + if (annotations.TryGetAndRemove(RelationalAnnotationNames.Name, out IAnnotation? nameAnnotation)) { stringBuilder .AppendLine() @@ -1876,7 +1868,7 @@ private void GenerateFluentApiForMaxLength( IProperty property, IndentedStringBuilder stringBuilder) { - if (property.GetMaxLength() is int maxLength) + if (property.GetMaxLength() is { } maxLength) { stringBuilder .AppendLine() @@ -1892,7 +1884,7 @@ private void GenerateFluentApiForPrecisionAndScale( IProperty property, IndentedStringBuilder stringBuilder) { - if (property.GetPrecision() is int precision) + if (property.GetPrecision() is { } precision) { stringBuilder .AppendLine() @@ -1901,7 +1893,7 @@ private void GenerateFluentApiForPrecisionAndScale( .Append("(") .Append(Code.Literal(precision)); - if (property.GetScale() is int scale) + if (property.GetScale() is { } scale) { if (scale != 0) { @@ -1919,7 +1911,7 @@ private void GenerateFluentApiForIsUnicode( IProperty property, IndentedStringBuilder stringBuilder) { - if (property.IsUnicode() is bool unicode) + if (property.IsUnicode() is { } unicode) { stringBuilder .AppendLine() @@ -2030,7 +2022,7 @@ private static string GetFullName(IReadOnlyEntityType entityType) if (entityType.HasSharedClrType && entityTypeName - == ownership!.PrincipalEntityType.GetOwnedName( + == ownership.PrincipalEntityType.GetOwnedName( entityType.ClrType.ShortDisplayName(), ownership.PrincipalToDependent!.Name)) { entityTypeName = entityType.ClrType.DisplayName(); diff --git a/src/EFCore.Design/Migrations/Design/MigrationsBundle.cs b/src/EFCore.Design/Migrations/Design/MigrationsBundle.cs index e9c4c28173a..d1d53afdb56 100644 --- a/src/EFCore.Design/Migrations/Design/MigrationsBundle.cs +++ b/src/EFCore.Design/Migrations/Design/MigrationsBundle.cs @@ -78,17 +78,16 @@ internal static void Configure(CommandLineApplication app) app.HandleResponseFiles = true; - app.OnExecute( - args => - { - Reporter.IsVerbose = verbose.HasValue(); - Reporter.NoColor = noColor.HasValue(); - Reporter.PrefixOutput = prefixOutput.HasValue(); + app.OnExecute(args => + { + Reporter.IsVerbose = verbose.HasValue(); + Reporter.NoColor = noColor.HasValue(); + Reporter.PrefixOutput = prefixOutput.HasValue(); - ExecuteInternal(args); + ExecuteInternal(args); - return 0; - }); + return 0; + }); } private static void ExecuteInternal(string[] args) diff --git a/src/EFCore.Design/Migrations/Design/MigrationsCodeGenerator.cs b/src/EFCore.Design/Migrations/Design/MigrationsCodeGenerator.cs index 6fdb07fc11f..16c7dbb5917 100644 --- a/src/EFCore.Design/Migrations/Design/MigrationsCodeGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/MigrationsCodeGenerator.cs @@ -170,12 +170,11 @@ private static IEnumerable GetAnnotatables(IEnumerableThe model. /// The namespaces. protected virtual IEnumerable GetNamespaces(IModel model) - => model.GetEntityTypes().SelectMany( - e => GetNamespaces(e) - .Concat( - e.GetDeclaredComplexProperties().Any() - ? Model.DefaultPropertyBagType.GetNamespaces() - : Enumerable.Empty())) + => model.GetEntityTypes().SelectMany(e => GetNamespaces(e) + .Concat( + e.GetDeclaredComplexProperties().Any() + ? Model.DefaultPropertyBagType.GetNamespaces() + : [])) .Concat(GetAnnotationNamespaces(GetAnnotatables(model))); private IEnumerable GetNamespaces(ITypeBase typeBase) @@ -276,11 +275,10 @@ private static IEnumerable GetAnnotatables(IComplexProperty comple } private IEnumerable GetAnnotationNamespaces(IEnumerable items) - => items.SelectMany( - i => Dependencies.AnnotationCodeGenerator.FilterIgnoredAnnotations(i.GetAnnotations()) - .Where(a => a.Value != null) - .Select(a => new { Annotatable = i, Annotation = a }) - .SelectMany(a => GetProviderType(a.Annotatable, a.Annotation.Value!.GetType()).GetNamespaces())); + => items.SelectMany(i => Dependencies.AnnotationCodeGenerator.FilterIgnoredAnnotations(i.GetAnnotations()) + .Where(a => a.Value != null) + .Select(a => new { Annotatable = i, Annotation = a }) + .SelectMany(a => GetProviderType(a.Annotatable, a.Annotation.Value!.GetType()).GetNamespaces())); private ValueConverter? FindValueConverter(IProperty property) => property.GetTypeMapping().Converter; diff --git a/src/EFCore.Design/Migrations/Design/MigrationsScaffolder.cs b/src/EFCore.Design/Migrations/Design/MigrationsScaffolder.cs index a64419911ad..648929011f1 100644 --- a/src/EFCore.Design/Migrations/Design/MigrationsScaffolder.cs +++ b/src/EFCore.Design/Migrations/Design/MigrationsScaffolder.cs @@ -270,8 +270,8 @@ public virtual MigrationFiles RemoveMigration( var applied = false; try { - applied = Dependencies.HistoryRepository.GetAppliedMigrations().Any( - e => e.MigrationId.Equals(migration.GetId(), StringComparison.OrdinalIgnoreCase)); + applied = Dependencies.HistoryRepository.GetAppliedMigrations().Any(e => e.MigrationId.Equals( + migration.GetId(), StringComparison.OrdinalIgnoreCase)); } catch (Exception ex) when (force) { diff --git a/src/EFCore.Design/Migrations/Internal/SnapshotModelProcessor.cs b/src/EFCore.Design/Migrations/Internal/SnapshotModelProcessor.cs index 30b89651e13..40bf9f2bb00 100644 --- a/src/EFCore.Design/Migrations/Internal/SnapshotModelProcessor.cs +++ b/src/EFCore.Design/Migrations/Internal/SnapshotModelProcessor.cs @@ -34,9 +34,8 @@ public SnapshotModelProcessor( [ ..typeof(RelationalAnnotationNames) .GetRuntimeFields() - .Where( - p => p.Name != nameof(RelationalAnnotationNames.Prefix) - && p.Name != nameof(RelationalAnnotationNames.AllNames)) + .Where(p => p.Name != nameof(RelationalAnnotationNames.Prefix) + && p.Name != nameof(RelationalAnnotationNames.AllNames)) .Select(p => (string)p.GetValue(null)!) .Where(v => v.IndexOf(':') > 0) .Select(v => v[(RelationalAnnotationNames.Prefix.Length - 1)..]) diff --git a/src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs b/src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs index c9668012c2d..a0f072c6ed5 100644 --- a/src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs +++ b/src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs @@ -69,7 +69,7 @@ INamedTypeSymbol GetTypeSymbolOrThrow(string fullyQualifiedMetadataName) } private readonly Stack> _parameterStack - = new(new[] { ImmutableDictionary.Empty }); + = new([ImmutableDictionary.Empty]); private readonly Dictionary _dataFlowsIn = new(SymbolEqualityComparer.Default); @@ -242,7 +242,7 @@ public override Expression VisitArrayCreationExpression(ArrayCreationExpressionS } var elementType = ResolveType(arrayTypeSymbol.ElementType); - Check.DebugAssert(elementType is not null, "elementType is not null"); + Check.DebugAssert(elementType is not null); return arrayCreation.Initializer is null ? NewArrayBounds(elementType, Visit(arrayCreation.Type.RankSpecifiers[0].Sizes[0])) @@ -278,7 +278,7 @@ public override Expression VisitBinaryExpression(BinaryExpressionSyntax binary) => Add( left, right, _stringConcatMethod ??= - typeof(string).GetMethod(nameof(string.Concat), new[] { typeof(string), typeof(string) })), + typeof(string).GetMethod(nameof(string.Concat), [typeof(string), typeof(string)])), SyntaxKind.AddExpression => Add(left, right), SyntaxKind.SubtractExpression => Subtract(left, right), @@ -374,11 +374,10 @@ public override Expression VisitElementAccessExpression(ElementAccessExpressionS var property = visitedExpression.Type .GetProperties() .Select(p => new { Property = p, IndexParameters = p.GetIndexParameters() }) - .Where( - t => t.IndexParameters.Length == arguments.Count - && t.IndexParameters - .Select(p => p.ParameterType) - .SequenceEqual(arguments.Select(a => ResolveType(a.Expression)))) + .Where(t => t.IndexParameters.Length == arguments.Count + && t.IndexParameters + .Select(p => p.ParameterType) + .SequenceEqual(arguments.Select(a => ResolveType(a.Expression)))) .Select(t => t.Property) .FirstOrDefault(); @@ -484,7 +483,7 @@ public override Expression VisitImplicitArrayCreationExpression(ImplicitArrayCre } var elementType = ResolveType(arrayTypeSymbol.ElementType); - Check.DebugAssert(elementType is not null, "elementType is not null"); + Check.DebugAssert(elementType is not null); var initializers = implicitArrayCreation.Initializer.Expressions.Select(e => Visit(e)); @@ -589,45 +588,44 @@ public override Expression VisitInvocationExpression(InvocationExpressionSyntax var typeTypeParameterMap = new Dictionary(GetTypeTypeParameters(methodSymbol.ContainingType)); var definitionMethodInfos = declaringType.GetMethods() - .Where( - m => + .Where(m => + { + if (m.Name == methodSymbol.Name + && m.IsGenericMethodDefinition + && m.GetGenericArguments() is var candidateGenericArguments + && candidateGenericArguments.Length == originalDefinition.TypeParameters.Length + && m.GetParameters() is var candidateParams + && candidateParams.Length == originalDefinition.Parameters.Length) { - if (m.Name == methodSymbol.Name - && m.IsGenericMethodDefinition - && m.GetGenericArguments() is var candidateGenericArguments - && candidateGenericArguments.Length == originalDefinition.TypeParameters.Length - && m.GetParameters() is var candidateParams - && candidateParams.Length == originalDefinition.Parameters.Length) - { - var methodTypeParameterMap = new Dictionary(typeTypeParameterMap); + var methodTypeParameterMap = new Dictionary(typeTypeParameterMap); - // Prepare a dictionary that will be used to resolve generic type parameters (ITypeParameterSymbol) to the - // corresponding reflection Type. This is needed to correctly (and recursively) resolve the type of parameters - // below. - foreach (var (symbol, type) in methodSymbol.TypeParameters.Zip(candidateGenericArguments)) + // Prepare a dictionary that will be used to resolve generic type parameters (ITypeParameterSymbol) to the + // corresponding reflection Type. This is needed to correctly (and recursively) resolve the type of parameters + // below. + foreach (var (symbol, type) in methodSymbol.TypeParameters.Zip(candidateGenericArguments)) + { + if (symbol.Name != type.Name) { - if (symbol.Name != type.Name) - { - return false; - } - - methodTypeParameterMap[symbol.Name] = type; + return false; } - for (var i = 0; i < candidateParams.Length; i++) + methodTypeParameterMap[symbol.Name] = type; + } + + for (var i = 0; i < candidateParams.Length; i++) + { + var translatedParamType = ResolveType(originalDefinition.Parameters[i].Type, methodTypeParameterMap); + if (translatedParamType != candidateParams[i].ParameterType) { - var translatedParamType = ResolveType(originalDefinition.Parameters[i].Type, methodTypeParameterMap); - if (translatedParamType != candidateParams[i].ParameterType) - { - return false; - } + return false; } - - return true; } - return false; - }).ToArray(); + return true; + } + + return false; + }).ToArray(); if (definitionMethodInfos.Length != 1) { @@ -732,7 +730,7 @@ IEnumerable> GetTypeTypeParameters(INamedTypeSymbol t { // TODO: We match Roslyn type parameters by name, not sure that's right; also for the method's generic type parameters - if (typeSymbol.ContainingType is INamedTypeSymbol containingTypeSymbol) + if (typeSymbol.ContainingType is { } containingTypeSymbol) { foreach (var kvp in GetTypeTypeParameters(containingTypeSymbol)) { @@ -744,8 +742,7 @@ IEnumerable> GetTypeTypeParameters(INamedTypeSymbol t var genericArguments = type.GetGenericArguments(); Check.DebugAssert( - genericArguments.Length == typeSymbol.TypeParameters.Length, - "genericArguments.Length == typeSymbol.TypeParameters.Length"); + genericArguments.Length == typeSymbol.TypeParameters.Length); foreach (var (typeParamSymbol, typeParamType) in typeSymbol.TypeParameters.Zip(genericArguments)) { @@ -761,7 +758,7 @@ IEnumerable> GetTypeTypeParameters(INamedTypeSymbol t /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public override Expression VisitLiteralExpression(LiteralExpressionSyntax literal) - => _semanticModel.GetTypeInfo(literal) is { ConvertedType: ITypeSymbol type } + => _semanticModel.GetTypeInfo(literal) is { ConvertedType: { } type } ? Constant(literal.Token.Value, ResolveType(type)) : Constant(literal.Token.Value); @@ -775,7 +772,7 @@ public override Expression VisitMemberAccessExpression(MemberAccessExpressionSyn { var expression = Visit(memberAccess.Expression); - if (_semanticModel.GetSymbolInfo(memberAccess).Symbol is not ISymbol memberSymbol) + if (_semanticModel.GetSymbolInfo(memberAccess).Symbol is not { } memberSymbol) { throw new InvalidOperationException($"MemberAccess: Couldn't find symbol for member: {memberAccess}"); } @@ -835,7 +832,7 @@ public override Expression VisitObjectCreationExpression(ObjectCreationExpressio throw new InvalidOperationException($"ObjectCreation: couldn't find IMethodSymbol for constructor: {objectCreation}"); } - Check.DebugAssert(constructorSymbol.MethodKind == MethodKind.Constructor, "constructorSymbol.MethodKind == MethodKind.Constructor"); + Check.DebugAssert(constructorSymbol.MethodKind == MethodKind.Constructor); var type = ResolveType(constructorSymbol.ContainingType); @@ -846,7 +843,7 @@ public override Expression VisitObjectCreationExpression(ObjectCreationExpressio var newExpression = constructor is not null ? New( constructor, - objectCreation.ArgumentList?.Arguments.Select(a => Visit(a)) ?? Array.Empty()) + objectCreation.ArgumentList?.Arguments.Select(a => Visit(a)) ?? []) : parameterTypes.Length == 0 // For structs, there's no actual parameterless constructor ? New(type) : throw new InvalidOperationException($"ObjectCreation: Missing constructor: {objectCreation}"); @@ -861,33 +858,32 @@ public override Expression VisitObjectCreationExpression(ObjectCreationExpressio case { Expressions: [AssignmentExpressionSyntax, ..] }: return MemberInit( newExpression, - objectCreation.Initializer.Expressions.Select( - e => + objectCreation.Initializer.Expressions.Select(e => + { + if (e is not AssignmentExpressionSyntax { Left: var lValue, Right: var value }) { - if (e is not AssignmentExpressionSyntax { Left: var lValue, Right: var value }) - { - throw new NotSupportedException( - $"ObjectCreation: non-assignment initializer expression of type '{e.GetType().Name}': {objectCreation}"); - } + throw new NotSupportedException( + $"ObjectCreation: non-assignment initializer expression of type '{e.GetType().Name}': {objectCreation}"); + } - var lValueSymbol = _semanticModel.GetSymbolInfo(lValue).Symbol; - var memberInfo = lValueSymbol switch - { - IPropertySymbol p => (MemberInfo?)type.GetProperty(p.Name), - IFieldSymbol f => type.GetField(f.Name), + var lValueSymbol = _semanticModel.GetSymbolInfo(lValue).Symbol; + var memberInfo = lValueSymbol switch + { + IPropertySymbol p => (MemberInfo?)type.GetProperty(p.Name), + IFieldSymbol f => type.GetField(f.Name), - _ => throw new InvalidOperationException( - $"ObjectCreation: unsupported initializer for member of type '{lValueSymbol?.GetType().Name}': {e}") - }; + _ => throw new InvalidOperationException( + $"ObjectCreation: unsupported initializer for member of type '{lValueSymbol?.GetType().Name}': {e}") + }; - if (memberInfo is null) - { - throw new InvalidOperationException( - $"ObjectCreation: couldn't find initialized member '{lValueSymbol.Name}': {e}"); - } + if (memberInfo is null) + { + throw new InvalidOperationException( + $"ObjectCreation: couldn't find initialized member '{lValueSymbol.Name}': {e}"); + } - return Bind(memberInfo, Visit(value)); - })); + return Bind(memberInfo, Visit(value)); + })); // Non-assignment initializer => list initializer (new List { 1, 2, 3 }) default: @@ -1083,8 +1079,8 @@ private Expression VisitLambdaExpression(AnonymousFunctionExpressionSyntax lambd _parameterStack.Push( _parameterStack.Peek() .AddRange( - translatedParameters.Select( - p => new KeyValuePair(p.Name ?? throw new NotImplementedException(), p)))); + translatedParameters.Select(p + => new KeyValuePair(p.Name ?? throw new NotImplementedException(), p)))); try { diff --git a/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs b/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs index 50292001598..897d600b4c1 100644 --- a/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs +++ b/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs @@ -13,6 +13,8 @@ using Microsoft.EntityFrameworkCore.Design.Internal; using Microsoft.EntityFrameworkCore.Internal; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using Attribute = System.Attribute; +using ConditionalExpression = System.Linq.Expressions.ConditionalExpression; namespace Microsoft.EntityFrameworkCore.Query.Internal; @@ -149,8 +151,8 @@ protected virtual SyntaxNode TranslateCore( Check.DebugAssert(_stack.Count == 1, "_parameterStack.Count == 1"); Check.DebugAssert(_stack.Peek().Variables.Count == 0, "_stack.Peek().Parameters.Count == 0"); Check.DebugAssert(_stack.Peek().VariableNames.Count == 0, "_stack.Peek().ParameterNames.Count == 0"); - Check.DebugAssert(_stack.Peek().Labels.Count == 0, "_stack.Peek().Labels.Count == 0"); - Check.DebugAssert(_stack.Peek().UniqueLabelNames.Count == 0, "_stack.Peek().UniqueLabelNames.Count == 0"); + Check.DebugAssert(_stack.Peek().Labels.Count == 0); + Check.DebugAssert(_stack.Peek().UniqueLabelNames.Count == 0); foreach (var unsafeAccessor in _fieldUnsafeAccessors.Values.Concat(_methodUnsafeAccessors.Values)) { @@ -551,7 +553,7 @@ protected override Expression VisitBlock(BlockExpression block) // We're on the last line of a block in expression context - the block is being lifted out. // All statements before the last line (this one) have already been added to _liftedStatements, just return the last // expression. - Check.DebugAssert(onLastBlockLine, "onLastBlockLine"); + Check.DebugAssert(onLastBlockLine); Result = translated; break; } @@ -639,9 +641,8 @@ protected override Expression VisitBlock(BlockExpression block) // But there may still be variables that get assigned inside nested blocks or other situations; prepare declarations for those // and either add them to the block, or lift them if we're an expression block. var unassignedVariableDeclarations = - unassignedVariables.Select( - v => (LocalDeclarationStatementSyntax)_g.LocalDeclarationStatement( - Generate(v.Type), LookupVariableName(v), initializer: _g.DefaultExpression(Generate(v.Type)))); + unassignedVariables.Select(v => (LocalDeclarationStatementSyntax)_g.LocalDeclarationStatement( + Generate(v.Type), LookupVariableName(v), initializer: _g.DefaultExpression(Generate(v.Type)))); if (blockContext == ExpressionContext.Expression) { @@ -660,7 +661,7 @@ protected override Expression VisitBlock(BlockExpression block) if (ownStackFrame is not null) { var popped = _stack.Pop(); - Check.DebugAssert(popped.Equals(ownStackFrame), "popped.Equals(ownStackFrame)"); + Check.DebugAssert(popped.Equals(ownStackFrame)); } _onLastLambdaLine = parentOnLastLambdaLine; @@ -758,7 +759,7 @@ protected virtual SyntaxNode TranslateCatchBlock(CatchBlock catchBlock, bool noT if (catchBlock.Variable is not null) { - Check.DebugAssert(catchDeclaration is not null, "catchDeclaration is not null"); + Check.DebugAssert(catchDeclaration is not null); if (catchBlock.Variable.Name is null) { @@ -808,7 +809,8 @@ protected virtual CSharpSyntaxNode TranslateConditional( if (isFalseAbsent) { throw new NotSupportedException( - $"Missing {nameof(System.Linq.Expressions.ConditionalExpression.IfFalse)} in {nameof(System.Linq.Expressions.ConditionalExpression)} in expression context"); + $"Missing {nameof(ConditionalExpression.IfFalse)} in " + + "{nameof(System.Linq.Expressions.ConditionalExpression)} in expression context"); } var parentLiftedState = _liftedState; @@ -1116,7 +1118,7 @@ ExpressionSyntax HandleEnum(Enum e) } var components = formatted.Split(", "); - Check.DebugAssert(components.Length > 0, "components.Length > 0"); + Check.DebugAssert(components.Length > 0); return components.Aggregate( (ExpressionSyntax?)null, @@ -1499,7 +1501,7 @@ protected override Expression VisitLambda(Expression lambda) if (_liftedState.Statements.Count > 0) { - Check.DebugAssert(lambda.ReturnType != typeof(void), "lambda.ReturnType != typeof(void)"); + Check.DebugAssert(lambda.ReturnType != typeof(void)); if (expressionBody != null) { @@ -1527,14 +1529,13 @@ protected override Expression VisitLambda(Expression lambda) returnType: lambda.ReturnType == typeof(void) || !TryGenerate(lambda.ReturnType, out var returnSyntax) ? null : returnSyntax, ParameterList( SeparatedList( - lambda.Parameters.Select( - p => Parameter(Identifier(LookupVariableName(p))) - .WithType(p.Type.IsAnonymousType() ? null : Generate(p.Type))))), + lambda.Parameters.Select(p => Parameter(Identifier(LookupVariableName(p))) + .WithType(p.Type.IsAnonymousType() ? null : Generate(p.Type))))), blockBody, expressionBody); var popped = _stack.Pop(); - Check.DebugAssert(popped.Equals(stackFrame), "popped.Equals(stackFrame)"); + Check.DebugAssert(popped.Equals(stackFrame)); _onLastLambdaLine = parentOnLastLambdaLine; @@ -1609,7 +1610,7 @@ protected override Expression VisitMember(MemberExpression member) case { Member: FieldInfo closureField, Expression: ConstantExpression constantExpression } when constantExpression.Type.Attributes.HasFlag(TypeAttributes.NestedPrivate) - && System.Attribute.IsDefined(constantExpression.Type, typeof(CompilerGeneratedAttribute), inherit: true): + && Attribute.IsDefined(constantExpression.Type, typeof(CompilerGeneratedAttribute), inherit: true): // Unwrap closure VisitConstant(Expression.Constant(closureField.GetValue(constantExpression.Value), member.Type)); break; @@ -1749,7 +1750,7 @@ private MethodDeclarationSyntax GetUnsafeAccessorDeclaration(MemberInfo member, _stringBuilder.Clear().Append("UnsafeAccessor_"); - if (member.DeclaringType?.Namespace?.Replace(".", "_") is string typeNamespace) + if (member.DeclaringType?.Namespace?.Replace(".", "_") is { } typeNamespace) { _stringBuilder.Append(typeNamespace).Append('_'); } @@ -1812,10 +1813,9 @@ private MethodDeclarationSyntax GetUnsafeAccessorDeclaration(MemberInfo member, [ _g.ParameterDeclaration("instance", Generate(member.DeclaringType)), .. method.GetParameters() - .Select( - p => _g.ParameterDeclaration( - p.Name ?? throw new UnreachableException("Missing parameter name"), - Generate(p.ParameterType))) + .Select(p => _g.ParameterDeclaration( + p.Name ?? throw new UnreachableException("Missing parameter name"), + Generate(p.ParameterType))) ]); unsafeAccessorDeclaration = @@ -1841,10 +1841,9 @@ .. method.GetParameters() modifiers: DeclarationModifiers.Static | DeclarationModifiers.Extern, returnType: Generate(member.DeclaringType), parameters: constructor.GetParameters() - .Select( - p => _g.ParameterDeclaration( - p.Name ?? throw new UnreachableException("Missing parameter name"), - Generate(p.ParameterType)))); + .Select(p => _g.ParameterDeclaration( + p.Name ?? throw new UnreachableException("Missing parameter name"), + Generate(p.ParameterType)))); unsafeAccessorDeclaration = (MethodDeclarationSyntax)_g.AddAttributes( @@ -1959,7 +1958,7 @@ protected override Expression VisitMethodCall(MethodCallExpression call) // If the member isn't declared on the same type as the expression, (e.g. explicit interface implementation), add // a cast up to the declaring type. - { Method.DeclaringType: Type declaringType, Object.Type: Type objectType, } when declaringType != objectType + { Method.DeclaringType: { } declaringType, Object.Type: var objectType, } when declaringType != objectType => ParenthesizedExpression(CastExpression(Generate(declaringType), Translate(call.Object))), _ => Translate(call.Object) @@ -2016,13 +2015,14 @@ void ProcessType(Type type) } } - static bool IsNull(ExpressionSyntax expr) => expr switch - { - LiteralExpressionSyntax literal when literal.IsKind(SyntaxKind.NullLiteralExpression) => true, - CastExpressionSyntax cast => IsNull(cast.Expression), - ParenthesizedExpressionSyntax parenthesized => IsNull(parenthesized.Expression), - _ => false - }; + static bool IsNull(ExpressionSyntax expr) + => expr switch + { + LiteralExpressionSyntax literal when literal.IsKind(SyntaxKind.NullLiteralExpression) => true, + CastExpressionSyntax cast => IsNull(cast.Expression), + ParenthesizedExpressionSyntax parenthesized => IsNull(parenthesized.Expression), + _ => false + }; } /// @@ -2044,7 +2044,7 @@ protected override Expression VisitNewArray(NewArrayExpression newArray) return newArray; } - Check.DebugAssert(newArray.NodeType == ExpressionType.NewArrayInit, "newArray.NodeType == ExpressionType.NewArrayInit"); + Check.DebugAssert(newArray.NodeType == ExpressionType.NewArrayInit); Result = _g.ArrayCreationExpression(elementType, expressions); @@ -2069,9 +2069,8 @@ protected override Expression VisitNew(NewExpression node) Result = AnonymousObjectCreationExpression( SeparatedList( - arguments.Select( - (arg, i) => - AnonymousObjectMemberDeclarator(NameEquals(node.Members[i].Name), arg.Expression)) + arguments.Select((arg, i) => + AnonymousObjectMemberDeclarator(NameEquals(node.Members[i].Name), arg.Expression)) .ToArray())); return node; @@ -2079,7 +2078,7 @@ protected override Expression VisitNew(NewExpression node) // If the constructor isn't public, or it has required properties and the constructor doesn't have [SetsRequiredMembers], we can't // just generate a regular instantiation expression (won't compile). Generate an unsafe accessor instead. - if (node.Constructor is ConstructorInfo constructor + if (node.Constructor is { } constructor && (!constructor.IsPublic || node.Type.GetCustomAttribute() is not null && constructor.GetCustomAttribute() is null)) @@ -2167,11 +2166,10 @@ protected virtual CSharpSyntaxNode TranslateSwitch(SwitchExpression switchNode, _liftedState = parentLiftedState.CreateChild(); var cases = List( - switchNode.Cases.Select( - c => SwitchSection( - labels: List( - c.TestValues.Select(tv => CaseSwitchLabel(Translate(tv)))), - statements: ProcessArmBody(c.Body)))); + switchNode.Cases.Select(c => SwitchSection( + labels: List( + c.TestValues.Select(tv => CaseSwitchLabel(Translate(tv)))), + statements: ProcessArmBody(c.Body)))); // LINQ SwitchExpression supports non-literal labels, which C# does not support. This rewrites the switch as a series of // nested ConditionalExpressions. @@ -2262,11 +2260,10 @@ SyntaxList ProcessArmBody(Expression body) } var cases = List( - switchNode.Cases.Select( - c => SwitchSection( - labels: List( - c.TestValues.Select(tv => CaseSwitchLabel(Translate(tv)))), - statements: ProcessArmBody(c.Body))) + switchNode.Cases.Select(c => SwitchSection( + labels: List( + c.TestValues.Select(tv => CaseSwitchLabel(Translate(tv)))), + statements: ProcessArmBody(c.Body))) .Append( SwitchSection( SingletonList(DefaultSwitchLabel()), @@ -2381,8 +2378,7 @@ protected override Expression VisitTry(TryExpression tryNode) if (tryNode.Fault is not null) { Check.DebugAssert( - tryNode.Finally is null && tryNode.Handlers.Count == 0, - "tryNode.Finally is null && tryNode.Handlers.Count == 0"); + tryNode.Finally is null && tryNode.Handlers.Count == 0); Result = _g.TryCatchStatement( translatedBody, @@ -2577,7 +2573,7 @@ protected override Expression VisitListInit(ListInitExpression listInit) /// protected override ElementInit VisitElementInit(ElementInit elementInit) { - Check.DebugAssert(elementInit.Arguments.Count == 1, "elementInit.Arguments.Count == 1"); + Check.DebugAssert(elementInit.Arguments.Count == 1); Visit(elementInit.Arguments.Single()); @@ -2604,12 +2600,11 @@ protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBind InitializerExpression( SyntaxKind.ObjectInitializerExpression, SeparatedList( - memberMemberBinding.Bindings.Select( - b => - { - VisitMemberBinding(b); - return (ExpressionSyntax)Result!; - })))); + memberMemberBinding.Bindings.Select(b => + { + VisitMemberBinding(b); + return (ExpressionSyntax)Result!; + })))); return memberMemberBinding; } @@ -2623,12 +2618,11 @@ protected override MemberListBinding VisitMemberListBinding(MemberListBinding me InitializerExpression( SyntaxKind.CollectionInitializerExpression, SeparatedList( - memberListBinding.Initializers.Select( - i => - { - VisitElementInit(i); - return (ExpressionSyntax)Result!; - })))); + memberListBinding.Initializers.Select(i => + { + VisitElementInit(i); + return (ExpressionSyntax)Result!; + })))); return memberListBinding; } @@ -2685,7 +2679,7 @@ private ArgumentSyntax[] TranslateMethodArguments(ParameterInfo[] parameters, IR private ExpressionSyntax[] TranslateList(IReadOnlyList list) { - Check.DebugAssert(_context == ExpressionContext.Expression, "_context == ExpressionContext.Expression"); + Check.DebugAssert(_context == ExpressionContext.Expression); var translatedList = new ExpressionSyntax[list.Count]; var lastLiftedArgumentPosition = 0; diff --git a/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs b/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs index d11cf7f07f2..954e7218fea 100644 --- a/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs +++ b/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs @@ -173,7 +173,7 @@ public virtual IReadOnlyList GeneratePrecompiledQueries( var penultimateOperator = terminatingOperator switch { // This is needed e.g. for GetEnumerator(), DbSet.AsAsyncEnumerable (non-static terminating operators) - { Object: Expression @object } => @object, + { Object: { } @object } => @object, { Arguments: [var sourceArgument, ..] } => sourceArgument, _ => throw new UnreachableException() }; @@ -284,13 +284,12 @@ public virtual IReadOnlyList GeneratePrecompiledQueries( ]); foreach (var ns in _namespaces - .OrderBy( - ns => ns switch - { - _ when ns.StartsWith("System.", StringComparison.Ordinal) => 10, - _ when ns.StartsWith("Microsoft.", StringComparison.Ordinal) => 9, - _ => 0 - }) + .OrderBy(ns => ns switch + { + _ when ns.StartsWith("System.", StringComparison.Ordinal) => 10, + _ when ns.StartsWith("Microsoft.", StringComparison.Ordinal) => 9, + _ => 0 + }) .ThenBy(ns => ns)) { _code.Append("using ").Append(ns).AppendLine(";"); @@ -398,7 +397,7 @@ private void GenerateOperatorInterceptorsRecursively( var nestedOperatorExpression = operatorMethodCall switch { // This is needed e.g. for GetEnumerator(), DbSet.AsAsyncEnumerable (non-static terminating operators) - { Object: Expression @object } => @object, + { Object: { } @object } => @object, { Arguments: [var sourceArgument, ..] } => sourceArgument, _ => throw new UnreachableException() }; @@ -489,10 +488,9 @@ private void GenerateOperatorInterceptor( IArrayTypeSymbol arrayTypeSymbol => arrayTypeSymbol.ElementType, INamedTypeSymbol namedReturnType2 when namedReturnType2.AllInterfaces.Prepend(namedReturnType2) - .Any( - i => i.OriginalDefinition.Equals(_symbols.GenericEnumerable, SymbolEqualityComparer.Default) - || i.OriginalDefinition.Equals(_symbols.GenericAsyncEnumerable, SymbolEqualityComparer.Default) - || i.OriginalDefinition.Equals(_symbols.GenericEnumerator, SymbolEqualityComparer.Default)) + .Any(i => i.OriginalDefinition.Equals(_symbols.GenericEnumerable, SymbolEqualityComparer.Default) + || i.OriginalDefinition.Equals(_symbols.GenericAsyncEnumerable, SymbolEqualityComparer.Default) + || i.OriginalDefinition.Equals(_symbols.GenericEnumerator, SymbolEqualityComparer.Default)) => namedReturnType2.TypeArguments[0], _ => null }; @@ -767,7 +765,8 @@ or nameof(EntityFrameworkQueryableExtensions.ExecuteUpdateAsync), // If there were captured variables, generate code to evaluate and build the same NewArrayExpression at runtime, // and then fall through to the normal logic, generating variable extractors against that NewArrayExpression // (local var) instead of against the method argument. - code.AppendLine($""" + code.AppendLine( + $""" var setterBuilder = new UpdateSettersBuilder<{sourceElementTypeName}>(); {parameterName}(setterBuilder); var setters = setterBuilder.BuildSettersExpression(); @@ -854,7 +853,8 @@ void GenerateCapturedVariableExtractors( { code .Append('"').Append(capturedVariablesPathTree.ParameterName!).AppendLine("\",") - .AppendLine($"Expression.Lambda>(Expression.Convert({roslynPathSegment}, typeof(object)))") + .AppendLine( + $"Expression.Lambda>(Expression.Convert({roslynPathSegment}, typeof(object)))") .AppendLine(".Compile(preferInterpretation: true)") .AppendLine(".Invoke());"); } @@ -869,8 +869,7 @@ void GenerateCapturedVariableExtractors( // side we have a query root (i.e. not the MethodCallExpression for the FromSql(), but rather its evaluated result) case FromSqlQueryRootExpression fromSqlQueryRoot: { - if (_funcletizer.CalculatePathsToEvaluatableRoots(fromSqlQueryRoot.Argument) is not ExpressionTreeFuncletizer.PathNode - evaluatableRootPaths) + if (_funcletizer.CalculatePathsToEvaluatableRoots(fromSqlQueryRoot.Argument) is not { } evaluatableRootPaths) { // There are no captured variables in this FromSqlQueryRootExpression, skip it. break; @@ -1134,7 +1133,7 @@ or nameof(EntityFrameworkQueryableExtensions.ToListAsync) _ => terminatingOperator switch { // This is needed e.g. for GetEnumerator(), DbSet.AsAsyncEnumerable (non-static terminating operators) - { Object: Expression } + { Object: not null } => terminatingOperator.Update(penultimateOperator, terminatingOperator.Arguments), { Arguments: [_, ..] } => terminatingOperator.Update(@object: null, [penultimateOperator, .. terminatingOperator.Arguments.Skip(1)]), @@ -1183,8 +1182,7 @@ private static NewArrayExpression ProcessExecuteUpdate(MethodCallExpression exec }, Arguments: [ - UnaryExpression { NodeType: ExpressionType.Quote, Operand: LambdaExpression propertySelector }, - Expression valueSelector + UnaryExpression { NodeType: ExpressionType.Quote, Operand: LambdaExpression propertySelector }, { } valueSelector ] } methodCallExpression && methodCallExpression.Method.DeclaringType.GetGenericTypeDefinition() == typeof(UpdateSettersBuilder<>)) diff --git a/src/EFCore.Design/Query/Internal/QueryLocator.cs b/src/EFCore.Design/Query/Internal/QueryLocator.cs index 4e30a445f55..72b47450ab6 100644 --- a/src/EFCore.Design/Query/Internal/QueryLocator.cs +++ b/src/EFCore.Design/Query/Internal/QueryLocator.cs @@ -81,7 +81,7 @@ public virtual IReadOnlyList LocateQueries( _cancellationToken = cancellationToken; _semanticModel = _compilation.GetSemanticModel(syntaxTree); - _locatedQueries = new List(); + _locatedQueries = []; _precompilationErrors = precompilationErrors; Visit(syntaxTree.GetRoot(cancellationToken)); diff --git a/src/EFCore.Design/Query/Internal/RuntimeModelLinqToCSharpSyntaxTranslator.cs b/src/EFCore.Design/Query/Internal/RuntimeModelLinqToCSharpSyntaxTranslator.cs index 06ef309ed3d..e8a0c1bbd11 100644 --- a/src/EFCore.Design/Query/Internal/RuntimeModelLinqToCSharpSyntaxTranslator.cs +++ b/src/EFCore.Design/Query/Internal/RuntimeModelLinqToCSharpSyntaxTranslator.cs @@ -104,7 +104,7 @@ protected override void TranslateNonPublicMemberAccess(MemberExpression memberEx AddNamespace(methodName.Namespace); Result = InvocationExpression( IdentifierName(methodName.Name), - ArgumentList(SeparatedList(new[] { Argument(Translate(memberExpression.Expression)) }))); + ArgumentList(SeparatedList([Argument(Translate(memberExpression.Expression))]))); } else { @@ -139,11 +139,10 @@ protected override void TranslateNonPublicMemberAssignment( IdentifierName(methodName.Name), ArgumentList( SeparatedList( - new[] - { - Argument(Translate(memberExpression.Expression)), - Argument(Translate(value)) - }))); + [ + Argument(Translate(memberExpression.Expression)), + Argument(Translate(value)) + ]))); } else { @@ -151,7 +150,7 @@ protected override void TranslateNonPublicMemberAssignment( assignmentKind, InvocationExpression( IdentifierName(methodName.Name), - ArgumentList(SeparatedList(new[] { Argument(Translate(memberExpression.Expression)) }))), + ArgumentList(SeparatedList([Argument(Translate(memberExpression.Expression))]))), Translate(value)); } } diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs index 8415a2c8052..07dbde06d0b 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs @@ -1312,7 +1312,8 @@ private void Create( private void Create(IElementType elementType, bool typeMappingSet, CSharpRuntimeAnnotationCodeGeneratorParameters parameters) { var mainBuilder = parameters.MainBuilder; - var elementVariableName = _code.Identifier(parameters.TargetName + "ElementType", elementType, parameters.ScopeObjects, capitalize: false); + var elementVariableName = _code.Identifier( + parameters.TargetName + "ElementType", elementType, parameters.ScopeObjects, capitalize: false); var elementParameters = parameters with { TargetName = elementVariableName }; mainBuilder @@ -1447,7 +1448,7 @@ private void SetValueComparer( { var mainBuilder = parameters.MainBuilder; var valueComparerType = valueComparer.GetType(); - if (valueComparer is IInfrastructure { Instance: ValueComparer underlyingValueComparer } + if (valueComparer is IInfrastructure { Instance: var underlyingValueComparer } && typeMappingComparer == underlyingValueComparer && valueComparerType.GetDeclaredConstructor([typeof(ValueComparer)]) != null) { @@ -1517,14 +1518,17 @@ private void .AppendLines( _code.Expression( getClrValueUsingContainingEntityExpression, parameters.Namespaces, unsafeAccessors, - (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), skipFinalNewline: true) + (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), + skipFinalNewline: true) .AppendLine(",") .AppendLines( _code.Expression( hasSentinelValueUsingContainingEntityExpression, parameters.Namespaces, unsafeAccessors, - (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), skipFinalNewline: true) + (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), + skipFinalNewline: true) .AppendLine(","); } + mainBuilder .AppendLines( _code.Expression( @@ -1549,9 +1553,11 @@ private void .AppendLines( _code.Expression( setterUsingContainingEntityExpression, parameters.Namespaces, unsafeAccessors, - (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), skipFinalNewline: true) + (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), + skipFinalNewline: true) .AppendLine(","); } + mainBuilder .AppendLines( _code.Expression( @@ -1560,7 +1566,8 @@ private void .AppendLine(");") .DecrementIndent(); - ClrPropertyMaterializationSetterFactory.Instance.Create(property, out var materializationSetterUsingContainingEntityExpression, out var materializationSetterExpression); + ClrPropertyMaterializationSetterFactory.Instance.Create( + property, out var materializationSetterUsingContainingEntityExpression, out var materializationSetterExpression); mainBuilder .Append(variableName).AppendLine(".SetMaterializationSetter(") @@ -1571,9 +1578,11 @@ private void .AppendLines( _code.Expression( materializationSetterUsingContainingEntityExpression, parameters.Namespaces, unsafeAccessors, - (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), skipFinalNewline: true) + (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), + skipFinalNewline: true) .AppendLine(","); } + mainBuilder .AppendLines( _code.Expression( @@ -1596,22 +1605,26 @@ private void .AppendLines( _code.Expression( get!, parameters.Namespaces, unsafeAccessors, - (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), skipFinalNewline: true) + (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), + skipFinalNewline: true) .AppendLine(",") .AppendLines( _code.Expression( set!, parameters.Namespaces, unsafeAccessors, - (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), skipFinalNewline: true) + (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), + skipFinalNewline: true) .AppendLine(",") .AppendLines( _code.Expression( setForMaterialization!, parameters.Namespaces, unsafeAccessors, - (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), skipFinalNewline: true) + (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), + skipFinalNewline: true) .AppendLine(",") .AppendLines( _code.Expression( createCollection!, parameters.Namespaces, unsafeAccessors, - (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), skipFinalNewline: true) + (IReadOnlyDictionary)parameters.ScopeVariables, memberAccessReplacements), + skipFinalNewline: true) .AppendLine(");") .DecrementIndent(); } @@ -3023,8 +3036,7 @@ private static void CreateAnnotations( annotatable, parameters with { - Annotations = annotatable.GetRuntimeAnnotations().ToDictionary(a => a.Name, a => a.Value), - IsRuntime = true + Annotations = annotatable.GetRuntimeAnnotations().ToDictionary(a => a.Name, a => a.Value), IsRuntime = true }); } diff --git a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs index 4813ef420f6..4b78e52a29b 100644 --- a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs @@ -185,8 +185,7 @@ protected virtual ModelBuilder VisitDatabaseModel(ModelBuilder modelBuilder, Dat VisitForeignKeys(modelBuilder, databaseModel.Tables.SelectMany(table => table.ForeignKeys).ToList()); modelBuilder.Model.AddAnnotations( - databaseModel.GetAnnotations().Where( - a => a.Name != ScaffoldingAnnotationNames.ConnectionString)); + databaseModel.GetAnnotations().Where(a => a.Name != ScaffoldingAnnotationNames.ConnectionString)); return modelBuilder; } @@ -503,9 +502,8 @@ protected virtual EntityTypeBuilder VisitColumns(EntityTypeBuilder builder, ICol property.Metadata.SetColumnOrder(column.Table.Columns.IndexOf(column)); property.Metadata.AddAnnotations( - column.GetAnnotations().Where( - a => a.Name != ScaffoldingAnnotationNames.ConcurrencyToken - && a.Name != ScaffoldingAnnotationNames.ClrType)); + column.GetAnnotations().Where(a => a.Name != ScaffoldingAnnotationNames.ConcurrencyToken + && a.Name != ScaffoldingAnnotationNames.ClrType)); return property; } @@ -814,8 +812,7 @@ protected virtual ModelBuilder VisitForeignKeys( } var principalPropertiesMap = foreignKey.PrincipalColumns - .Select( - fc => (property: principalEntityType.FindProperty(GetPropertyName(fc))!, column: fc)).ToList(); + .Select(fc => (property: principalEntityType.FindProperty(GetPropertyName(fc))!, column: fc)).ToList(); var principalProperties = principalPropertiesMap .Select(tuple => tuple.property) .ToList(); diff --git a/src/EFCore.Design/Scaffolding/Internal/TextTemplatingEngineHost.cs b/src/EFCore.Design/Scaffolding/Internal/TextTemplatingEngineHost.cs index 8a78e882446..db5732d36c0 100644 --- a/src/EFCore.Design/Scaffolding/Internal/TextTemplatingEngineHost.cs +++ b/src/EFCore.Design/Scaffolding/Internal/TextTemplatingEngineHost.cs @@ -55,10 +55,10 @@ public virtual ITextTemplatingSession Session /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual IList StandardAssemblyReferences { get; } = new[] - { + public virtual IList StandardAssemblyReferences { get; } = + [ typeof(ITextTemplatingEngineHost).Assembly.Location, typeof(CompilerErrorCollection).Assembly.Location - }; + ]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -66,7 +66,7 @@ public virtual ITextTemplatingSession Session /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual IList StandardImports { get; } = new[] { "System" }; + public virtual IList StandardImports { get; } = ["System"]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Design/build/net10.0/Microsoft.EntityFrameworkCore.Design.props b/src/EFCore.Design/build/net10.0/Microsoft.EntityFrameworkCore.Design.props index affac16f65b..4969df90e3d 100644 --- a/src/EFCore.Design/build/net10.0/Microsoft.EntityFrameworkCore.Design.props +++ b/src/EFCore.Design/build/net10.0/Microsoft.EntityFrameworkCore.Design.props @@ -2,4 +2,4 @@ True - + \ No newline at end of file diff --git a/src/EFCore.InMemory/Extensions/InMemoryServiceCollectionExtensions.cs b/src/EFCore.InMemory/Extensions/InMemoryServiceCollectionExtensions.cs index d3d50a93eb0..11d0208a0f5 100644 --- a/src/EFCore.InMemory/Extensions/InMemoryServiceCollectionExtensions.cs +++ b/src/EFCore.InMemory/Extensions/InMemoryServiceCollectionExtensions.cs @@ -49,13 +49,12 @@ public static IServiceCollection AddEntityFrameworkInMemoryDatabase(this IServic .TryAdd() .TryAdd() .TryAdd(p => p.GetRequiredService()) - .TryAddProviderSpecificServices( - b => b - .TryAddSingleton() - .TryAddScoped() - .TryAddSingleton() - .TryAddSingleton() - .TryAddScoped()); + .TryAddProviderSpecificServices(b => b + .TryAddSingleton() + .TryAddScoped() + .TryAddSingleton() + .TryAddSingleton() + .TryAddScoped()); builder.TryAddCoreServices(); diff --git a/src/EFCore.InMemory/Metadata/Conventions/InMemoryConventionSetBuilder.cs b/src/EFCore.InMemory/Metadata/Conventions/InMemoryConventionSetBuilder.cs index 7bfad928af8..f53c7ebeec6 100644 --- a/src/EFCore.InMemory/Metadata/Conventions/InMemoryConventionSetBuilder.cs +++ b/src/EFCore.InMemory/Metadata/Conventions/InMemoryConventionSetBuilder.cs @@ -76,10 +76,9 @@ private static IServiceScope CreateServiceScope() { var serviceProvider = new ServiceCollection() .AddEntityFrameworkInMemoryDatabase() - .AddDbContext( - (p, o) => - o.UseInMemoryDatabase(Guid.NewGuid().ToString()) - .UseInternalServiceProvider(p)) + .AddDbContext((p, o) => + o.UseInMemoryDatabase(Guid.NewGuid().ToString()) + .UseInternalServiceProvider(p)) .BuildServiceProvider(); return serviceProvider.GetRequiredService().CreateScope(); diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs index 9ccba1f9659..fdc860cdc25 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; using JetBrains.Annotations; @@ -369,8 +370,7 @@ private static bool TryUseComparer( foreach (var candidate in comparer .GetType() .GetMethods(BindingFlags.Public | BindingFlags.Instance) - .Where( - m => m.Name == "Equals" && m.GetParameters().Length == 2) + .Where(m => m.Name == "Equals" && m.GetParameters().Length == 2) .ToList()) { var parameters = candidate.GetParameters(); @@ -553,7 +553,7 @@ protected override Expression VisitMember(MemberExpression memberExpression) return QueryCompilationContext.NotTranslatedExpression; } - if (TryBindMember(innerExpression, MemberIdentity.Create(memberExpression.Member), memberExpression.Type) is Expression result) + if (TryBindMember(innerExpression, MemberIdentity.Create(memberExpression.Member), memberExpression.Type) is { } result) { return result; } @@ -928,7 +928,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp // Null-compensate any extension method where the 'this' argument is a reference type // (in theory should do this for value types as well, but that's more complicated as the expression type needs to be changed etc.) if (methodCallExpression is { Object: null, Method: { IsStatic: true } staticMethod } - && staticMethod.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), inherit: false) + && staticMethod.IsDefined(typeof(ExtensionAttribute), inherit: false) && arguments is [{ Type.IsValueType: false } instance, ..]) { return Expression.Condition( @@ -1206,7 +1206,7 @@ private static Expression ProcessSingleResultScalar( var valueBufferVariable = Expression.Variable(typeof(ValueBuffer)); var readExpression = valueBufferVariable.CreateValueBufferReadValueExpression(type, index: 0, property: null); return Expression.Block( - variables: new[] { valueBufferVariable }, + variables: [valueBufferVariable], Expression.Assign(valueBufferVariable, serverQuery), Expression.Condition( Expression.MakeMemberAccess(valueBufferVariable, ValueBufferIsEmpty), @@ -1366,11 +1366,10 @@ private bool TryRewriteEntityEquality( } result = Visit( - primaryKeyProperties1.Select( - p => - Expression.MakeBinary( - nodeType, CreatePropertyAccessExpression(nonNullEntityReference, p), - Expression.Constant(null, p.ClrType.MakeNullable()))) + primaryKeyProperties1.Select(p => + Expression.MakeBinary( + nodeType, CreatePropertyAccessExpression(nonNullEntityReference, p), + Expression.Constant(null, p.ClrType.MakeNullable()))) .Aggregate((l, r) => nodeType == ExpressionType.Equal ? Expression.OrElse(l, r) : Expression.AndAlso(l, r))); return true; @@ -1418,16 +1417,14 @@ private bool TryRewriteEntityEquality( } result = Visit( - primaryKeyProperties.Select( - p => - Expression.MakeBinary( - nodeType, - CreatePropertyAccessExpression(left, p), - CreatePropertyAccessExpression(right, p))) - .Aggregate( - (l, r) => nodeType == ExpressionType.Equal - ? Expression.AndAlso(l, r) - : Expression.OrElse(l, r))); + primaryKeyProperties.Select(p => + Expression.MakeBinary( + nodeType, + CreatePropertyAccessExpression(left, p), + CreatePropertyAccessExpression(right, p))) + .Aggregate((l, r) => nodeType == ExpressionType.Equal + ? Expression.AndAlso(l, r) + : Expression.OrElse(l, r))); return true; } @@ -1459,8 +1456,8 @@ when methodCallExpression.Method.GetGenericMethodDefinition() == GetParameterVal return _queryCompilationContext.RegisterRuntimeParameter(newParameterName, lambda); case MemberInitExpression memberInitExpression - when memberInitExpression.Bindings.SingleOrDefault( - mb => mb.Member.Name == property.Name) is MemberAssignment memberAssignment: + when memberInitExpression.Bindings.SingleOrDefault(mb => mb.Member.Name == property.Name) is MemberAssignment + memberAssignment: return memberAssignment.Expression.Type.IsNullableType() ? memberAssignment.Expression : Expression.Convert(memberAssignment.Expression, property.ClrType.MakeNullable()); @@ -1519,8 +1516,8 @@ private static bool CanEvaluate(Expression expression) case MemberInitExpression memberInitExpression: return CanEvaluate(memberInitExpression.NewExpression) - && memberInitExpression.Bindings.All( - mb => mb is MemberAssignment memberAssignment && CanEvaluate(memberAssignment.Expression)); + && memberInitExpression.Bindings.All(mb + => mb is MemberAssignment memberAssignment && CanEvaluate(memberAssignment.Expression)); default: return false; @@ -1719,7 +1716,7 @@ public Expression Convert(Type type) } return StructuralType is IEntityType entityType - && entityType.GetDerivedTypes().FirstOrDefault(et => et.ClrType == type) is IEntityType derivedEntityType + && entityType.GetDerivedTypes().FirstOrDefault(et => et.ClrType == type) is { } derivedEntityType ? new StructuralTypeReferenceExpression(this, derivedEntityType) : QueryCompilationContext.NotTranslatedExpression; } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs index ba7120441e1..7fb56232687 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs @@ -76,10 +76,9 @@ public InMemoryQueryExpression(IEntityType entityType) foreach (var derivedEntityType in entityType.GetDerivedTypes()) { var entityCheck = derivedEntityType.GetConcreteDerivedTypesInclusive() - .Select( - e => keyValueComparer.ExtractEqualsBody( - propertyExpressionsMap[discriminatorProperty], - Constant(e.GetDiscriminatorValue(), discriminatorProperty.ClrType))) + .Select(e => keyValueComparer.ExtractEqualsBody( + propertyExpressionsMap[discriminatorProperty], + Constant(e.GetDiscriminatorValue(), discriminatorProperty.ClrType))) .Aggregate((l, r) => OrElse(l, r)); foreach (var property in derivedEntityType.GetDeclaredProperties()) @@ -469,19 +468,20 @@ public virtual void ApplyDefaultIfEmpty() ServerQueryExpression, Constant(new ValueBuffer(Enumerable.Repeat((object?)null, _projectionMappingExpressions.Count).ToArray()))); - ReplaceProjection(_projectionMapping.ToDictionary( - kv => kv.Key, - kv => kv.Value switch - { - EntityProjectionExpression p => MakeEntityProjectionNullable(p), + ReplaceProjection( + _projectionMapping.ToDictionary( + kv => kv.Key, + kv => kv.Value switch + { + EntityProjectionExpression p => MakeEntityProjectionNullable(p), - var p when !p.Type.IsNullableType() - => Coalesce( - MakeReadValueNullable(p), - p.Type.GetDefaultValueConstant()), + var p when !p.Type.IsNullableType() + => Coalesce( + MakeReadValueNullable(p), + p.Type.GetDefaultValueConstant()), - var p => p - })); + var p => p + })); } /// @@ -667,8 +667,8 @@ public virtual StructuralTypeShaperExpression AddNavigationToWeakEntityType( var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(ValueBuffer), "inner"); var replacingVisitor = new ReplacingExpressionVisitor( - new Expression[] { CurrentParameter, innerQueryExpression.CurrentParameter }, - new Expression[] { outerParameter, innerParameter }); + [CurrentParameter, innerQueryExpression.CurrentParameter], + [outerParameter, innerParameter]); var selectorExpressions = _projectionMappingExpressions.Select(e => replacingVisitor.Visit(e)).ToList(); var outerIndex = selectorExpressions.Count; @@ -912,8 +912,8 @@ private Expression AddJoin( var outerParameter = Parameter(typeof(ValueBuffer), "outer"); var innerParameter = Parameter(typeof(ValueBuffer), "inner"); var replacingVisitor = new ReplacingExpressionVisitor( - new Expression[] { CurrentParameter, innerQueryExpression.CurrentParameter }, - new Expression[] { outerParameter, innerParameter }); + [CurrentParameter, innerQueryExpression.CurrentParameter], + [outerParameter, innerParameter]); int outerIndex; if (outerClientEval) @@ -1030,23 +1030,22 @@ private Expression AddJoin( New( ValueBufferConstructor, NewArrayInit( typeof(object), - resultSelectorExpressions.Select( - (e, i) => + resultSelectorExpressions.Select((e, i) => + { + var expression = replacingVisitor.Visit(e); + if (innerNullable + && i > outerIndex) + { + expression = MakeReadValueNullable(expression); + } + + if (expression.Type.IsValueType) { - var expression = replacingVisitor.Visit(e); - if (innerNullable - && i > outerIndex) - { - expression = MakeReadValueNullable(expression); - } - - if (expression.Type.IsValueType) - { - expression = Convert(expression, typeof(object)); - } - - return expression; - }))), + expression = Convert(expression, typeof(object)); + } + + return expression; + }))), outerParameter, innerParameter); @@ -1116,7 +1115,7 @@ private Expression AddJoin( return New( transparentIdentifierType.GetTypeInfo().DeclaredConstructors.Single(), - new[] { outerShaperExpression, innerShaperExpression }, outerMemberInfo, innerMemberInfo); + [outerShaperExpression, innerShaperExpression], outerMemberInfo, innerMemberInfo); static Expression MakeNullable(Expression expression, bool nullable) => nullable diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs index a64883aaf3f..8a5af0166fb 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs @@ -383,8 +383,8 @@ private static ShapedQueryExpression CreateShapedQueryExpressionStatic(IEntityTy var original2 = resultSelector.Parameters[1]; var newResultSelectorBody = new ReplacingExpressionVisitor( - new Expression[] { original1, original2 }, - new[] { groupByShaper.KeySelector, groupByShaper }).Visit(resultSelector.Body); + [original1, original2], + [groupByShaper.KeySelector, groupByShaper]).Visit(resultSelector.Body); newResultSelectorBody = ExpandSharedTypeEntities(inMemoryQueryExpression, newResultSelectorBody); var newShaper = _projectionBindingExpressionVisitor.Translate(inMemoryQueryExpression, newResultSelectorBody); @@ -1162,12 +1162,14 @@ protected override Expression VisitMember(MemberExpression memberExpression) { // Fold member access into conditional, i.e. transform // (test ? expr1 : expr2).Member -> (test ? expr1.Member : expr2.Member) - if (memberExpression.Expression is ConditionalExpression cond) { - return Visit(Expression.Condition( - cond.Test, - Expression.MakeMemberAccess(cond.IfTrue, memberExpression.Member), - Expression.MakeMemberAccess(cond.IfFalse, memberExpression.Member) - )); + if (memberExpression.Expression is ConditionalExpression cond) + { + return Visit( + Expression.Condition( + cond.Test, + Expression.MakeMemberAccess(cond.IfTrue, memberExpression.Member), + Expression.MakeMemberAccess(cond.IfFalse, memberExpression.Member) + )); } var innerExpression = Visit(memberExpression.Expression); @@ -1183,7 +1185,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp source = Visit(source); return TryExpand(source, MemberIdentity.Create(navigationName)) - ?? methodCallExpression.Update(null!, new[] { source, methodCallExpression.Arguments[1] }); + ?? methodCallExpression.Update(null!, [source, methodCallExpression.Arguments[1]]); } return base.VisitMethodCall(methodCallExpression); @@ -1264,13 +1266,12 @@ protected override Expression VisitExtension(Expression extensionExpression) ? Expression.AndAlso( outerKey is NewArrayExpression newArrayExpression ? newArrayExpression.Expressions - .Select( - e => - { - var left = (e as UnaryExpression)?.Operand ?? e; + .Select(e => + { + var left = (e as UnaryExpression)?.Operand ?? e; - return Expression.NotEqual(left, Expression.Constant(null, left.Type)); - }) + return Expression.NotEqual(left, Expression.Constant(null, left.Type)); + }) .Aggregate((l, r) => Expression.AndAlso(l, r)) : Expression.NotEqual(outerKey, Expression.Constant(null, outerKey.Type)), keyComparison) @@ -1341,7 +1342,7 @@ private ShapedQueryExpression TranslateTwoParameterSelector(ShapedQueryExpressio var replacement2 = AccessField(transparentIdentifierType, transparentIdentifierParameter, "Inner"); var newResultSelector = Expression.Lambda( new ReplacingExpressionVisitor( - new[] { original1, original2 }, new[] { replacement1, replacement2 }) + [original1, original2], [replacement1, replacement2]) .Visit(resultSelector.Body), transparentIdentifierParameter); diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.ShaperExpressionProcessingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.ShaperExpressionProcessingExpressionVisitor.cs index 7f435655384..0a7c964f4f6 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.ShaperExpressionProcessingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryCompilingExpressionVisitor.ShaperExpressionProcessingExpressionVisitor.cs @@ -215,7 +215,7 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) = queryExpression.GetProjection(projectionBindingExpression).GetConstantValue>(); var updatedExpression = newExpression.Update( - new[] { Constant(ValueBuffer.Empty), newExpression.Arguments[1] }); + [Constant(ValueBuffer.Empty), newExpression.Arguments[1]]); return MakeBinary(ExpressionType.Assign, binaryExpression.Left, updatedExpression); } diff --git a/src/EFCore.InMemory/Storage/Internal/InMemoryStoreProvider.cs b/src/EFCore.InMemory/Storage/Internal/InMemoryStoreProvider.cs index 0f8ea7b1ced..7ccaac07cad 100644 --- a/src/EFCore.InMemory/Storage/Internal/InMemoryStoreProvider.cs +++ b/src/EFCore.InMemory/Storage/Internal/InMemoryStoreProvider.cs @@ -24,7 +24,10 @@ public class InMemoryStoreProvider : IInMemoryStoreProvider /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public InMemoryStoreProvider(IDbContextOptions options, IInMemoryDatabaseRootCache databaseRootCache, IInMemoryTableFactory tableFactory) + public InMemoryStoreProvider( + IDbContextOptions options, + IInMemoryDatabaseRootCache databaseRootCache, + IInMemoryTableFactory tableFactory) { _options = options; _databaseRootCache = databaseRootCache; diff --git a/src/EFCore.InMemory/Storage/Internal/InMemoryTable.cs b/src/EFCore.InMemory/Storage/Internal/InMemoryTable.cs index fb3b097285f..c5a3d5a6750 100644 --- a/src/EFCore.InMemory/Storage/Internal/InMemoryTable.cs +++ b/src/EFCore.InMemory/Storage/Internal/InMemoryTable.cs @@ -385,7 +385,7 @@ private static bool IsNullable(IProperty property) private static bool IsNullable(IComplexProperty property) => property.IsNullable - ||( property.DeclaringType is IComplexType complexType + || (property.DeclaringType is IComplexType complexType && IsNullable(complexType.ComplexProperty)); private void ThrowNullabilityErrorException( @@ -399,14 +399,14 @@ private void ThrowNullabilityErrorException( nullabilityErrors.Format(), entry.EntityType.DisplayName(), entry.BuildCurrentValuesString(entry.EntityType.FindPrimaryKey()!.Properties)), - new[] { entry }); + [entry]); } throw new DbUpdateException( InMemoryStrings.NullabilityErrorException( nullabilityErrors.Format(), entry.EntityType.DisplayName()), - new[] { entry }); + [entry]); } /// @@ -432,8 +432,7 @@ protected virtual void ThrowUpdateConcurrencyException( "{" + string.Join( ", ", - concurrencyConflicts.Select( - c => c.Key.Name + ": " + Convert.ToString(c.Value, CultureInfo.InvariantCulture))) + concurrencyConflicts.Select(c => c.Key.Name + ": " + Convert.ToString(c.Value, CultureInfo.InvariantCulture))) + "}"), entries) : new DbUpdateConcurrencyException( diff --git a/src/EFCore.Proxies/Proxies/Internal/IProxyLazyLoader.cs b/src/EFCore.Proxies/Proxies/Internal/IProxyLazyLoader.cs index 442d9360b63..8c3295364e1 100644 --- a/src/EFCore.Proxies/Proxies/Internal/IProxyLazyLoader.cs +++ b/src/EFCore.Proxies/Proxies/Internal/IProxyLazyLoader.cs @@ -20,7 +20,6 @@ public interface IProxyLazyLoader /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - [IgnoreDataMember] - [JsonIgnore] + [IgnoreDataMember, JsonIgnore] ILazyLoader? LazyLoader { get; set; } } diff --git a/src/EFCore.Proxies/ProxiesServiceCollectionExtensions.cs b/src/EFCore.Proxies/ProxiesServiceCollectionExtensions.cs index 3b3a0707893..31b0a872098 100644 --- a/src/EFCore.Proxies/ProxiesServiceCollectionExtensions.cs +++ b/src/EFCore.Proxies/ProxiesServiceCollectionExtensions.cs @@ -31,8 +31,7 @@ public static IServiceCollection AddEntityFrameworkProxies( new EntityFrameworkServicesBuilder(serviceCollection) .TryAdd() .TryAdd() - .TryAddProviderSpecificServices( - b => b.TryAddSingleton()); + .TryAddProviderSpecificServices(b => b.TryAddSingleton()); return serviceCollection; } diff --git a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs index f69dae85b38..b3c1718ea06 100644 --- a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs @@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; -using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; #pragma warning disable EF1001 // Accessing annotation names (internal) @@ -55,9 +54,8 @@ public AnnotationCodeGenerator(AnnotationCodeGeneratorDependencies dependencies) /// public virtual IEnumerable FilterIgnoredAnnotations(IEnumerable annotations) - => annotations.Where( - a => !(CoreAnnotationNames.AllNames.Contains(a.Name) - || IgnoredRelationalAnnotations.Contains(a.Name))); + => annotations.Where(a => !(CoreAnnotationNames.AllNames.Contains(a.Name) + || IgnoredRelationalAnnotations.Contains(a.Name))); /// public virtual void RemoveAnnotationsHandledByConventions(IModel model, IDictionary annotations) @@ -376,7 +374,8 @@ public virtual IReadOnlyList GenerateFluentApiCalls( GenerateSimpleFluentApiCall( annotations, - RelationalAnnotationNames.JsonPropertyName, nameof(RelationalPropertyBuilderExtensions.HasJsonPropertyName), methodCallCodeFragments); + RelationalAnnotationNames.JsonPropertyName, nameof(RelationalPropertyBuilderExtensions.HasJsonPropertyName), + methodCallCodeFragments); GenerateSimpleFluentApiCall( annotations, @@ -400,7 +399,8 @@ public virtual IReadOnlyList GenerateFluentApiCalls( GenerateSimpleFluentApiCall( annotations, - RelationalAnnotationNames.JsonPropertyName, nameof(RelationalComplexPropertyBuilderExtensions.HasJsonPropertyName), methodCallCodeFragments); + RelationalAnnotationNames.JsonPropertyName, nameof(RelationalComplexPropertyBuilderExtensions.HasJsonPropertyName), + methodCallCodeFragments); methodCallCodeFragments.AddRange(GenerateFluentApiCallsHelper(complexProperty, annotations, GenerateFluentApi)); @@ -1051,7 +1051,7 @@ private static void GenerateSimpleFluentApiCall( if (annotations.TryGetValue(annotationName, out var annotation)) { annotations.Remove(annotationName); - if (annotation.Value is object annotationValue) + if (annotation.Value is { } annotationValue) { methodCallCodeFragments.Add( new MethodCallCodeFragment(method, annotationValue)); diff --git a/src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs index a521fa01210..ed97fd13171 100644 --- a/src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs @@ -66,7 +66,7 @@ public override void Generate(IModel model, CSharpRuntimeAnnotationCodeGenerator if (annotations.TryGetAndRemove( RelationalAnnotationNames.DbFunctions, - out IReadOnlyDictionary functions)) + out IReadOnlyDictionary? functions)) { parameters.Namespaces.Add(typeof(Dictionary<,>).Namespace!); parameters.Namespaces.Add(typeof(BindingFlags).Namespace!); @@ -85,7 +85,7 @@ public override void Generate(IModel model, CSharpRuntimeAnnotationCodeGenerator if (annotations.TryGetAndRemove( RelationalAnnotationNames.Sequences, - out IReadOnlyDictionary<(string, string?), ISequence> sequences)) + out IReadOnlyDictionary<(string, string?), ISequence>? sequences)) { parameters.Namespaces.Add(typeof(Dictionary<,>).Namespace!); var sequencesVariable = Dependencies.CSharpHelper.Identifier( @@ -1611,7 +1611,7 @@ private void Create( AddNamespace(method.DeclaringType!, parameters.Namespaces); mainBuilder.AppendLine(",") .AppendLine($"methodInfo: {code.Literal(method.DeclaringType!)}.GetMethod(").IncrementIndent() - .Append(code.Literal(method.Name!)).AppendLine(",") + .Append(code.Literal(method.Name)).AppendLine(",") .Append(method.IsPublic ? "BindingFlags.Public" : "BindingFlags.NonPublic") .Append(method.IsStatic ? " | BindingFlags.Static" : " | BindingFlags.Instance") .AppendLine(" | BindingFlags.DeclaredOnly,") @@ -1825,7 +1825,7 @@ public override void Generate(IEntityType entityType, CSharpRuntimeAnnotationCod if (annotations.TryGetAndRemove( RelationalAnnotationNames.MappingFragments, - out IReadOnlyStoreObjectDictionary fragments)) + out IReadOnlyStoreObjectDictionary? fragments)) { AddNamespace(typeof(StoreObjectDictionary), parameters.Namespaces); AddNamespace(typeof(StoreObjectIdentifier), parameters.Namespaces); @@ -1845,7 +1845,7 @@ public override void Generate(IEntityType entityType, CSharpRuntimeAnnotationCod if (annotations.TryGetAndRemove( RelationalAnnotationNames.InsertStoredProcedure, - out StoredProcedure insertStoredProcedure)) + out StoredProcedure? insertStoredProcedure)) { var sprocVariable = Dependencies.CSharpHelper.Identifier( "insertSproc", insertStoredProcedure, parameters.ScopeObjects, capitalize: false); @@ -1858,7 +1858,7 @@ public override void Generate(IEntityType entityType, CSharpRuntimeAnnotationCod if (annotations.TryGetAndRemove( RelationalAnnotationNames.DeleteStoredProcedure, - out StoredProcedure deleteStoredProcedure)) + out StoredProcedure? deleteStoredProcedure)) { var sprocVariable = Dependencies.CSharpHelper.Identifier( "deleteSproc", deleteStoredProcedure, parameters.ScopeObjects, capitalize: false); @@ -1871,7 +1871,7 @@ public override void Generate(IEntityType entityType, CSharpRuntimeAnnotationCod if (annotations.TryGetAndRemove( RelationalAnnotationNames.UpdateStoredProcedure, - out StoredProcedure updateStoredProcedure)) + out StoredProcedure? updateStoredProcedure)) { var sprocVariable = Dependencies.CSharpHelper.Identifier( "updateSproc", updateStoredProcedure, parameters.ScopeObjects, capitalize: false); @@ -2087,7 +2087,7 @@ public override void Generate(IProperty property, CSharpRuntimeAnnotationCodeGen if (annotations.TryGetAndRemove( RelationalAnnotationNames.RelationalOverrides, - out IReadOnlyStoreObjectDictionary tableOverrides)) + out IReadOnlyStoreObjectDictionary? tableOverrides)) { AddNamespace(typeof(StoreObjectDictionary), parameters.Namespaces); AddNamespace(typeof(StoreObjectIdentifier), parameters.Namespaces); diff --git a/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs b/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs index acecc79ca01..08913cc8397 100644 --- a/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs +++ b/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs @@ -3144,18 +3144,17 @@ private static string NamedIndexPropertiesMappedToNonOverlappingTables(EventDefi { var d = (FallbackEventDefinition)definition; var p = (IndexWithPropertiesEventData)payload; - return d.GenerateMessage( - l => l.Log( - d.Level, - d.EventId, - d.MessageFormat, - p.Name, - p.EntityType.DisplayName(), - p.PropertyNames.Format(), - p.Property1Name, - p.TablesMappedToProperty1.FormatTables(), - p.Property2Name, - p.TablesMappedToProperty2.FormatTables())); + return d.GenerateMessage(l => l.Log( + d.Level, + d.EventId, + d.MessageFormat, + p.Name, + p.EntityType.DisplayName(), + p.PropertyNames.Format(), + p.Property1Name, + p.TablesMappedToProperty1.FormatTables(), + p.Property2Name, + p.TablesMappedToProperty2.FormatTables())); } /// @@ -3242,18 +3241,17 @@ private static string ForeignKeyPropertiesMappedToUnrelatedTables(EventDefinitio { var d = (FallbackEventDefinition)definition; var p = (ForeignKeyEventData)payload; - return d.GenerateMessage( - l => l.Log( - d.Level, - d.EventId, - d.MessageFormat, - p.ForeignKey.Properties.Format(), - p.ForeignKey.DeclaringEntityType.DisplayName(), - p.ForeignKey.PrincipalEntityType.DisplayName(), - p.ForeignKey.Properties.Format(), - p.ForeignKey.DeclaringEntityType.GetSchemaQualifiedTableName(), - p.ForeignKey.PrincipalKey.Properties.Format(), - p.ForeignKey.PrincipalEntityType.GetSchemaQualifiedTableName())); + return d.GenerateMessage(l => l.Log( + d.Level, + d.EventId, + d.MessageFormat, + p.ForeignKey.Properties.Format(), + p.ForeignKey.DeclaringEntityType.DisplayName(), + p.ForeignKey.PrincipalEntityType.DisplayName(), + p.ForeignKey.Properties.Format(), + p.ForeignKey.DeclaringEntityType.GetSchemaQualifiedTableName(), + p.ForeignKey.PrincipalKey.Properties.Format(), + p.ForeignKey.PrincipalEntityType.GetSchemaQualifiedTableName())); } /// @@ -3299,18 +3297,17 @@ private static string ForeignKeyTPCPrincipal(EventDefinitionBase definition, Eve { var d = (FallbackEventDefinition)definition; var p = (ForeignKeyEventData)payload; - return d.GenerateMessage( - l => l.Log( - d.Level, - d.EventId, - d.MessageFormat, - p.ForeignKey.Properties.Format(), - p.ForeignKey.DeclaringEntityType.DisplayName(), - p.ForeignKey.PrincipalEntityType.DisplayName(), - p.ForeignKey.PrincipalEntityType.GetSchemaQualifiedTableName()!, - p.ForeignKey.PrincipalEntityType.DisplayName(), - p.ForeignKey.DeclaringEntityType.DisplayName(), - p.ForeignKey.PrincipalEntityType.DisplayName())); + return d.GenerateMessage(l => l.Log( + d.Level, + d.EventId, + d.MessageFormat, + p.ForeignKey.Properties.Format(), + p.ForeignKey.DeclaringEntityType.DisplayName(), + p.ForeignKey.PrincipalEntityType.DisplayName(), + p.ForeignKey.PrincipalEntityType.GetSchemaQualifiedTableName()!, + p.ForeignKey.PrincipalEntityType.DisplayName(), + p.ForeignKey.DeclaringEntityType.DisplayName(), + p.ForeignKey.PrincipalEntityType.DisplayName())); } /// diff --git a/src/EFCore.Relational/EFExtensions.cs b/src/EFCore.Relational/EFExtensions.cs index c790c6256f2..a7212acc073 100644 --- a/src/EFCore.Relational/EFExtensions.cs +++ b/src/EFCore.Relational/EFExtensions.cs @@ -30,7 +30,8 @@ public static class EFExtensions /// The type of collection. /// The collection to be integrated as parameters into the query. /// The same value for further use in the query. - public static TSource MultipleParameters(TSource argument) where TSource : IEnumerable + public static TSource MultipleParameters(TSource argument) + where TSource : IEnumerable => throw new InvalidOperationException(RelationalStrings.EFMultipleParametersInvoked); } } diff --git a/src/EFCore.Relational/Extensions/RelationalComplexCollectionTypePropertyBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalComplexCollectionTypePropertyBuilderExtensions.cs index 136edb2463e..b67da37c280 100644 --- a/src/EFCore.Relational/Extensions/RelationalComplexCollectionTypePropertyBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalComplexCollectionTypePropertyBuilderExtensions.cs @@ -41,5 +41,6 @@ public static ComplexCollectionTypePropertyBuilder HasJsonPropertyName( public static ComplexCollectionTypePropertyBuilder HasJsonPropertyName( this ComplexCollectionTypePropertyBuilder propertyBuilder, string? name) - => (ComplexCollectionTypePropertyBuilder)HasJsonPropertyName((ComplexCollectionTypePropertyBuilder)propertyBuilder, name); + => (ComplexCollectionTypePropertyBuilder)HasJsonPropertyName( + (ComplexCollectionTypePropertyBuilder)propertyBuilder, name); } diff --git a/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs b/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs index 561186f724c..fa35a3764d1 100644 --- a/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs @@ -561,7 +561,7 @@ public static Task ExecuteSqlRawAsync( this DatabaseFacade databaseFacade, string sql, CancellationToken cancellationToken = default) - => ExecuteSqlRawAsync(databaseFacade, sql, Enumerable.Empty(), cancellationToken); + => ExecuteSqlRawAsync(databaseFacade, sql, [], cancellationToken); /// /// Executes the given SQL against the database and returns the number of rows affected. diff --git a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs index 86da4f7ffe2..0f0833b02bc 100644 --- a/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs @@ -1021,7 +1021,7 @@ public static void SetComment(this IMutableEntityType entityType, string? commen /// The entity type. /// The configured entity type mapping fragments. public static IEnumerable GetMappingFragments(this IReadOnlyEntityType entityType) - => EntityTypeMappingFragment.Get(entityType) ?? Enumerable.Empty(); + => EntityTypeMappingFragment.Get(entityType) ?? []; /// /// @@ -1036,7 +1036,7 @@ public static IEnumerable GetMappingFragment /// The configured entity type mapping fragments. public static IEnumerable GetMappingFragments(this IMutableEntityType entityType) => EntityTypeMappingFragment.Get(entityType)?.Cast() - ?? Enumerable.Empty(); + ?? []; /// /// @@ -1051,7 +1051,7 @@ public static IEnumerable GetMappingFragments /// The configured entity type mapping fragments. public static IEnumerable GetMappingFragments(this IConventionEntityType entityType) => EntityTypeMappingFragment.Get(entityType)?.Cast() - ?? Enumerable.Empty(); + ?? []; /// /// @@ -1066,7 +1066,7 @@ public static IEnumerable GetMappingFragme /// The configured entity type mapping fragments. public static IEnumerable GetMappingFragments(this IEntityType entityType) => EntityTypeMappingFragment.Get(entityType)?.Cast() - ?? Enumerable.Empty(); + ?? []; /// /// @@ -1086,7 +1086,7 @@ public static IEnumerable GetMappingFragment { var fragments = EntityTypeMappingFragment.Get(entityType); return fragments == null - ? Enumerable.Empty() + ? [] : fragments.Where(f => f.StoreObject.StoreObjectType == storeObjectType); } @@ -1640,10 +1640,10 @@ public static void SetContainerColumnTypeMapping(this IMutableEntityType entityT { var propertyName = entityType.FindAnnotation(RelationalAnnotationNames.JsonPropertyName); return propertyName == null - ? (entityType.IsMappedToJson() - ? entityType.FindOwnership()!.GetNavigation(pointsToPrincipal: false)!.Name - : null) - : (string?)propertyName.Value; + ? (entityType.IsMappedToJson() + ? entityType.FindOwnership()!.GetNavigation(pointsToPrincipal: false)!.Name + : null) + : (string?)propertyName.Value; } /// diff --git a/src/EFCore.Relational/Extensions/RelationalForeignKeyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalForeignKeyExtensions.cs index 2e53d147e76..985ac838e1f 100644 --- a/src/EFCore.Relational/Extensions/RelationalForeignKeyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalForeignKeyExtensions.cs @@ -139,7 +139,7 @@ public static IEnumerable GetMappedConstraints(this IFore foreignKey.DeclaringEntityType.Model.EnsureRelationalModel(); return (IEnumerable?)foreignKey.FindRuntimeAnnotationValue( RelationalAnnotationNames.ForeignKeyMappings) - ?? Enumerable.Empty(); + ?? []; } /// diff --git a/src/EFCore.Relational/Extensions/RelationalIndexExtensions.cs b/src/EFCore.Relational/Extensions/RelationalIndexExtensions.cs index 7df34a087a3..2f27af24c08 100644 --- a/src/EFCore.Relational/Extensions/RelationalIndexExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalIndexExtensions.cs @@ -170,7 +170,7 @@ public static IEnumerable GetMappedTableIndexes(this IIndex index) index.DeclaringEntityType.Model.EnsureRelationalModel(); return (IEnumerable?)index.FindRuntimeAnnotationValue( RelationalAnnotationNames.TableIndexMappings) - ?? Enumerable.Empty(); + ?? []; } /// diff --git a/src/EFCore.Relational/Extensions/RelationalKeyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalKeyExtensions.cs index 2db451d52bb..e6848e8e732 100644 --- a/src/EFCore.Relational/Extensions/RelationalKeyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalKeyExtensions.cs @@ -111,7 +111,7 @@ public static IEnumerable GetMappedConstraints(this IKey key) key.DeclaringEntityType.Model.EnsureRelationalModel(); return (IEnumerable?)key.FindRuntimeAnnotationValue( RelationalAnnotationNames.UniqueConstraintMappings) - ?? Enumerable.Empty(); + ?? []; } /// diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs index 11c4ec363a5..eb1c6ca33f8 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs @@ -253,7 +253,10 @@ public static string GetDefaultColumnName(this IReadOnlyProperty property) return Uniquifier.Truncate(baseName, property.DeclaringType.Model.GetMaxIdentifierLength()); [return: NotNullIfNotNull("builder")] - static StringBuilder? CreateOwnershipPrefix(IReadOnlyEntityType entityType, in StoreObjectIdentifier storeObject, StringBuilder? builder) + static StringBuilder? CreateOwnershipPrefix( + IReadOnlyEntityType entityType, + in StoreObjectIdentifier storeObject, + StringBuilder? builder) { while (true) { @@ -289,7 +292,10 @@ public static string GetDefaultColumnName(this IReadOnlyProperty property) } } - static StringBuilder CreateComplexPrefix(IReadOnlyComplexType complexType, in StoreObjectIdentifier storeObject, StringBuilder? builder) + static StringBuilder CreateComplexPrefix( + IReadOnlyComplexType complexType, + in StoreObjectIdentifier storeObject, + StringBuilder? builder) { builder ??= new StringBuilder(); while (true) @@ -552,7 +558,7 @@ public static IEnumerable GetDefaultColumnMappings(this IPro property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.DefaultColumnMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -565,7 +571,7 @@ public static IEnumerable GetTableColumnMappings(this IProperty property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.TableColumnMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -578,7 +584,7 @@ public static IEnumerable GetViewColumnMappings(this IProper property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.ViewColumnMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -591,7 +597,7 @@ public static IEnumerable GetSqlQueryColumnMappings(this property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.SqlQueryColumnMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -604,7 +610,7 @@ public static IEnumerable GetFunctionColumnMappings(this property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.FunctionColumnMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -617,7 +623,7 @@ public static IEnumerable GetInsertStoredPr property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.InsertStoredProcedureResultColumnMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -630,7 +636,7 @@ public static IEnumerable GetInsertStoredProce property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.InsertStoredProcedureParameterMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -643,7 +649,7 @@ public static IEnumerable GetDeleteStoredProce property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.DeleteStoredProcedureParameterMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -656,7 +662,7 @@ public static IEnumerable GetUpdateStoredPr property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.UpdateStoredProcedureResultColumnMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -669,7 +675,7 @@ public static IEnumerable GetUpdateStoredProce property.DeclaringType.Model.EnsureRelationalModel(); return (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.UpdateStoredProcedureParameterMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -1218,7 +1224,7 @@ public static void SetIsFixedLength(this IMutableProperty property, bool? fixedL /// if the mapped column is nullable; otherwise. public static bool IsColumnNullable(this IReadOnlyProperty property) => property.IsNullable - || (property.DeclaringType.ContainingEntityType is IReadOnlyEntityType entityType + || (property.DeclaringType.ContainingEntityType is { } entityType && entityType.BaseType != null && entityType.GetMappingStrategy() == RelationalAnnotationNames.TphMappingStrategy) || (property.DeclaringType is IReadOnlyComplexType complexType @@ -1226,8 +1232,8 @@ public static bool IsColumnNullable(this IReadOnlyProperty property) private static bool IsNullable(IReadOnlyComplexProperty complexProperty) => complexProperty.IsNullable - || (complexProperty.DeclaringType is IReadOnlyComplexType complexType - && IsNullable(complexType.ComplexProperty)); + || (complexProperty.DeclaringType is IReadOnlyComplexType complexType + && IsNullable(complexType.ComplexProperty)); /// /// Checks whether the column mapped to the given property will be nullable @@ -1255,7 +1261,7 @@ public static bool IsColumnNullable(this IReadOnlyProperty property, in StoreObj } return property.IsNullable - || (property.DeclaringType.ContainingEntityType is IReadOnlyEntityType entityType + || (property.DeclaringType.ContainingEntityType is { } entityType && ((entityType.BaseType != null && entityType.GetMappingStrategy() == RelationalAnnotationNames.TphMappingStrategy) || IsOptionalSharingDependent(entityType, storeObject, 0))) @@ -1643,7 +1649,7 @@ public static IEnumerable GetOverrides(thi /// The property facet overrides. public static IEnumerable GetOverrides(this IMutableProperty property) => RelationalPropertyOverrides.Get(property)?.Cast() - ?? Enumerable.Empty(); + ?? []; /// /// @@ -1658,7 +1664,7 @@ public static IEnumerable GetOverrides(this /// The property facet overrides. public static IEnumerable GetOverrides(this IConventionProperty property) => RelationalPropertyOverrides.Get(property)?.Cast() - ?? Enumerable.Empty(); + ?? []; /// /// @@ -1673,7 +1679,7 @@ public static IEnumerable GetOverrides(t /// The property facet overrides. public static IEnumerable GetOverrides(this IProperty property) => RelationalPropertyOverrides.Get(property)?.Cast() - ?? Enumerable.Empty(); + ?? []; /// /// @@ -2054,7 +2060,9 @@ private static TValue ThrowReadValueException( => (string?)property.FindAnnotation(RelationalAnnotationNames.JsonPropertyName)?.Value ?? (property.IsKey() || !property.DeclaringType.IsMappedToJson() ? null - : property == property.DeclaringType.FindDiscriminatorProperty() ? "$type" : property.Name); + : property == property.DeclaringType.FindDiscriminatorProperty() + ? "$type" + : property.Name); /// /// Sets the value of JSON property name used for the given property of an entity mapped to a JSON column. @@ -2098,10 +2106,10 @@ public static void SetJsonPropertyName(this IMutableProperty property, string? n => property is RuntimeProperty ? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData) : (string?)property[RelationalAnnotationNames.DefaultConstraintName] - ?? (ShouldHaveDefaultConstraintName(property) - && StoreObjectIdentifier.Create(property.DeclaringType, StoreObjectType.Table) is StoreObjectIdentifier table - ? property.GetDefaultDefaultConstraintName(table) - : null); + ?? (ShouldHaveDefaultConstraintName(property) + && StoreObjectIdentifier.Create(property.DeclaringType, StoreObjectType.Table) is { } table + ? property.GetDefaultDefaultConstraintName(table) + : null); /// /// Gets the default constraint name. @@ -2112,13 +2120,13 @@ public static void SetJsonPropertyName(this IMutableProperty property, string? n => property is RuntimeProperty ? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData) : (string?)property[RelationalAnnotationNames.DefaultConstraintName] - ?? (ShouldHaveDefaultConstraintName(property) - ? property.GetDefaultDefaultConstraintName(storeObject) - : null); + ?? (ShouldHaveDefaultConstraintName(property) + ? property.GetDefaultDefaultConstraintName(storeObject) + : null); private static bool ShouldHaveDefaultConstraintName(IReadOnlyProperty property) => property.DeclaringType.Model.AreNamedDefaultConstraintsUsed() - && (property[RelationalAnnotationNames.DefaultValue] is not null + && (property[RelationalAnnotationNames.DefaultValue] is not null || property[RelationalAnnotationNames.DefaultValueSql] is not null); /// diff --git a/src/EFCore.Relational/Extensions/RelationalTypeBaseExtensions.cs b/src/EFCore.Relational/Extensions/RelationalTypeBaseExtensions.cs index 43646c1606d..0ce1ae6a31b 100644 --- a/src/EFCore.Relational/Extensions/RelationalTypeBaseExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalTypeBaseExtensions.cs @@ -1,12 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// ReSharper disable once CheckNamespace - using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Metadata.Internal; +// ReSharper disable once CheckNamespace +#pragma warning disable IDE0130 // Namespace does not match folder structure namespace Microsoft.EntityFrameworkCore; +#pragma warning restore IDE0130 // Namespace does not match folder structure /// /// Type extension methods for relational database metadata. @@ -45,7 +45,7 @@ public static IEnumerable GetDefaultMappings(this ITypeBase t typeBase.Model.EnsureRelationalModel(); return (IEnumerable?)typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.DefaultMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -58,7 +58,7 @@ public static IEnumerable GetTableMappings(this ITypeBase typeBas typeBase.Model.EnsureRelationalModel(); return (IEnumerable?)typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.TableMappings) - ?? Enumerable.Empty(); + ?? []; } #endregion Table mapping @@ -91,7 +91,7 @@ public static IEnumerable GetViewMappings(this ITypeBase typeBase) typeBase.Model.EnsureRelationalModel(); return (IEnumerable?)typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.ViewMappings) - ?? Enumerable.Empty(); + ?? []; } #endregion View mapping @@ -116,7 +116,7 @@ public static IEnumerable GetSqlQueryMappings(this ITypeBase t typeBase.Model.EnsureRelationalModel(); return (IEnumerable?)typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.SqlQueryMappings) - ?? Enumerable.Empty(); + ?? []; } #endregion SQL query mapping @@ -141,7 +141,7 @@ public static IEnumerable GetFunctionMappings(this ITypeBase t typeBase.Model.EnsureRelationalModel(); return (IEnumerable?)typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.FunctionMappings) - ?? Enumerable.Empty(); + ?? []; } #endregion @@ -212,7 +212,7 @@ public static IEnumerable GetInsertStoredProcedureMappi typeBase.Model.EnsureRelationalModel(); return (IEnumerable?)typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.InsertStoredProcedureMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -225,7 +225,7 @@ public static IEnumerable GetDeleteStoredProcedureMappi typeBase.Model.EnsureRelationalModel(); return (IEnumerable?)typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.DeleteStoredProcedureMappings) - ?? Enumerable.Empty(); + ?? []; } /// @@ -238,7 +238,7 @@ public static IEnumerable GetUpdateStoredProcedureMappi typeBase.Model.EnsureRelationalModel(); return (IEnumerable?)typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.UpdateStoredProcedureMappings) - ?? Enumerable.Empty(); + ?? []; } #endregion @@ -374,10 +374,10 @@ public static bool IsMappedToJson(this IReadOnlyTypeBase typeBase) { var containerColumnName = typeBase.FindAnnotation(RelationalAnnotationNames.ContainerColumnName); return containerColumnName != null - ? (string?)containerColumnName.Value - : typeBase is IReadOnlyEntityType entityType - ? entityType.FindOwnership()?.PrincipalEntityType.GetContainerColumnName() - : ((IReadOnlyComplexType)typeBase).ComplexProperty.DeclaringType.GetContainerColumnName(); + ? (string?)containerColumnName.Value + : typeBase is IReadOnlyEntityType entityType + ? entityType.FindOwnership()?.PrincipalEntityType.GetContainerColumnName() + : ((IReadOnlyComplexType)typeBase).ComplexProperty.DeclaringType.GetContainerColumnName(); } /// @@ -416,7 +416,7 @@ public static void SetContainerColumnName(this IMutableTypeBase typeBase, string /// The type. /// The database column type. public static string? GetContainerColumnType(this IReadOnlyTypeBase typeBase) - => typeBase.FindAnnotation(RelationalAnnotationNames.ContainerColumnType)?.Value is string columnName + => typeBase.FindAnnotation(RelationalAnnotationNames.ContainerColumnType)?.Value is string columnName ? columnName : typeBase is IReadOnlyEntityType entityType ? entityType.FindOwnership()?.PrincipalEntityType.GetContainerColumnType() @@ -451,7 +451,7 @@ public static void SetContainerColumnType(this IMutableTypeBase typeBase, string public static ConfigurationSource? GetContainerColumnTypeConfigurationSource(this IConventionTypeBase typeBase) => typeBase.FindAnnotation(RelationalAnnotationNames.ContainerColumnType) ?.GetConfigurationSource(); - + /// /// Gets the value of JSON property name used for the given entity mapped to a JSON column. /// diff --git a/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs b/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs index ca9d17a642f..7041c191934 100644 --- a/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs +++ b/src/EFCore.Relational/Infrastructure/EntityFrameworkRelationalServicesBuilder.cs @@ -168,8 +168,8 @@ public override EntityFrameworkServicesBuilder TryAddCoreServices() TryAdd(p => p.GetRequiredService()); TryAdd(); TryAdd(); - TryAdd>( - p => p.GetRequiredService()); + TryAdd>(p + => p.GetRequiredService()); TryAdd(); TryAdd>(p => p.GetRequiredService()); TryAdd(); diff --git a/src/EFCore.Relational/Infrastructure/RelationalDbContextOptionsBuilder.cs b/src/EFCore.Relational/Infrastructure/RelationalDbContextOptionsBuilder.cs index 01935a24036..424276901a1 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalDbContextOptionsBuilder.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalDbContextOptionsBuilder.cs @@ -154,8 +154,7 @@ public virtual TBuilder UseQuerySplittingBehavior(QuerySplittingBehavior querySp /// A function that returns a new instance of an execution strategy. public virtual TBuilder ExecutionStrategy( Func getExecutionStrategy) - => WithOption( - e => (TExtension)e.WithExecutionStrategyFactory(Check.NotNull(getExecutionStrategy))); + => WithOption(e => (TExtension)e.WithExecutionStrategyFactory(Check.NotNull(getExecutionStrategy))); /// /// Configures the context to translate parameterized collections to inline constants. @@ -191,7 +190,8 @@ public virtual TBuilder TranslateParameterizedCollectionsToConstants() /// WHERE [b].[Id] IN (@ids1, @ids2, @ids3). /// /// - /// instructs EF to translate the collection to a single array-like parameter: + /// instructs EF to translate the collection to a single array-like + /// parameter: /// WHERE [b].[Id] IN (SELECT [i].[value] FROM OPENJSON(@ids) ...). /// /// diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs index a940d9be61e..77a1246bc17 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs @@ -97,7 +97,7 @@ static void ValidateType(ITypeBase typeBase) } } - /// + /// protected override void ValidatePropertyMapping( IConventionComplexProperty complexProperty, IDiagnosticsLogger logger) @@ -129,7 +129,8 @@ protected override void ValidatePropertyMapping( columnName, complexProperty.GetJsonPropertyName())); } - else if (!complexProperty.DeclaringType.IsMappedToJson()) + + if (!complexProperty.DeclaringType.IsMappedToJson()) { throw new InvalidOperationException( RelationalStrings.ComplexPropertyJsonPropertyNameWithoutJsonMapping( @@ -517,7 +518,7 @@ private static void ValidateSproc( var parameterNames = new HashSet(); foreach (var parameter in sproc.Parameters) { - IProperty property = null!; + IProperty? property = null; if (parameter.PropertyName != null) { if (parameter.ForOriginalValue == true) @@ -612,12 +613,11 @@ private static void ValidateSproc( case StoreObjectType.InsertStoredProcedure: case StoreObjectType.UpdateStoredProcedure: if (parameter.Direction != ParameterDirection.Input - && !storeGeneratedProperties.Remove(property.Name)) + && !storeGeneratedProperties.Remove(property!.Name)) { - if (sproc.Parameters.Any( - p => p.PropertyName == property.Name - && p.ForOriginalValue != parameter.ForOriginalValue - && p.Direction != ParameterDirection.Input)) + if (sproc.Parameters.Any(p => p.PropertyName == property.Name + && p.ForOriginalValue != parameter.ForOriginalValue + && p.Direction != ParameterDirection.Input)) { throw new InvalidOperationException( RelationalStrings.StoredProcedureOutputParameterConflict( @@ -631,7 +631,7 @@ private static void ValidateSproc( break; case StoreObjectType.DeleteStoredProcedure: - if (!property.IsPrimaryKey() + if (!property!.IsPrimaryKey() && !property.IsConcurrencyToken) { throw new InvalidOperationException( @@ -1006,10 +1006,9 @@ protected virtual void ValidateSharedTableCompatibility( var primaryKey = mappedType.FindPrimaryKey(); if (primaryKey != null && (mappedType.FindForeignKeys(primaryKey.Properties) - .FirstOrDefault( - fk => fk.PrincipalKey.IsPrimaryKey() - && !fk.PrincipalEntityType.IsAssignableFrom(fk.DeclaringEntityType) - && unvalidatedTypes.Contains(fk.PrincipalEntityType)) is { } linkingFK)) + .FirstOrDefault(fk => fk.PrincipalKey.IsPrimaryKey() + && !fk.PrincipalEntityType.IsAssignableFrom(fk.DeclaringEntityType) + && unvalidatedTypes.Contains(fk.PrincipalEntityType)) is { } linkingFK)) { if (mappedType.BaseType != null) { @@ -1035,7 +1034,7 @@ protected virtual void ValidateSharedTableCompatibility( root = mappedType; } - Check.DebugAssert(root != null, "root != null"); + Check.DebugAssert(root != null); unvalidatedTypes.Remove(root); var typesToValidate = new Queue(); typesToValidate.Enqueue(root); @@ -1047,10 +1046,9 @@ protected virtual void ValidateSharedTableCompatibility( var comment = entityType.GetComment(); var isExcluded = entityType.IsTableExcludedFromMigrations(storeObject); var typesToValidateLeft = typesToValidate.Count; - var directlyConnectedTypes = unvalidatedTypes.Where( - unvalidatedType => - entityType.IsAssignableFrom(unvalidatedType) - || IsIdentifyingPrincipal(unvalidatedType, entityType)); + var directlyConnectedTypes = unvalidatedTypes.Where(unvalidatedType => + entityType.IsAssignableFrom(unvalidatedType) + || IsIdentifyingPrincipal(unvalidatedType, entityType)); foreach (var nextEntityType in directlyConnectedTypes) { @@ -1190,16 +1188,14 @@ protected virtual void ValidateSharedViewCompatibility( if (mappedType.FindPrimaryKey() != null && mappedType.FindForeignKeys(mappedType.FindPrimaryKey()!.Properties) - .Any( - fk => fk.PrincipalKey.IsPrimaryKey() - && unvalidatedTypes.Contains(fk.PrincipalEntityType))) + .Any(fk => fk.PrincipalKey.IsPrimaryKey() + && unvalidatedTypes.Contains(fk.PrincipalEntityType))) { if (mappedType.BaseType != null) { var principalType = mappedType.FindForeignKeys(mappedType.FindPrimaryKey()!.Properties) - .First( - fk => fk.PrincipalKey.IsPrimaryKey() - && unvalidatedTypes.Contains(fk.PrincipalEntityType)) + .First(fk => fk.PrincipalKey.IsPrimaryKey() + && unvalidatedTypes.Contains(fk.PrincipalEntityType)) .PrincipalEntityType; throw new InvalidOperationException( RelationalStrings.IncompatibleViewDerivedRelationship( @@ -1223,7 +1219,7 @@ protected virtual void ValidateSharedViewCompatibility( root = mappedType; } - Check.DebugAssert(root != null, "root != null"); + Check.DebugAssert(root != null); unvalidatedTypes.Remove(root); var typesToValidate = new Queue(); typesToValidate.Enqueue(root); @@ -1232,10 +1228,9 @@ protected virtual void ValidateSharedViewCompatibility( { var entityType = typesToValidate.Dequeue(); var typesToValidateLeft = typesToValidate.Count; - var directlyConnectedTypes = unvalidatedTypes.Where( - unvalidatedType => - entityType.IsAssignableFrom(unvalidatedType) - || IsIdentifyingPrincipal(unvalidatedType, entityType)); + var directlyConnectedTypes = unvalidatedTypes.Where(unvalidatedType => + entityType.IsAssignableFrom(unvalidatedType) + || IsIdentifyingPrincipal(unvalidatedType, entityType)); foreach (var nextEntityType in directlyConnectedTypes) { @@ -1266,9 +1261,8 @@ protected virtual void ValidateSharedViewCompatibility( private static bool IsIdentifyingPrincipal(IEntityType dependentEntityType, IEntityType principalEntityType) => dependentEntityType.FindForeignKeys(dependentEntityType.FindPrimaryKey()!.Properties) - .Any( - fk => fk.PrincipalKey.IsPrimaryKey() - && fk.PrincipalEntityType == principalEntityType); + .Any(fk => fk.PrincipalKey.IsPrimaryKey() + && fk.PrincipalEntityType == principalEntityType); /// /// Validates the compatibility of properties sharing columns in a given table-like object. @@ -1337,6 +1331,8 @@ protected virtual void ValidateSharedColumnsCompatibility( columnOrders.Where(g => g.Value.Count > 1).SelectMany(g => g.Value).ToList()); } + return; + void ValidateCompatible( ITypeBase structuralType, in StoreObjectIdentifier storeObject, @@ -2081,10 +2077,9 @@ private static void ValidateNonTphMapping(IEntityType rootEntityType, StoreObjec var unmappedOwnedType = entityType.GetReferencingForeignKeys() .Where(fk => fk.IsOwnership) .Select(fk => fk.DeclaringEntityType) - .FirstOrDefault( - owned => StoreObjectIdentifier.Create(owned, storeObjectType) == null - && ((IConventionEntityType)owned).GetStoreObjectConfigurationSource(storeObjectType) == null - && !owned.IsMappedToJson()); + .FirstOrDefault(owned => StoreObjectIdentifier.Create(owned, storeObjectType) == null + && ((IConventionEntityType)owned).GetStoreObjectConfigurationSource(storeObjectType) == null + && !owned.IsMappedToJson()); if (unmappedOwnedType != null && entityType.GetDerivedTypes().Any(derived => StoreObjectIdentifier.Create(derived, storeObjectType) != null)) { @@ -2599,7 +2594,7 @@ protected override void ValidateData(IModel model, IDiagnosticsLogger x.ForeignKey.IsOwnership && x.TargetEntityType.IsMappedToJson())) { - if (entityType.GetSeedData().Any(x => x.TryGetValue(navigation.Name, out var _))) + if (entityType.GetSeedData().Any(x => x.TryGetValue(navigation.Name, out _))) { throw new InvalidOperationException( RelationalStrings.HasDataNotSupportedForEntitiesMappedToJson(entityType.DisplayName())); @@ -2730,7 +2725,7 @@ protected virtual void ValidateJsonEntities( var jsonColumnMappings = new Dictionary>(); foreach (var entityType in mappedTypes) { - if (entityType.FindOwnership() is not IForeignKey ownership + if (entityType.FindOwnership() is not { } ownership || ownership.PrincipalEntityType.IsMappedToJson()) { continue; @@ -2744,6 +2739,7 @@ protected virtual void ValidateJsonEntities( sources = []; jsonColumnMappings[columnName] = sources; } + sources.Add(entityType); } } @@ -2793,6 +2789,7 @@ static void ValidateNestedComplexTypes(Dictionary> jsonC sources = []; jsonColumnMappings[columnName] = sources; } + sources.Add(complexProperty.ComplexType); } else @@ -2805,10 +2802,9 @@ static void ValidateNestedComplexTypes(Dictionary> jsonC private void ValidateJsonEntitiesNotMappedToTableOrView(IEnumerable entityTypes) { - var entitiesNotMappedToTableOrView = entityTypes.Where( - x => !x.IsMappedToJson() - && x.GetSchemaQualifiedTableName() == null - && x.GetSchemaQualifiedViewName() == null); + var entitiesNotMappedToTableOrView = entityTypes.Where(x => !x.IsMappedToJson() + && x.GetSchemaQualifiedTableName() == null + && x.GetSchemaQualifiedViewName() == null); foreach (var entityNotMappedToTableOrView in entitiesNotMappedToTableOrView) { @@ -2991,7 +2987,7 @@ private static Dictionary ValidateJsonProperties(IConventionType jsonPropertyName)); } - if (property.TryGetDefaultValue(out var _)) + if (property.TryGetDefaultValue(out _)) { // Issue #35934 throw new InvalidOperationException( @@ -3021,7 +3017,11 @@ private static Dictionary ValidateJsonProperties(IConventionType return jsonPropertyNames; } - private static void CheckUniqueness(string jsonPropertyName, string propertyName, IReadOnlyTypeBase structuralType, Dictionary jsonPropertyNames) + private static void CheckUniqueness( + string jsonPropertyName, + string propertyName, + IReadOnlyTypeBase structuralType, + Dictionary jsonPropertyNames) { if (jsonPropertyNames.TryGetValue(jsonPropertyName, out var existingProperty)) { @@ -3032,6 +3032,7 @@ private static void CheckUniqueness(string jsonPropertyName, string propertyName structuralType.DisplayName(), jsonPropertyName)); } + jsonPropertyNames[jsonPropertyName] = propertyName; } diff --git a/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs b/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs index f191708d16f..cec56bf873d 100644 --- a/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/CheckConstraintConvention.cs @@ -161,7 +161,7 @@ private static bool AreCompatible(IConventionCheckConstraint checkConstraint, IC } if (checkConstraint.GetName(baseTable.Value) != baseCheckConstraint.GetName(baseTable.Value) - && checkConstraint.GetNameConfigurationSource() is ConfigurationSource nameConfigurationSource + && checkConstraint.GetNameConfigurationSource() is { } nameConfigurationSource && !nameConfigurationSource.OverridesStrictly(baseCheckConstraint.GetNameConfigurationSource())) { return false; diff --git a/src/EFCore.Relational/Metadata/Conventions/EntitySplittingConvention.cs b/src/EFCore.Relational/Metadata/Conventions/EntitySplittingConvention.cs index 7c533938f18..cf08ff7dab3 100644 --- a/src/EFCore.Relational/Metadata/Conventions/EntitySplittingConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/EntitySplittingConvention.cs @@ -92,10 +92,9 @@ public virtual void ProcessModelFinalizing( var pk = entityType.FindPrimaryKey(); if (pk != null && !entityType.FindDeclaredForeignKeys(pk.Properties) - .Any( - fk => fk.PrincipalKey.IsPrimaryKey() - && fk.PrincipalEntityType.IsAssignableFrom(entityType) - && fk.PrincipalEntityType != entityType)) + .Any(fk => fk.PrincipalKey.IsPrimaryKey() + && fk.PrincipalEntityType.IsAssignableFrom(entityType) + && fk.PrincipalEntityType != entityType)) { entityType.Builder.HasRelationship(entityType, pk.Properties, pk) ?.IsUnique(true) diff --git a/src/EFCore.Relational/Metadata/Conventions/EntityTypeHierarchyMappingConvention.cs b/src/EFCore.Relational/Metadata/Conventions/EntityTypeHierarchyMappingConvention.cs index df68c322111..f695920f589 100644 --- a/src/EFCore.Relational/Metadata/Conventions/EntityTypeHierarchyMappingConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/EntityTypeHierarchyMappingConvention.cs @@ -89,10 +89,9 @@ public virtual void ProcessModelFinalizing( var pk = entityType.FindPrimaryKey(); if (pk != null && !entityType.FindDeclaredForeignKeys(pk.Properties) - .Any( - fk => fk.PrincipalKey.IsPrimaryKey() - && fk.PrincipalEntityType.IsAssignableFrom(entityType) - && fk.PrincipalEntityType != entityType)) + .Any(fk => fk.PrincipalKey.IsPrimaryKey() + && fk.PrincipalEntityType.IsAssignableFrom(entityType) + && fk.PrincipalEntityType != entityType)) { var closestMappedType = entityType.BaseType; while (closestMappedType != null diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalKeyDiscoveryConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalKeyDiscoveryConvention.cs index 1d2a1e2d96c..fc35e5d6cb1 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalKeyDiscoveryConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalKeyDiscoveryConvention.cs @@ -4,7 +4,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions; /// -/// A relational-specific convention inheriting from . +/// A relational-specific convention inheriting from . /// /// /// @@ -31,9 +31,7 @@ public RelationalKeyDiscoveryConvention( ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies) : base(dependencies) - { - RelationalDependencies = relationalDependencies; - } + => RelationalDependencies = relationalDependencies; /// /// Relational provider-specific dependencies for this service. diff --git a/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs b/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs index 85663dd18d4..494c2a6418d 100644 --- a/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs @@ -251,12 +251,12 @@ private static void UniquifyColumnNames( #pragma warning disable EF1001 // Internal EF Core API usage. var identifyingMemberInfo = property.GetIdentifyingMemberInfo(); var isInheritedSharedMember = identifyingMemberInfo != null - && ((declaringEntityType != null && identifyingMemberInfo.DeclaringType != type.ClrType) - || (declaringEntityType == null - && otherProperty.DeclaringType is IConventionComplexType otherDeclaringComplexType - && ((IConventionComplexType)property.DeclaringType).ComplexProperty.GetIdentifyingMemberInfo() - .IsSameAs(otherDeclaringComplexType.ComplexProperty.GetIdentifyingMemberInfo()))) - && identifyingMemberInfo.IsSameAs(otherProperty.GetIdentifyingMemberInfo()); + && ((declaringEntityType != null && identifyingMemberInfo.DeclaringType != type.ClrType) + || (declaringEntityType == null + && otherProperty.DeclaringType is IConventionComplexType otherDeclaringComplexType + && ((IConventionComplexType)property.DeclaringType).ComplexProperty.GetIdentifyingMemberInfo() + .IsSameAs(otherDeclaringComplexType.ComplexProperty.GetIdentifyingMemberInfo()))) + && identifyingMemberInfo.IsSameAs(otherProperty.GetIdentifyingMemberInfo()); #pragma warning restore EF1001 // Internal EF Core API usage. if (isInheritedSharedMember || (property.IsPrimaryKey() && otherProperty.IsPrimaryKey()) @@ -692,14 +692,16 @@ private void UniquifyDefaultConstraintNames( continue; } - var newConstraintName = TryUniquifyDefaultConstraint(property, constraintName, storeObject.Schema, defaultConstraints, storeObject, maxLength); + var newConstraintName = TryUniquifyDefaultConstraint( + property, constraintName, storeObject.Schema, defaultConstraints, storeObject, maxLength); if (newConstraintName != null) { defaultConstraints[(newConstraintName, storeObject.Schema)] = (property, storeObject); continue; } - var newOtherConstraintName = TryUniquifyDefaultConstraint(otherProperty, constraintName, storeObject.Schema, defaultConstraints, otherStoreObject, maxLength); + var newOtherConstraintName = TryUniquifyDefaultConstraint( + otherProperty, constraintName, storeObject.Schema, defaultConstraints, otherStoreObject, maxLength); if (newOtherConstraintName != null) { defaultConstraints[(constraintName, storeObject.Schema)] = (property, storeObject); @@ -742,11 +744,9 @@ protected virtual bool AreCompatibleDefaultConstraints( throw new InvalidOperationException( RelationalStrings.ImplicitDefaultNamesNotSupportedForTpcWhenNamesClash(constraintName)); } - else - { - throw new InvalidOperationException( - RelationalStrings.ExplicitDefaultConstraintNamesNotSupportedForTpc(constraintName)); - } + + throw new InvalidOperationException( + RelationalStrings.ExplicitDefaultConstraintNamesNotSupportedForTpc(constraintName)); } if (property.Builder.CanSetAnnotation(RelationalAnnotationNames.DefaultConstraintName, null)) diff --git a/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs b/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs index ed127d01126..cf9b6f99cdb 100644 --- a/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/TableSharingConcurrencyTokenConvention.cs @@ -238,15 +238,13 @@ public static bool IsConcurrencyTokenMissing( } var linkingFks = containingEntityType.FindForeignKeys(containingEntityType.FindPrimaryKey()!.Properties) - .Where( - fk => fk.PrincipalKey.IsPrimaryKey() - && mappedTypes.Contains(fk.PrincipalEntityType)).ToList(); + .Where(fk => fk.PrincipalKey.IsPrimaryKey() + && mappedTypes.Contains(fk.PrincipalEntityType)).ToList(); if (linkingFks != null && linkingFks.Count > 0 && linkingFks.All(fk => fk.PrincipalEntityType != entityType) - && linkingFks.Any( - fk => fk.PrincipalEntityType.IsAssignableFrom(entityType) - || entityType.IsAssignableFrom(fk.PrincipalEntityType))) + && linkingFks.Any(fk => fk.PrincipalEntityType.IsAssignableFrom(entityType) + || entityType.IsAssignableFrom(fk.PrincipalEntityType))) { // The concurrency token is on a type that shares the row with a base or derived type propertyMissing = false; diff --git a/src/EFCore.Relational/Metadata/ITableIndex.cs b/src/EFCore.Relational/Metadata/ITableIndex.cs index a320e1de25c..569ae971273 100644 --- a/src/EFCore.Relational/Metadata/ITableIndex.cs +++ b/src/EFCore.Relational/Metadata/ITableIndex.cs @@ -78,15 +78,14 @@ string ToDebugString(MetadataDebugStringOptions options = MetadataDebugStringOpt .AppendJoin( ", ", Enumerable.Range(0, Columns.Count) - .Select( - i => - $@"'{Columns[i].Name}'{( - MappedIndexes.First() is not RuntimeIndex - && IsDescending is not null - && (IsDescending.Count == 0 || IsDescending[i]) - ? " Desc" - : "" - )}")) + .Select(i => + $@"'{Columns[i].Name}'{( + MappedIndexes.First() is not RuntimeIndex + && IsDescending is not null + && (IsDescending.Count == 0 || IsDescending[i]) + ? " Desc" + : "" + )}")) .Append('}'); if (IsUnique) diff --git a/src/EFCore.Relational/Metadata/Internal/DbFunction.cs b/src/EFCore.Relational/Metadata/Internal/DbFunction.cs index f93df12aea9..c9c3ed381a3 100644 --- a/src/EFCore.Relational/Metadata/Internal/DbFunction.cs +++ b/src/EFCore.Relational/Metadata/Internal/DbFunction.cs @@ -195,7 +195,7 @@ public override bool IsReadOnly public static IEnumerable GetDbFunctions(IReadOnlyModel model) => ((Dictionary?)model[RelationalAnnotationNames.DbFunctions]) ?.OrderBy(t => t.Key).Select(t => t.Value) - ?? Enumerable.Empty(); + ?? []; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalEntityTypeExtensions.cs b/src/EFCore.Relational/Metadata/Internal/RelationalEntityTypeExtensions.cs index c62e88fc279..82610c599b9 100644 --- a/src/EFCore.Relational/Metadata/Internal/RelationalEntityTypeExtensions.cs +++ b/src/EFCore.Relational/Metadata/Internal/RelationalEntityTypeExtensions.cs @@ -29,7 +29,7 @@ public static IEnumerable FindDeclaredReferencingRowInternalForeign this IEntityType entityType, StoreObjectIdentifier storeObject) => entityType.IsMappedToJson() - ? Enumerable.Empty() + ? [] : entityType.GetDeclaredReferencingForeignKeys().Where(fk => fk.IsRowInternal(storeObject)); /// diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs b/src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs index 1f5ea263001..4c7460bb7dc 100644 --- a/src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs +++ b/src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs @@ -220,11 +220,10 @@ is not { } principalColumns .Select(t => StoreObjectIdentifier.Create(t, StoreObjectType.Table)) .Where(t => t != null); if (foreignKey.GetConstraintName() != null - && derivedTables.All( - t => foreignKey.GetConstraintName( - t!.Value, - principalTable) - == null)) + && derivedTables.All(t => foreignKey.GetConstraintName( + t!.Value, + principalTable) + == null)) { logger.ForeignKeyPropertiesMappedToUnrelatedTables((IForeignKey)foreignKey); } diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalModel.cs b/src/EFCore.Relational/Metadata/Internal/RelationalModel.cs index a0f664d10d4..9f6c26fb8fb 100644 --- a/src/EFCore.Relational/Metadata/Internal/RelationalModel.cs +++ b/src/EFCore.Relational/Metadata/Internal/RelationalModel.cs @@ -275,7 +275,7 @@ private static void AddDefaultMappings( // ownership and inheritance. var principalRootEntityType = mappedType; - if (mappedType.FindOwnership() is IForeignKey ownership && (ownership.IsUnique || mappedType.IsMappedToJson())) + if (mappedType.FindOwnership() is { } ownership && (ownership.IsUnique || mappedType.IsMappedToJson())) { principalRootEntityType = ownership.PrincipalEntityType; } @@ -378,7 +378,7 @@ private static void CreateDefaultColumnMapping( .FindRuntimeAnnotationValue(RelationalAnnotationNames.DefaultMappings); if (tableMappings == null) { - tableMappings = new List>(); + tableMappings = []; complexType.AddRuntimeAnnotation(RelationalAnnotationNames.DefaultMappings, tableMappings); } @@ -412,7 +412,7 @@ static string GetColumnName(IProperty property) private static IEnumerable GetTableMappings(ITypeBase typeBase) => (IEnumerable?)typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.TableMappings) - ?? Enumerable.Empty(); + ?? []; private static void AddTables( RelationalModel databaseModel, @@ -606,12 +606,15 @@ private static void CreateContainerColumn( return; } - Check.DebugAssert(tableBase.FindColumn(containerColumnName) == null, $"Table '{tableBase.Name}' already has a '{containerColumnName}' column."); + Check.DebugAssert( + tableBase.FindColumn(containerColumnName) == null, $"Table '{tableBase.Name}' already has a '{containerColumnName}' column."); - var jsonColumnTypeMapping = relationalTypeMappingSource.FindMapping(typeof(JsonTypePlaceholder), storeTypeName: containerColumnType); + var jsonColumnTypeMapping = relationalTypeMappingSource.FindMapping( + typeof(JsonTypePlaceholder), storeTypeName: containerColumnType); if (jsonColumnTypeMapping == null) { - throw new InvalidOperationException(RelationalStrings.UnsupportedJsonColumnType(containerColumnType ?? "null", containerColumnName, tableBase.Name)); + throw new InvalidOperationException( + RelationalStrings.UnsupportedJsonColumnType(containerColumnType ?? "null", containerColumnName, tableBase.Name)); } var jsonColumn = createColumn(containerColumnName, containerColumnType, tableBase, jsonColumnTypeMapping); @@ -631,7 +634,8 @@ private static void CreateContainerColumn( { complexType = (IComplexType)mappedType; #pragma warning disable EF1001 // Internal EF Core API usage. - jsonColumn.IsNullable = complexType.ComplexProperty.IsNullable || complexType.ComplexProperty.GetChainToComplexProperty(fromEntity: true).Any(p => p.IsNullable); + jsonColumn.IsNullable = complexType.ComplexProperty.IsNullable + || complexType.ComplexProperty.GetChainToComplexProperty(fromEntity: true).Any(p => p.IsNullable); #pragma warning restore EF1001 // Internal EF Core API usage. } } @@ -1044,11 +1048,10 @@ private static void AddStoredProcedures( ? !isTpc && mappedType == entityType : (bool?)null; - var tableMappings = GetTableMappings(entityType).Where( - m => m.Table.Name == mappedType.GetTableName() - && m.Table.Schema == mappedType.GetSchema() - && m.IsSplitEntityTypePrincipal != false - && m.IncludesDerivedTypes == includesDerivedTypes); + var tableMappings = GetTableMappings(entityType).Where(m => m.Table.Name == mappedType.GetTableName() + && m.Table.Schema == mappedType.GetSchema() + && m.IsSplitEntityTypePrincipal != false + && m.IncludesDerivedTypes == includesDerivedTypes); var tableMapping = (TableMapping?)tableMappings.FirstOrDefault(); Check.DebugAssert(tableMapping == null || tableMappings.Count() == 1, "Expected table mapping to be unique"); @@ -1405,7 +1408,7 @@ static StoreStoredProcedureResultColumn GetOrCreateStoreStoredProcedureResultCol private static IEnumerable GetTableColumnMappings(IProperty property) => (IEnumerable?)property.FindRuntimeAnnotationValue( RelationalAnnotationNames.TableColumnMappings) - ?? Enumerable.Empty(); + ?? []; private static IColumn? FindColumn(Table table, IProperty property) => GetTableColumnMappings(property) @@ -1566,7 +1569,7 @@ private static void PopulateRowInternalForeignKeys(TableBase tab } var foreignKeys = entityType.IsMappedToJson() - ? new[] { entityType.FindOwnership()! } + ? [entityType.FindOwnership()!] : entityType.FindForeignKeys(primaryKey.Properties); var isMainMapping = true; @@ -1730,7 +1733,7 @@ private static void PopulateForeignKeyConstraints(Table table) if (entityTypeMapping.IncludesDerivedTypes == true && foreignKey.DeclaringEntityType != entityType - && entityType.FindPrimaryKey() is IKey primaryKey + && entityType.FindPrimaryKey() is { } primaryKey && foreignKey.Properties.SequenceEqual(primaryKey.Properties)) { Check.DebugAssert(false, "Should not get here if name is not null"); diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalTypeBaseExtensions.cs b/src/EFCore.Relational/Metadata/Internal/RelationalTypeBaseExtensions.cs index d84babc6554..0c30e6610b6 100644 --- a/src/EFCore.Relational/Metadata/Internal/RelationalTypeBaseExtensions.cs +++ b/src/EFCore.Relational/Metadata/Internal/RelationalTypeBaseExtensions.cs @@ -25,6 +25,6 @@ public static IEnumerable GetViewOrTableMappings(this ITypeBa return (IEnumerable?)(typeBase.FindRuntimeAnnotationValue( RelationalAnnotationNames.ViewMappings) ?? typeBase.FindRuntimeAnnotationValue(RelationalAnnotationNames.TableMappings)) - ?? Enumerable.Empty(); + ?? []; } } diff --git a/src/EFCore.Relational/Metadata/Internal/Sequence.cs b/src/EFCore.Relational/Metadata/Internal/Sequence.cs index 97f97c7bd8b..aa748db14d8 100644 --- a/src/EFCore.Relational/Metadata/Internal/Sequence.cs +++ b/src/EFCore.Relational/Metadata/Internal/Sequence.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; -using System.Text; namespace Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -132,7 +131,7 @@ public Sequence(IReadOnlyModel model, string annotationName) public static IEnumerable GetSequences(IReadOnlyModel model) => ((Dictionary<(string, string?), ISequence>?)model[RelationalAnnotationNames.Sequences]) ?.OrderBy(t => t.Key).Select(t => t.Value) - ?? Enumerable.Empty(); + ?? []; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -483,7 +482,7 @@ public virtual long? MaxValue /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public static IReadOnlyCollection SupportedTypes { get; } - = new[] { typeof(byte), typeof(long), typeof(int), typeof(short), typeof(decimal) }; + = [typeof(byte), typeof(long), typeof(int), typeof(short), typeof(decimal)]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -756,29 +755,16 @@ public static SequenceData Deserialize(string value) => value == null ? null : long.Parse(value, CultureInfo.InvariantCulture); private static Type AsType(string value) - => value == nameof(Int64) - ? typeof(long) - : value == nameof(Int32) - ? typeof(int) - : value == nameof(Int16) - ? typeof(short) - : value == nameof(Decimal) - ? typeof(decimal) - : typeof(byte); + => value switch + { + nameof(Int64) => typeof(long), + nameof(Int32) => typeof(int), + nameof(Int16) => typeof(short), + nameof(Decimal) => typeof(decimal), + _ => typeof(byte) + }; private static bool AsBool(string? value) => value != null && bool.Parse(value); - - private static void EscapeAndQuote(StringBuilder builder, object? value) - { - builder.Append('\''); - - if (value != null) - { - builder.Append(value.ToString()!.Replace("'", "''")); - } - - builder.Append('\''); - } } } diff --git a/src/EFCore.Relational/Metadata/Internal/TableBase.cs b/src/EFCore.Relational/Metadata/Internal/TableBase.cs index 7910aea9b33..50ce10fe0d7 100644 --- a/src/EFCore.Relational/Metadata/Internal/TableBase.cs +++ b/src/EFCore.Relational/Metadata/Internal/TableBase.cs @@ -255,7 +255,7 @@ IEnumerable ITableBase.GetRowInternalForeignKeys(IEntityType entity } CheckMappedType(entityType); - return Enumerable.Empty(); + return []; } /// @@ -268,6 +268,6 @@ IEnumerable ITableBase.GetReferencingRowInternalForeignKeys(IEntity } CheckMappedType(entityType); - return Enumerable.Empty(); + return []; } } diff --git a/src/EFCore.Relational/Metadata/RelationalAnnotationProvider.cs b/src/EFCore.Relational/Metadata/RelationalAnnotationProvider.cs index b7e0bea889f..048c4c0bac2 100644 --- a/src/EFCore.Relational/Metadata/RelationalAnnotationProvider.cs +++ b/src/EFCore.Relational/Metadata/RelationalAnnotationProvider.cs @@ -34,77 +34,77 @@ public RelationalAnnotationProvider(RelationalAnnotationProviderDependencies dep /// public virtual IEnumerable For(IRelationalModel model, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(ITable table, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IColumn column, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IView view, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IViewColumn column, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(ISqlQuery sqlQuery, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(ISqlQueryColumn column, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IStoreFunction function, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IStoreFunctionParameter parameter, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IFunctionColumn column, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IStoreStoredProcedure storedProcedure, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IStoreStoredProcedureParameter parameter, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IStoreStoredProcedureResultColumn column, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IForeignKeyConstraint foreignKey, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(ITableIndex index, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(IUniqueConstraint constraint, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(ISequence sequence, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(ICheckConstraint checkConstraint, bool designTime) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable For(ITrigger trigger, bool designTime) - => Enumerable.Empty(); + => []; } diff --git a/src/EFCore.Relational/Metadata/RuntimeStoredProcedure.cs b/src/EFCore.Relational/Metadata/RuntimeStoredProcedure.cs index 45a171b79c3..313327da079 100644 --- a/src/EFCore.Relational/Metadata/RuntimeStoredProcedure.cs +++ b/src/EFCore.Relational/Metadata/RuntimeStoredProcedure.cs @@ -170,9 +170,8 @@ IReadOnlyList IStoredProcedure.Parameters /// IReadOnlyStoredProcedureParameter? IReadOnlyStoredProcedure.FindParameter(string propertyName) - => _parameters.FirstOrDefault( - (IReadOnlyStoredProcedureParameter p) - => p.ForOriginalValue == false && p.PropertyName == propertyName); + => _parameters.FirstOrDefault((IReadOnlyStoredProcedureParameter p) + => p.ForOriginalValue == false && p.PropertyName == propertyName); /// [DebuggerStepThrough] @@ -181,9 +180,8 @@ IReadOnlyList IStoredProcedure.Parameters /// IReadOnlyStoredProcedureParameter? IReadOnlyStoredProcedure.FindOriginalValueParameter(string propertyName) - => _parameters.FirstOrDefault( - (IReadOnlyStoredProcedureParameter p) - => p.ForOriginalValue == true && p.PropertyName == propertyName); + => _parameters.FirstOrDefault((IReadOnlyStoredProcedureParameter p) + => p.ForOriginalValue == true && p.PropertyName == propertyName); /// IStoredProcedureParameter? IStoredProcedure.FindOriginalValueParameter(string propertyName) @@ -191,9 +189,8 @@ IReadOnlyList IStoredProcedure.Parameters /// IReadOnlyStoredProcedureParameter? IReadOnlyStoredProcedure.FindRowsAffectedParameter() - => _parameters.FirstOrDefault( - (IStoredProcedureParameter p) - => p.ForRowsAffected); + => _parameters.FirstOrDefault((IStoredProcedureParameter p) + => p.ForRowsAffected); /// IStoredProcedureParameter? IStoredProcedure.FindRowsAffectedParameter() @@ -215,9 +212,8 @@ IReadOnlyList IStoredProcedure.ResultColumns /// IReadOnlyStoredProcedureResultColumn? IReadOnlyStoredProcedure.FindResultColumn(string propertyName) - => _resultColumns.FirstOrDefault( - (IReadOnlyStoredProcedureResultColumn c) - => c.PropertyName == propertyName); + => _resultColumns.FirstOrDefault((IReadOnlyStoredProcedureResultColumn c) + => c.PropertyName == propertyName); /// IStoredProcedureResultColumn? IStoredProcedure.FindResultColumn(string propertyName) @@ -225,9 +221,8 @@ IReadOnlyList IStoredProcedure.ResultColumns /// IReadOnlyStoredProcedureResultColumn? IReadOnlyStoredProcedure.FindRowsAffectedResultColumn() - => _resultColumns.FirstOrDefault( - (IReadOnlyStoredProcedureResultColumn c) - => c.ForRowsAffected); + => _resultColumns.FirstOrDefault((IReadOnlyStoredProcedureResultColumn c) + => c.ForRowsAffected); /// IStoredProcedureResultColumn? IStoredProcedure.FindRowsAffectedResultColumn() diff --git a/src/EFCore.Relational/Migrations/HistoryRepository.cs b/src/EFCore.Relational/Migrations/HistoryRepository.cs index 9aa9d933f9a..48934123be0 100644 --- a/src/EFCore.Relational/Migrations/HistoryRepository.cs +++ b/src/EFCore.Relational/Migrations/HistoryRepository.cs @@ -95,12 +95,11 @@ private IModel EnsureModel() conventionSet.Remove(typeof(RelationalDbFunctionAttributeConvention)); var modelBuilder = new ModelBuilder(conventionSet); - modelBuilder.Entity( - x => - { - ConfigureTable(x); - x.ToTable(TableName, TableSchema); - }); + modelBuilder.Entity(x => + { + ConfigureTable(x); + x.ToTable(TableName, TableSchema); + }); _model = Dependencies.ModelRuntimeInitializer.Initialize( (IModel)modelBuilder.Model, designTime: true, validationLogger: null); @@ -191,7 +190,8 @@ public virtual void Create() /// public virtual Task CreateAsync(CancellationToken cancellationToken = default) => Dependencies.MigrationCommandExecutor.ExecuteNonQueryAsync( - GetCreateCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true, cancellationToken: cancellationToken); + GetCreateCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true, + cancellationToken: cancellationToken); /// /// Returns the migration commands that will create the history table. @@ -208,19 +208,17 @@ protected virtual IReadOnlyList GetCreateCommands() bool IHistoryRepository.CreateIfNotExists() => Dependencies.MigrationCommandExecutor.ExecuteNonQuery( - GetCreateIfNotExistsCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true) + GetCreateIfNotExistsCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true) != 0; async Task IHistoryRepository.CreateIfNotExistsAsync(CancellationToken cancellationToken) => (await Dependencies.MigrationCommandExecutor.ExecuteNonQueryAsync( - GetCreateIfNotExistsCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true, cancellationToken: cancellationToken).ConfigureAwait(false)) + GetCreateIfNotExistsCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true, + cancellationToken: cancellationToken).ConfigureAwait(false)) != 0; private IReadOnlyList GetCreateIfNotExistsCommands() - => Dependencies.MigrationsSqlGenerator.Generate([new SqlOperation - { - Sql = GetCreateIfNotExistsScript() - }]); + => Dependencies.MigrationsSqlGenerator.Generate([new SqlOperation { Sql = GetCreateIfNotExistsScript() }]); /// /// Gets an exclusive lock on the database. @@ -232,7 +230,6 @@ private IReadOnlyList GetCreateIfNotExistsCommands() /// Gets an exclusive lock on the database. /// /// A to observe while waiting for the task to complete. - /// /// An object that can be disposed to release the lock. /// If the is canceled. public abstract Task AcquireDatabaseLockAsync(CancellationToken cancellationToken = default); diff --git a/src/EFCore.Relational/Migrations/IHistoryRepository.cs b/src/EFCore.Relational/Migrations/IHistoryRepository.cs index 2189e6cea87..92779e48c83 100644 --- a/src/EFCore.Relational/Migrations/IHistoryRepository.cs +++ b/src/EFCore.Relational/Migrations/IHistoryRepository.cs @@ -66,6 +66,7 @@ bool CreateIfNotExists() Create(); return true; } + return false; } @@ -85,6 +86,7 @@ async Task CreateIfNotExistsAsync(CancellationToken cancellationToken = de await CreateAsync(cancellationToken).ConfigureAwait(false); return true; } + return false; } diff --git a/src/EFCore.Relational/Migrations/IMigrationCommandExecutor.cs b/src/EFCore.Relational/Migrations/IMigrationCommandExecutor.cs index 039bbaa4f15..d8ff9952a60 100644 --- a/src/EFCore.Relational/Migrations/IMigrationCommandExecutor.cs +++ b/src/EFCore.Relational/Migrations/IMigrationCommandExecutor.cs @@ -38,7 +38,7 @@ void ExecuteNonQuery( /// The state of the current migration execution. /// /// Indicates whether the transaction started by this call should be commited. - /// If , the transaction will be made available in . + /// If , the transaction will be made available in . /// /// The isolation level for the transaction. int ExecuteNonQuery( @@ -69,7 +69,7 @@ Task ExecuteNonQueryAsync( /// The state of the current migration execution. /// /// Indicates whether the transaction started by this call should be commited. - /// If , the transaction will be made available in . + /// If , the transaction will be made available in . /// /// The isolation level for the transaction. /// A to observe while waiting for the task to complete. diff --git a/src/EFCore.Relational/Migrations/IMigrationsAnnotationProvider.cs b/src/EFCore.Relational/Migrations/IMigrationsAnnotationProvider.cs index 15b0af28137..8cd6f12b5ce 100644 --- a/src/EFCore.Relational/Migrations/IMigrationsAnnotationProvider.cs +++ b/src/EFCore.Relational/Migrations/IMigrationsAnnotationProvider.cs @@ -107,7 +107,7 @@ public interface IMigrationsAnnotationProvider /// The table. /// The annotations. IEnumerable ForRename(ITable table) - => Enumerable.Empty(); + => []; /// /// Gets provider-specific Migrations annotations for the given @@ -116,7 +116,7 @@ IEnumerable ForRename(ITable table) /// The column. /// The annotations. IEnumerable ForRename(IColumn column) - => Enumerable.Empty(); + => []; /// /// Gets provider-specific Migrations annotations for the given @@ -125,7 +125,7 @@ IEnumerable ForRename(IColumn column) /// The index. /// The annotations. IEnumerable ForRename(ITableIndex index) - => Enumerable.Empty(); + => []; /// /// Gets provider-specific Migrations annotations for the given @@ -134,5 +134,5 @@ IEnumerable ForRename(ITableIndex index) /// The sequence. /// The annotations. IEnumerable ForRename(ISequence sequence) - => Enumerable.Empty(); + => []; } diff --git a/src/EFCore.Relational/Migrations/IMigrationsDatabaseLock.cs b/src/EFCore.Relational/Migrations/IMigrationsDatabaseLock.cs index b08ea1b9faa..770f3afb75b 100644 --- a/src/EFCore.Relational/Migrations/IMigrationsDatabaseLock.cs +++ b/src/EFCore.Relational/Migrations/IMigrationsDatabaseLock.cs @@ -12,7 +12,7 @@ namespace Microsoft.EntityFrameworkCore.Migrations; public interface IMigrationsDatabaseLock : IDisposable, IAsyncDisposable { /// - /// The history repository. + /// The history repository. /// protected IHistoryRepository HistoryRepository { get; } @@ -22,13 +22,13 @@ public interface IMigrationsDatabaseLock : IDisposable, IAsyncDisposable /// Indicates whether the connection was reopened. /// /// Indicates whether the transaction was restarted. - /// if there's no current transaction. + /// if there's no current transaction. /// /// An object that can be disposed to release the lock. IMigrationsDatabaseLock ReacquireIfNeeded(bool connectionReopened, bool? transactionRestarted) { if ((connectionReopened && HistoryRepository.LockReleaseBehavior == LockReleaseBehavior.Connection) - || (transactionRestarted is true && HistoryRepository.LockReleaseBehavior == LockReleaseBehavior.Transaction)) + || (transactionRestarted is true && HistoryRepository.LockReleaseBehavior == LockReleaseBehavior.Transaction)) { Dispose(); return HistoryRepository.AcquireDatabaseLock(); @@ -43,15 +43,17 @@ IMigrationsDatabaseLock ReacquireIfNeeded(bool connectionReopened, bool? transac /// Indicates whether the connection was reopened. /// /// Indicates whether the transaction was restarted. - /// if there's no current transaction. + /// if there's no current transaction. /// /// A to observe while waiting for the task to complete. /// An object that can be disposed to release the lock. async Task ReacquireIfNeededAsync( - bool connectionReopened, bool? transactionRestarted, CancellationToken cancellationToken = default) + bool connectionReopened, + bool? transactionRestarted, + CancellationToken cancellationToken = default) { if ((connectionReopened && HistoryRepository.LockReleaseBehavior == LockReleaseBehavior.Connection) - || (transactionRestarted is true && HistoryRepository.LockReleaseBehavior == LockReleaseBehavior.Transaction)) + || (transactionRestarted is true && HistoryRepository.LockReleaseBehavior == LockReleaseBehavior.Transaction)) { await DisposeAsync().ConfigureAwait(false); return await HistoryRepository.AcquireDatabaseLockAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/EFCore.Relational/Migrations/IMigrator.cs b/src/EFCore.Relational/Migrations/IMigrator.cs index b7735b4f0f7..c7d1bf45c11 100644 --- a/src/EFCore.Relational/Migrations/IMigrator.cs +++ b/src/EFCore.Relational/Migrations/IMigrator.cs @@ -32,8 +32,8 @@ public interface IMigrator /// /// See Database migrations for more information and examples. /// - [RequiresUnreferencedCode("Migration generation currently isn't compatible with trimming")] - [RequiresDynamicCode("Migrations operations are not supported with NativeAOT")] + [RequiresUnreferencedCode("Migration generation currently isn't compatible with trimming"), + RequiresDynamicCode("Migrations operations are not supported with NativeAOT")] void Migrate(string? targetMigration = null); /// @@ -49,8 +49,8 @@ public interface IMigrator /// See Database migrations for more information and examples. /// /// If the is canceled. - [RequiresUnreferencedCode("Migration generation currently isn't compatible with trimming")] - [RequiresDynamicCode("Migrations operations are not supported with NativeAOT")] + [RequiresUnreferencedCode("Migration generation currently isn't compatible with trimming"), + RequiresDynamicCode("Migrations operations are not supported with NativeAOT")] Task MigrateAsync( string? targetMigration = null, CancellationToken cancellationToken = default); @@ -72,8 +72,8 @@ Task MigrateAsync( /// The options to use when generating SQL for migrations. /// /// The generated script. - [RequiresUnreferencedCode("Migration generation currently isn't compatible with trimming")] - [RequiresDynamicCode("Migrations operations are not supported with NativeAOT")] + [RequiresUnreferencedCode("Migration generation currently isn't compatible with trimming"), + RequiresDynamicCode("Migrations operations are not supported with NativeAOT")] string GenerateScript( string? fromMigration = null, string? toMigration = null, diff --git a/src/EFCore.Relational/Migrations/Internal/MigrationCommandExecutor.cs b/src/EFCore.Relational/Migrations/Internal/MigrationCommandExecutor.cs index 7c1c8ef26ed..325132288bb 100644 --- a/src/EFCore.Relational/Migrations/Internal/MigrationCommandExecutor.cs +++ b/src/EFCore.Relational/Migrations/Internal/MigrationCommandExecutor.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Transactions; +using IsolationLevel = System.Data.IsolationLevel; namespace Microsoft.EntityFrameworkCore.Migrations.Internal; @@ -42,7 +43,7 @@ public virtual int ExecuteNonQuery( IRelationalConnection connection, MigrationExecutionState executionState, bool commitTransaction, - System.Data.IsolationLevel? isolationLevel = null) + IsolationLevel? isolationLevel = null) { var inUserTransaction = connection.CurrentTransaction is not null && executionState.Transaction == null; if (inUserTransaction @@ -71,11 +72,12 @@ private static int Execute( MigrationExecutionState executionState, bool beginTransaction, bool commitTransaction, - System.Data.IsolationLevel? isolationLevel) + IsolationLevel? isolationLevel) { var result = 0; var connectionOpened = connection.Open(); - Check.DebugAssert(!connectionOpened || executionState.Transaction == null, + Check.DebugAssert( + !connectionOpened || executionState.Transaction == null, "executionState.Transaction should be null"); try @@ -155,7 +157,8 @@ public virtual Task ExecuteNonQueryAsync( IRelationalConnection connection, CancellationToken cancellationToken = default) => ExecuteNonQueryAsync( - migrationCommands.ToList(), connection, new MigrationExecutionState(), commitTransaction: true, System.Data.IsolationLevel.Unspecified, cancellationToken); + migrationCommands.ToList(), connection, new MigrationExecutionState(), commitTransaction: true, IsolationLevel.Unspecified, + cancellationToken); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -168,7 +171,7 @@ public virtual async Task ExecuteNonQueryAsync( IRelationalConnection connection, MigrationExecutionState executionState, bool commitTransaction, - System.Data.IsolationLevel? isolationLevel = null, + IsolationLevel? isolationLevel = null, CancellationToken cancellationToken = default) { var inUserTransaction = connection.CurrentTransaction is not null && executionState.Transaction == null; @@ -200,12 +203,13 @@ private static async Task ExecuteAsync( MigrationExecutionState executionState, bool beginTransaction, bool commitTransaction, - System.Data.IsolationLevel? isolationLevel, + IsolationLevel? isolationLevel, CancellationToken cancellationToken) { var result = 0; var connectionOpened = await connection.OpenAsync(cancellationToken).ConfigureAwait(false); - Check.DebugAssert(!connectionOpened || executionState.Transaction == null, + Check.DebugAssert( + !connectionOpened || executionState.Transaction == null, "executionState.Transaction should be null"); try @@ -219,14 +223,14 @@ private static async Task ExecuteAsync( && beginTransaction) { executionState.Transaction = await (isolationLevel == null - ? connection.BeginTransactionAsync(cancellationToken) - : connection.BeginTransactionAsync(isolationLevel.Value, cancellationToken)) + ? connection.BeginTransactionAsync(cancellationToken) + : connection.BeginTransactionAsync(isolationLevel.Value, cancellationToken)) .ConfigureAwait(false); if (executionState.DatabaseLock != null) { executionState.DatabaseLock = await executionState.DatabaseLock.ReacquireIfNeededAsync( - connectionOpened, transactionRestarted: true, cancellationToken) + connectionOpened, transactionRestarted: true, cancellationToken) .ConfigureAwait(false); lockReacquired = true; } @@ -245,7 +249,7 @@ private static async Task ExecuteAsync( && !lockReacquired) { executionState.DatabaseLock = await executionState.DatabaseLock.ReacquireIfNeededAsync( - connectionOpened, transactionRestarted: null, cancellationToken) + connectionOpened, transactionRestarted: null, cancellationToken) .ConfigureAwait(false); } } @@ -275,6 +279,7 @@ private static async Task ExecuteAsync( await executionState.Transaction.DisposeAsync().ConfigureAwait(false); executionState.Transaction = null; } + await connection.CloseAsync().ConfigureAwait(false); throw; } diff --git a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs index 91a409a72f1..26305af61aa 100644 --- a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs +++ b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs @@ -266,9 +266,9 @@ protected virtual IReadOnlyList Sort( continue; } - var principalCreateTableOperation = createTableOperations.FirstOrDefault( - o => o.Name == addForeignKeyOperation.PrincipalTable - && o.Schema == addForeignKeyOperation.PrincipalSchema); + var principalCreateTableOperation = createTableOperations.FirstOrDefault(o + => o.Name == addForeignKeyOperation.PrincipalTable + && o.Schema == addForeignKeyOperation.PrincipalSchema); if (principalCreateTableOperation != null) { createTableGraph.AddEdge(principalCreateTableOperation, createTableOperation, addForeignKeyOperation); @@ -276,8 +276,8 @@ protected virtual IReadOnlyList Sort( } } - createTableOperations = (List)createTableGraph.TopologicalSort( - (_, createTableOperation, cyclicAddForeignKeyOperations) => + createTableOperations = + (List)createTableGraph.TopologicalSort((_, createTableOperation, cyclicAddForeignKeyOperations) => { foreach (var cyclicAddForeignKeyOperation in cyclicAddForeignKeyOperations) { @@ -312,13 +312,12 @@ protected virtual IReadOnlyList Sort( } var newDiffContext = new DiffContext(); - dropTableOperations = (List)dropTableGraph.TopologicalSort( - (_, _, foreignKeys) => - { - dropForeignKeyOperations.AddRange(foreignKeys.SelectMany(c => Remove(c, newDiffContext))); + dropTableOperations = (List)dropTableGraph.TopologicalSort((_, _, foreignKeys) => + { + dropForeignKeyOperations.AddRange(foreignKeys.SelectMany(c => Remove(c, newDiffContext))); - return true; - }); + return true; + }); return dropForeignKeyOperations .Concat(dropTableOperations) @@ -374,7 +373,7 @@ protected virtual IEnumerable Diff( alterDatabaseOperation.AddAnnotations(targetMigrationsAnnotations); alterDatabaseOperation.OldDatabase.AddAnnotations(sourceMigrationsAnnotations); - operations = new[] { alterDatabaseOperation }; + operations = [alterDatabaseOperation]; } operations = operations @@ -393,7 +392,7 @@ protected virtual IEnumerable Diff( ? Add(target, diffContext) : source != null ? Remove(source, diffContext) - : Enumerable.Empty(); + : []; } return operations.Concat(GetDataOperations(source, target, diffContext)); @@ -496,7 +495,7 @@ protected virtual IEnumerable Diff( string source, string target, DiffContext diffContext) - => Enumerable.Empty(); + => []; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -516,7 +515,7 @@ protected virtual IEnumerable Add(string target, DiffContext /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected virtual IEnumerable Remove(string source, DiffContext diffContext) - => Enumerable.Empty(); + => []; #endregion @@ -552,9 +551,8 @@ protected virtual IEnumerable Diff( t.Name, StringComparison.OrdinalIgnoreCase), (s, t, _) => string.Equals(GetMainType(s).Name, GetMainType(t).Name, StringComparison.OrdinalIgnoreCase), - (s, t, _) => s.EntityTypeMappings.Any( - se => t.EntityTypeMappings.Any( - te => string.Equals(se.TypeBase.Name, te.TypeBase.Name, StringComparison.OrdinalIgnoreCase)))); + (s, t, _) => s.EntityTypeMappings.Any(se => t.EntityTypeMappings.Any(te => string.Equals( + se.TypeBase.Name, te.TypeBase.Name, StringComparison.OrdinalIgnoreCase)))); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -909,24 +907,18 @@ protected virtual IEnumerable Diff( (t, c) => Add(t, c), Remove, (s, t, _) => string.Equals(s.Name, t.Name, StringComparison.OrdinalIgnoreCase), - (s, t, c) => s.PropertyMappings.Any( - sm => - t.PropertyMappings.Any( - tm => - string.Equals(sm.Property.Name, tm.Property.Name, StringComparison.OrdinalIgnoreCase) - && EntityTypePathEquals(sm.Property.DeclaringType, tm.Property.DeclaringType, c))), - (s, t, _) => s.PropertyMappings.Any( - sm => - t.PropertyMappings.Any( - tm => - string.Equals(sm.Property.Name, tm.Property.Name, StringComparison.OrdinalIgnoreCase))), + (s, t, c) => s.PropertyMappings.Any(sm => + t.PropertyMappings.Any(tm => + string.Equals(sm.Property.Name, tm.Property.Name, StringComparison.OrdinalIgnoreCase) + && EntityTypePathEquals(sm.Property.DeclaringType, tm.Property.DeclaringType, c))), + (s, t, _) => s.PropertyMappings.Any(sm => + t.PropertyMappings.Any(tm => + string.Equals(sm.Property.Name, tm.Property.Name, StringComparison.OrdinalIgnoreCase))), (s, t, c) => ColumnStructureEquals(s, t) - && s.PropertyMappings.Any( - sm => - t.PropertyMappings.Any( - tm => - string.Equals(sm.Property.Name, tm.Property.Name, StringComparison.OrdinalIgnoreCase) - && EntityTypePathEquals(sm.Property.DeclaringType, tm.Property.DeclaringType, c))), + && s.PropertyMappings.Any(sm => + t.PropertyMappings.Any(tm => + string.Equals(sm.Property.Name, tm.Property.Name, StringComparison.OrdinalIgnoreCase) + && EntityTypePathEquals(sm.Property.DeclaringType, tm.Property.DeclaringType, c))), (s, t, _) => ColumnStructureEquals(s, t) && ColumnAnnotationsEqual(s, t, matchValues: true), (s, t, _) => ColumnStructureEquals(s, t) && ColumnAnnotationsEqual(s, t, matchValues: false), (s, t, _) => ColumnStructureEquals(s, t)); @@ -1035,10 +1027,7 @@ private static bool EntityTypePathEquals(ITypeBase source, ITypeBase target, Dif { var nextSource = sourceComplexType.ComplexProperty.DeclaringType; var nextTarget = targetComplexType.ComplexProperty.DeclaringType; - return (nextSource == null && nextTarget == null) - || (nextSource != null - && nextTarget != null - && EntityTypePathEquals(nextSource, nextTarget, diffContext)); + return EntityTypePathEquals(nextSource, nextTarget, diffContext); } return false; @@ -1247,9 +1236,9 @@ private void Initialize( defaultValue = !inline && column is { - IsNullable: false, StoreTypeMapping: { ElementTypeMapping: not null, Converter: ValueConverter columnValueConverter } + IsNullable: false, StoreTypeMapping: { ElementTypeMapping: not null, Converter: { } columnValueConverter } } - && columnValueConverter.GetType() is Type { IsGenericType: true } columnValueConverterType + && columnValueConverter.GetType() is { IsGenericType: true } columnValueConverterType && columnValueConverterType.GetGenericTypeDefinition() == typeof(CollectionToJsonStringConverter<>) ? "[]" : null; @@ -1332,7 +1321,7 @@ protected virtual IEnumerable Diff( IUniqueConstraint source, IUniqueConstraint target, DiffContext diffContext) - => Enumerable.Empty(); + => []; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -1429,7 +1418,7 @@ protected virtual IEnumerable Diff( IForeignKeyConstraint source, IForeignKeyConstraint target, DiffContext diffContext) - => Enumerable.Empty(); + => []; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -1623,7 +1612,7 @@ protected virtual IEnumerable Diff( ICheckConstraint source, ICheckConstraint target, DiffContext diffContext) - => Enumerable.Empty(); + => []; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -2030,7 +2019,7 @@ private void AddSeedData(IEntityType entityType, Dictionary GetDataOperations( var commands = identityMaps.Values .SelectMany(m => m.Rows) - .Where( - r => r.EntityState is EntityState.Added or EntityState.Modified - || (r.EntityState is EntityState.Deleted && diffContext.FindDrop(r.Table!) == null)); + .Where(r => r.EntityState is EntityState.Added or EntityState.Modified + || (r.EntityState is EntityState.Deleted && diffContext.FindDrop(r.Table!) == null)); var commandSets = new CommandBatchPreparer(CommandBatchPreparerDependencies) .TopologicalSort(commands); @@ -2492,8 +2480,8 @@ protected virtual bool HasDifferences(IEnumerable source, IEnumerab var unmatched = new List(target); foreach (var annotation in source) { - var index = unmatched.FindIndex( - a => a.Name == annotation.Name && StructuralComparisons.StructuralEqualityComparer.Equals(a.Value, annotation.Value)); + var index = unmatched.FindIndex(a + => a.Name == annotation.Name && StructuralComparisons.StructuralEqualityComparer.Equals(a.Value, annotation.Value)); if (index == -1) { return true; @@ -2574,10 +2562,9 @@ private static IEntityType GetMainType(ITable table) private static string BuildValuesString(object?[] values) => "{" + string.Join( - ", ", values.Select( - p => p == null - ? "" - : Convert.ToString(p, CultureInfo.InvariantCulture))) + ", ", values.Select(p => p == null + ? "" + : Convert.ToString(p, CultureInfo.InvariantCulture))) + "}"; /// diff --git a/src/EFCore.Relational/Migrations/Internal/Migrator.cs b/src/EFCore.Relational/Migrations/Internal/Migrator.cs index 2d5989257aa..8e0d1ef5cd7 100644 --- a/src/EFCore.Relational/Migrations/Internal/Migrator.cs +++ b/src/EFCore.Relational/Migrations/Internal/Migrator.cs @@ -3,6 +3,7 @@ using System.Transactions; using Microsoft.EntityFrameworkCore.Diagnostics.Internal; +using IsolationLevel = System.Data.IsolationLevel; namespace Microsoft.EntityFrameworkCore.Migrations.Internal; @@ -82,7 +83,8 @@ public Migrator( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected virtual System.Data.IsolationLevel? MigrationTransactionIsolationLevel => null; + protected virtual IsolationLevel? MigrationTransactionIsolationLevel + => null; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -130,9 +132,9 @@ public virtual void Migrate(string? targetMigration) _executionStrategy.Execute( (Migrator: this, - TargetMigration: targetMigration, - State: state, - UseTransaction: useTransaction), + TargetMigration: targetMigration, + State: state, + UseTransaction: useTransaction), static (c, s) => s.Migrator.MigrateImplementation(c, s.TargetMigration, s.State, s.UseTransaction), static (_, s) => new ExecutionResult( successful: s.Migrator.VerifyMigrationSucceeded(s.TargetMigration, s.State), @@ -145,7 +147,10 @@ public virtual void Migrate(string? targetMigration) } private bool MigrateImplementation( - DbContext context, string? targetMigration, MigrationExecutionState state, bool useTransaction) + DbContext context, + string? targetMigration, + MigrationExecutionState state, + bool useTransaction) { var connectionOpened = _connection.Open(); try @@ -255,16 +260,16 @@ static async (_, migrator, ct) => cancellationToken).ConfigureAwait(false); await _executionStrategy.ExecuteAsync( - (Migrator: this, - TargetMigration: targetMigration, - State: state, - UseTransaction: useTransaction), - async static (c, s, ct) => await s.Migrator.MigrateImplementationAsync( - c, s.TargetMigration, s.State, s.UseTransaction, ct).ConfigureAwait(false), - async static (_, s, ct) => new ExecutionResult( - successful: await s.Migrator.VerifyMigrationSucceededAsync(s.TargetMigration, s.State, ct).ConfigureAwait(false), - result: true), - cancellationToken) + (Migrator: this, + TargetMigration: targetMigration, + State: state, + UseTransaction: useTransaction), + async static (c, s, ct) => await s.Migrator.MigrateImplementationAsync( + c, s.TargetMigration, s.State, s.UseTransaction, ct).ConfigureAwait(false), + async static (_, s, ct) => new ExecutionResult( + successful: await s.Migrator.VerifyMigrationSucceededAsync(s.TargetMigration, s.State, ct).ConfigureAwait(false), + result: true), + cancellationToken) .ConfigureAwait(false); } finally @@ -274,7 +279,11 @@ async static (c, s, ct) => await s.Migrator.MigrateImplementationAsync( } private async Task MigrateImplementationAsync( - DbContext context, string? targetMigration, MigrationExecutionState state, bool useTransaction, CancellationToken cancellationToken = default) + DbContext context, + string? targetMigration, + MigrationExecutionState state, + bool useTransaction, + CancellationToken cancellationToken = default) { var connectionOpened = await _connection.OpenAsync(cancellationToken).ConfigureAwait(false); try @@ -282,9 +291,9 @@ private async Task MigrateImplementationAsync( if (useTransaction) { state.Transaction = await (MigrationTransactionIsolationLevel == null - ? context.Database.BeginTransactionAsync(cancellationToken) - : context.Database.BeginTransactionAsync(MigrationTransactionIsolationLevel.Value, cancellationToken)) - .ConfigureAwait(false); + ? context.Database.BeginTransactionAsync(cancellationToken) + : context.Database.BeginTransactionAsync(MigrationTransactionIsolationLevel.Value, cancellationToken)) + .ConfigureAwait(false); state.DatabaseLock = state.DatabaseLock == null ? await _historyRepository.AcquireDatabaseLockAsync(cancellationToken).ConfigureAwait(false) @@ -308,7 +317,7 @@ private async Task MigrateImplementationAsync( } await _migrationCommandExecutor.ExecuteNonQueryAsync( - getCommands(), _connection, state, commitTransaction: false, MigrationTransactionIsolationLevel, cancellationToken) + getCommands(), _connection, state, commitTransaction: false, MigrationTransactionIsolationLevel, cancellationToken) .ConfigureAwait(false); } @@ -330,6 +339,7 @@ await _migrationCommandExecutor.ExecuteNonQueryAsync( { await state.Transaction.CommitAsync(cancellationToken).ConfigureAwait(false); } + return state.AnyOperationPerformed; } finally @@ -339,11 +349,13 @@ await _migrationCommandExecutor.ExecuteNonQueryAsync( state.DatabaseLock.Dispose(); state.DatabaseLock = null; } + if (state.Transaction != null) { await state.Transaction.DisposeAsync().ConfigureAwait(false); state.Transaction = null; } + await _connection.CloseAsync().ConfigureAwait(false); } } @@ -365,8 +377,8 @@ private void ValidateMigrations(bool useTransaction, string? targetMigration) _logger.ModelSnapshotNotFound(this, _migrationsAssembly); } else if (targetMigration == null - && RelationalResources.LogPendingModelChanges(_logger).WarningBehavior != WarningBehavior.Ignore - && HasPendingModelChanges()) + && RelationalResources.LogPendingModelChanges(_logger).WarningBehavior != WarningBehavior.Ignore + && HasPendingModelChanges()) { var modelSource = (ModelSource)_currentContext.Context.GetService(); #pragma warning disable EF1001 // Internal EF Core API usage. @@ -412,7 +424,7 @@ private void ValidateMigrations(bool useTransaction, string? targetMigration) ? migrationsToRevert[index + 1] : actualTargetMigration); if (migration.DownOperations.Count > 1 - && commands.FirstOrDefault(c => c.TransactionSuppressed) is MigrationCommand nonTransactionalCommand) + && commands.FirstOrDefault(c => c.TransactionSuppressed) is { } nonTransactionalCommand) { _logger.NonTransactionalMigrationOperationWarning(this, migration, nonTransactionalCommand); } @@ -429,7 +441,7 @@ private void ValidateMigrations(bool useTransaction, string? targetMigration) var commands = GenerateUpSql(migration); if (migration.UpOperations.Count > 1 - && commands.FirstOrDefault(c => c.TransactionSuppressed) is MigrationCommand nonTransactionalCommand) + && commands.FirstOrDefault(c => c.TransactionSuppressed) is { } nonTransactionalCommand) { _logger.NonTransactionalMigrationOperationWarning(this, migration, nonTransactionalCommand); } @@ -519,7 +531,8 @@ protected virtual void PopulateMigrations( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected virtual bool VerifyMigrationSucceeded( - string? targetMigration, MigrationExecutionState state) + string? targetMigration, + MigrationExecutionState state) => false; /// @@ -529,7 +542,9 @@ protected virtual bool VerifyMigrationSucceeded( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// protected virtual Task VerifyMigrationSucceededAsync( - string? targetMigration, MigrationExecutionState state, CancellationToken cancellationToken) + string? targetMigration, + MigrationExecutionState state, + CancellationToken cancellationToken) => Task.FromResult(false); /// @@ -552,7 +567,7 @@ public virtual string GenerateScript( if (string.IsNullOrEmpty(fromMigration) || fromMigration == Migration.InitialDatabase) { - appliedMigrations = Enumerable.Empty(); + appliedMigrations = []; } else { @@ -673,7 +688,7 @@ private static void GenerateSqlScript( } else { - builder .Append(Environment.NewLine); + builder.Append(Environment.NewLine); } } } @@ -700,7 +715,8 @@ protected virtual IReadOnlyList GenerateUpSql( return [ .. operations, - new MigrationCommand(insertCommand, _currentContext.Context, _commandLogger, + new MigrationCommand( + insertCommand, _currentContext.Context, _commandLogger, transactionSuppressed: operations.Any(o => o.TransactionSuppressed)), // If any command was transaction-suppressed then the migrations history table is also updated without a transaction // to decrease the risk that a non-recoverable exception happens during execution and the database is left in a broken state. @@ -727,13 +743,15 @@ protected virtual IReadOnlyList GenerateDownSql( previousMigration == null ? null : FinalizeModel(previousMigration.TargetModel), options); - return [ + return + [ .. operations, - new MigrationCommand(deleteCommand, _currentContext.Context, _commandLogger, + new MigrationCommand( + deleteCommand, _currentContext.Context, _commandLogger, transactionSuppressed: operations.Any(o => o.TransactionSuppressed)) // If any command was transaction-suppressed then the migrations history table is also updated without a transaction // to decrease the risk that a non-recoverable exception happens during execution and the database is left in a broken state. - ]; + ]; } private IModel? FinalizeModel(IModel? model) diff --git a/src/EFCore.Relational/Migrations/MigrationExecutionState.cs b/src/EFCore.Relational/Migrations/MigrationExecutionState.cs index accd83e0cfc..2f3b3e469a4 100644 --- a/src/EFCore.Relational/Migrations/MigrationExecutionState.cs +++ b/src/EFCore.Relational/Migrations/MigrationExecutionState.cs @@ -19,7 +19,7 @@ public sealed class MigrationExecutionState public string? CurrentMigrationId { get; set; } /// - /// Indicates whether any migration operation was performed. + /// Indicates whether any migration operation was performed. /// public bool AnyOperationPerformed { get; set; } diff --git a/src/EFCore.Relational/Migrations/MigrationsAnnotationProvider.cs b/src/EFCore.Relational/Migrations/MigrationsAnnotationProvider.cs index 8813f778429..5b1261afd9e 100644 --- a/src/EFCore.Relational/Migrations/MigrationsAnnotationProvider.cs +++ b/src/EFCore.Relational/Migrations/MigrationsAnnotationProvider.cs @@ -33,57 +33,57 @@ public MigrationsAnnotationProvider(MigrationsAnnotationProviderDependencies dep /// public virtual IEnumerable ForRemove(IRelationalModel model) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRemove(ITable table) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRemove(IColumn column) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRemove(IView view) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRemove(IViewColumn column) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRemove(IUniqueConstraint constraint) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRemove(ITableIndex index) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRemove(IForeignKeyConstraint foreignKey) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRemove(ISequence sequence) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRemove(ICheckConstraint checkConstraint) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRename(ITable table) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRename(IColumn column) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRename(ITableIndex index) - => Enumerable.Empty(); + => []; /// public virtual IEnumerable ForRename(ISequence sequence) - => Enumerable.Empty(); + => []; } diff --git a/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs b/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs index 9db17d862fe..b8c70fc1195 100644 --- a/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs +++ b/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs @@ -1834,7 +1834,7 @@ protected virtual bool HasLegacyRenameOperations(IModel? model) /// if the version could be retrieved. protected virtual bool TryGetVersion([NotNullWhen(true)] IModel? model, [NotNullWhen(true)] out string? version) { - if (!(model?.GetProductVersion() is string versionString)) + if (!(model?.GetProductVersion() is { } versionString)) { version = null; diff --git a/src/EFCore.Relational/Query/Internal/QueryableAggregateMethodTranslator.cs b/src/EFCore.Relational/Query/Internal/QueryableAggregateMethodTranslator.cs index d8d48b77835..c9df8fc4da0 100644 --- a/src/EFCore.Relational/Query/Internal/QueryableAggregateMethodTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/QueryableAggregateMethodTranslator.cs @@ -60,7 +60,7 @@ public QueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpressionFac ? _sqlExpressionFactory.Convert( _sqlExpressionFactory.Function( "AVG", - new[] { averageSqlExpression }, + [averageSqlExpression], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[1], typeof(double)), @@ -68,7 +68,7 @@ public QueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpressionFac averageSqlExpression.TypeMapping) : _sqlExpressionFactory.Function( "AVG", - new[] { averageSqlExpression }, + [averageSqlExpression], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[1], averageSqlExpression.Type, @@ -83,7 +83,7 @@ public QueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpressionFac countSqlExpression = CombineTerms(source, countSqlExpression); return _sqlExpressionFactory.Function( "COUNT", - new[] { countSqlExpression }, + [countSqlExpression], nullable: false, argumentsPropagateNullability: Statics.FalseArrays[1], typeof(int)); @@ -95,7 +95,7 @@ public QueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpressionFac longCountSqlExpression = CombineTerms(source, longCountSqlExpression); return _sqlExpressionFactory.Function( "COUNT", - new[] { longCountSqlExpression }, + [longCountSqlExpression], nullable: false, argumentsPropagateNullability: Statics.FalseArrays[1], typeof(long)); @@ -107,7 +107,7 @@ public QueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpressionFac maxSqlExpression = CombineTerms(source, maxSqlExpression); return _sqlExpressionFactory.Function( "MAX", - new[] { maxSqlExpression }, + [maxSqlExpression], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[1], maxSqlExpression.Type, @@ -120,7 +120,7 @@ public QueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpressionFac minSqlExpression = CombineTerms(source, minSqlExpression); return _sqlExpressionFactory.Function( "MIN", - new[] { minSqlExpression }, + [minSqlExpression], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[1], minSqlExpression.Type, @@ -136,7 +136,7 @@ public QueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpressionFac ? _sqlExpressionFactory.Convert( _sqlExpressionFactory.Function( "SUM", - new[] { sumSqlExpression }, + [sumSqlExpression], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[1], typeof(double)), @@ -144,7 +144,7 @@ public QueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpressionFac sumSqlExpression.TypeMapping) : _sqlExpressionFactory.Function( "SUM", - new[] { sumSqlExpression }, + [sumSqlExpression], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[1], sumInputType, diff --git a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs index e7ba5c61764..8184f7ef030 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalCommandCache.cs @@ -119,8 +119,7 @@ internal CommandCacheKey(Expression queryExpression, IReadOnlyDictionary _visitedFromSqlExpre /// /// Contains parameter names seen so far, for uniquification. These parameter names have already gone through - /// (i.e. they're prefixed), since + /// (i.e. they're prefixed), since /// can be prefixed or not. /// - private readonly HashSet _prefixedParameterNames = new(); + private readonly HashSet _prefixedParameterNames = []; private readonly Dictionary _sqlParameters = new(); @@ -112,7 +112,7 @@ private SqlParameterExpression VisitSqlParameter(SqlParameterExpression paramete // that we need to ensure that there's only ever one type mapping instance (i.e. no type mappings are ever instantiated out of the // type mapping source). See #30677. if (_sqlParameters.TryGetValue(parameter.InvariantName, out var existingParameter) - && existingParameter is { TypeMapping: RelationalTypeMapping existingTypeMapping } + && existingParameter is { TypeMapping: { } existingTypeMapping } && string.Equals(existingTypeMapping.StoreType, typeMapping.StoreType, StringComparison.OrdinalIgnoreCase) && (existingTypeMapping.Converter is null && typeMapping.Converter is null || existingTypeMapping.Converter is not null && existingTypeMapping.Converter.Equals(typeMapping.Converter))) @@ -214,11 +214,9 @@ object ProcessConstantValue(object? existingConstantValue) } void ProcessDbParameter(DbParameter dbParameter) - { - dbParameter.ParameterName = string.IsNullOrEmpty(dbParameter.ParameterName) + => dbParameter.ParameterName = string.IsNullOrEmpty(dbParameter.ParameterName) ? GenerateNewParameterName() : UniquifyParameterName(dbParameter.ParameterName); - } } private string GenerateNewParameterName() diff --git a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs index 610c974c741..35641457b6c 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs @@ -192,7 +192,7 @@ public virtual Expression Translate(SelectExpression selectExpression, Expressio && method.DeclaringType == typeof(Enumerable) && argument.Type.TryGetElementType(typeof(IQueryable<>)) != null) { - if (_queryableMethodTranslatingExpressionVisitor.TranslateSubquery(argument) is ShapedQueryExpression subquery) + if (_queryableMethodTranslatingExpressionVisitor.TranslateSubquery(argument) is { } subquery) { _clientProjections!.Add(subquery); // expression.Type here will be List @@ -389,7 +389,10 @@ protected override Expression VisitExtension(Expression extensionExpression) return QueryCompilationContext.NotTranslatedExpression; } - case CollectionResultExpression { QueryExpression: ProjectionBindingExpression projectionBindingExpression } collectionResultExpression: + case CollectionResultExpression + { + QueryExpression: ProjectionBindingExpression projectionBindingExpression + } collectionResultExpression: { // TODO this should not be needed at some point, we shouldn't be revisiting same projection. // This happens because we don't process result selector for Join/SelectMany directly. diff --git a/src/EFCore.Relational/Query/Internal/RelationalStructuralTypeMaterializerSource.cs b/src/EFCore.Relational/Query/Internal/RelationalStructuralTypeMaterializerSource.cs index b61477d3aad..156235bae60 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalStructuralTypeMaterializerSource.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalStructuralTypeMaterializerSource.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - namespace Microsoft.EntityFrameworkCore.Query.Internal; #pragma warning disable EF1001 // StructuralTypeMaterializerSource is pubternal @@ -20,5 +19,6 @@ public class RelationalStructuralTypeMaterializerSource(StructuralTypeMaterializ /// since they're not simply e.g. DbDataReader.GetFieldValue calls. /// So they're handled afterwards in the shaper, and need to be skipped. /// - protected override bool ReadComplexTypeDirectly(IComplexType complexType) => !complexType.IsMappedToJson(); + protected override bool ReadComplexTypeDirectly(IComplexType complexType) + => !complexType.IsMappedToJson(); } diff --git a/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs index 8b7cef3ab73..e262e1553b3 100644 --- a/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SqlExpressionSimplifyingExpressionVisitor.cs @@ -93,8 +93,8 @@ private static bool IsCompareTo([NotNullWhen(true)] CaseExpression? caseExpressi if (caseExpression is { Operand: null, ElseResult: null, WhenClauses.Count: 3 } && caseExpression.WhenClauses.All(c => c is { Test: SqlBinaryExpression, Result: SqlConstantExpression { Value: int } })) { - var whenClauses = caseExpression.WhenClauses.Select( - c => new { Test = (SqlBinaryExpression)c.Test, ResultValue = (int)((SqlConstantExpression)c.Result).Value! }).ToList(); + var whenClauses = caseExpression.WhenClauses.Select(c + => new { Test = (SqlBinaryExpression)c.Test, ResultValue = (int)((SqlConstantExpression)c.Result).Value! }).ToList(); if (whenClauses[0].Test.Left.Equals(whenClauses[1].Test.Left) && whenClauses[1].Test.Left.Equals(whenClauses[2].Test.Left) @@ -222,55 +222,55 @@ or ExpressionType.LessThan var left = (SqlExpression)Visit(sqlBinaryExpression.Left); var right = (SqlExpression)Visit(sqlBinaryExpression.Right); - if (sqlBinaryExpression.OperatorType is ExpressionType.AndAlso or ExpressionType.OrElse) + if (sqlBinaryExpression.OperatorType is not (ExpressionType.AndAlso or ExpressionType.OrElse) + || !TryGetInExpressionCandidateInfo(left, out var leftCandidateInfo) + || !TryGetInExpressionCandidateInfo(right, out var rightCandidateInfo) + || leftCandidateInfo.ColumnExpression != rightCandidateInfo.ColumnExpression + || leftCandidateInfo.OperationType != rightCandidateInfo.OperationType) { - if (TryGetInExpressionCandidateInfo(left, out var leftCandidateInfo) - && TryGetInExpressionCandidateInfo(right, out var rightCandidateInfo) - && leftCandidateInfo.ColumnExpression == rightCandidateInfo.ColumnExpression - && leftCandidateInfo.OperationType == rightCandidateInfo.OperationType) - { - // for relational nulls we can't combine comparisons that contain null - // a != 1 && a != null would be converted to a NOT IN (1, null), which never returns any results - // we need to keep it in the original form so that a != null gets converted to a IS NOT NULL instead - // for c# null semantics it's fine because null semantics visitor extracts null back into proper null checks - var leftValues = leftCandidateInfo.ValueOrValues switch - { - IReadOnlyList v => v, - SqlConstantExpression c when !_useRelationalNulls || c.Value is not null => new[] { c }, - _ => null - }; + return sqlBinaryExpression.Update(left, right); + } - var rightValues = rightCandidateInfo.ValueOrValues switch - { - IReadOnlyList v => v, - SqlConstantExpression c when !_useRelationalNulls || c.Value is not null => new[] { c }, - _ => null - }; + // for relational nulls we can't combine comparisons that contain null + // a != 1 && a != null would be converted to a NOT IN (1, null), which never returns any results + // we need to keep it in the original form so that a != null gets converted to a IS NOT NULL instead + // for c# null semantics it's fine because null semantics visitor extracts null back into proper null checks + var leftValues = leftCandidateInfo.ValueOrValues switch + { + IReadOnlyList v => v, + SqlConstantExpression c when !_useRelationalNulls || c.Value is not null => [c], + _ => null + }; - if (leftValues is not null && rightValues is not null) - { - // Union: - // a IN (1, 2) || a IN (2, 3) -> a IN (1, 2, 3) - // a IN (1, 2) || a = 3 -> a IN (1, 2, 3) - // a NOT IN (1, 2) && a <> 3 -> a NOT IN (1, 2, 3) - - // Intersection: - // a IN (1, 2, 3) && a IN (2, 3, 4) -> a IN (2, 3) - var inExpression = _sqlExpressionFactory.In( - leftCandidateInfo.ColumnExpression, - (leftCandidateInfo.OperationType, sqlBinaryExpression.OperatorType) is - (ExpressionType.Equal, ExpressionType.OrElse) or (ExpressionType.NotEqual, ExpressionType.AndAlso) - ? leftValues.Union(rightValues).ToArray() - : leftValues.Intersect(rightValues).ToArray()); - - return leftCandidateInfo.OperationType switch - { - ExpressionType.Equal => inExpression, - ExpressionType.NotEqual => _sqlExpressionFactory.Not(inExpression), - _ => throw new UnreachableException() - }; - } - } + var rightValues = rightCandidateInfo.ValueOrValues switch + { + IReadOnlyList v => v, + SqlConstantExpression c when !_useRelationalNulls || c.Value is not null => [c], + _ => null + }; + + if (leftValues is not null && rightValues is not null) + { + // Union: + // a IN (1, 2) || a IN (2, 3) -> a IN (1, 2, 3) + // a IN (1, 2) || a = 3 -> a IN (1, 2, 3) + // a NOT IN (1, 2) && a <> 3 -> a NOT IN (1, 2, 3) + + // Intersection: + // a IN (1, 2, 3) && a IN (2, 3, 4) -> a IN (2, 3) + var inExpression = _sqlExpressionFactory.In( + leftCandidateInfo.ColumnExpression, + (leftCandidateInfo.OperationType, sqlBinaryExpression.OperatorType) is + (ExpressionType.Equal, ExpressionType.OrElse) or (ExpressionType.NotEqual, ExpressionType.AndAlso) + ? leftValues.Union(rightValues).ToArray() + : leftValues.Intersect(rightValues).ToArray()); + + return leftCandidateInfo.OperationType switch + { + ExpressionType.Equal => inExpression, + ExpressionType.NotEqual => _sqlExpressionFactory.Not(inExpression), + _ => throw new UnreachableException() + }; } return sqlBinaryExpression.Update(left, right); diff --git a/src/EFCore.Relational/Query/Internal/TpcTablesExpression.cs b/src/EFCore.Relational/Query/Internal/TpcTablesExpression.cs index 00a30da2122..1832cee4850 100644 --- a/src/EFCore.Relational/Query/Internal/TpcTablesExpression.cs +++ b/src/EFCore.Relational/Query/Internal/TpcTablesExpression.cs @@ -101,9 +101,8 @@ public TpcTablesExpression Prune(IReadOnlyList discriminatorValues) { var subSelectExpressions = discriminatorValues.Count == 0 ? [SelectExpressions[0]] - : SelectExpressions.Where( - se => - discriminatorValues.Contains((string)((SqlConstantExpression)se.Projection[^1].Expression).Value!)).ToList(); + : SelectExpressions.Where(se => + discriminatorValues.Contains((string)((SqlConstantExpression)se.Projection[^1].Expression).Value!)).ToList(); Check.DebugAssert(subSelectExpressions.Count > 0, "TPC must have at least 1 table selected."); diff --git a/src/EFCore.Relational/Query/Internal/Translators/ComparisonTranslator.cs b/src/EFCore.Relational/Query/Internal/Translators/ComparisonTranslator.cs index 718ac057cd3..fe16ea58a5b 100644 --- a/src/EFCore.Relational/Query/Internal/Translators/ComparisonTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/Translators/ComparisonTranslator.cs @@ -61,15 +61,14 @@ public ComparisonTranslator(ISqlExpressionFactory sqlExpressionFactory) && right != null) { return _sqlExpressionFactory.Case( - new[] - { + [ new CaseWhenClause( _sqlExpressionFactory.Equal(left, right), _sqlExpressionFactory.Constant(0)), new CaseWhenClause( _sqlExpressionFactory.GreaterThan(left, right), _sqlExpressionFactory.Constant(1)), new CaseWhenClause( _sqlExpressionFactory.LessThan(left, right), _sqlExpressionFactory.Constant(-1)) - }, + ], null); } } diff --git a/src/EFCore.Relational/Query/Internal/Translators/EnumMethodTranslator.cs b/src/EFCore.Relational/Query/Internal/Translators/EnumMethodTranslator.cs index 2911a5a33d2..08620f4625d 100644 --- a/src/EFCore.Relational/Query/Internal/Translators/EnumMethodTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/Translators/EnumMethodTranslator.cs @@ -53,7 +53,7 @@ public EnumMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) } if (Equals(method, ToStringMethodInfo) - && instance is { Type.IsEnum: true, TypeMapping.Converter: ValueConverter converter } + && instance is { Type.IsEnum: true, TypeMapping.Converter: { } converter } && converter.GetType() is { IsGenericType: true } converterType) { switch (converterType) @@ -61,10 +61,9 @@ public EnumMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) case not null when converterType.GetGenericTypeDefinition() == typeof(EnumToNumberConverter<,>): var whenClauses = Enum.GetValues(instance.Type) .Cast() - .Select( - value => new CaseWhenClause( - _sqlExpressionFactory.Constant(value), - _sqlExpressionFactory.Constant(value.ToString(), typeof(string)))) + .Select(value => new CaseWhenClause( + _sqlExpressionFactory.Constant(value), + _sqlExpressionFactory.Constant(value.ToString(), typeof(string)))) .ToArray(); var elseResult = _sqlExpressionFactory.Coalesce( diff --git a/src/EFCore.Relational/Query/Internal/Translators/RandomTranslator.cs b/src/EFCore.Relational/Query/Internal/Translators/RandomTranslator.cs index 186975efc8a..0a50dc76076 100644 --- a/src/EFCore.Relational/Query/Internal/Translators/RandomTranslator.cs +++ b/src/EFCore.Relational/Query/Internal/Translators/RandomTranslator.cs @@ -42,9 +42,9 @@ public RandomTranslator(ISqlExpressionFactory sqlExpressionFactory) => MethodInfo.Equals(method) ? _sqlExpressionFactory.Function( "RAND", - Enumerable.Empty(), + [], nullable: false, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], method.ReturnType) : null; } diff --git a/src/EFCore.Relational/Query/JsonQueryExpression.cs b/src/EFCore.Relational/Query/JsonQueryExpression.cs index 72144dfc179..d9346a7f292 100644 --- a/src/EFCore.Relational/Query/JsonQueryExpression.cs +++ b/src/EFCore.Relational/Query/JsonQueryExpression.cs @@ -21,7 +21,10 @@ public class JsonQueryExpression : Expression, IPrintableExpression /// /// The structural type represented by this expression. /// A column containing the JSON value. - /// For owned entities, a map of key properties and columns they map to in the database. For complex types, . + /// + /// For owned entities, a map of key properties and columns they map to in the database. For complex types, + /// . + /// /// The CLR represented by this expression. /// Whether this expression represents a collection. public JsonQueryExpression( @@ -46,7 +49,10 @@ public JsonQueryExpression( /// /// The structural type represented by this expression. /// A column containing the JSON value. - /// For owned entities, a map of key properties and columns they map to in the database. For complex types, . + /// + /// For owned entities, a map of key properties and columns they map to in the database. For complex types, + /// . + /// /// The list of path segments leading to the entity from the root of the JSON stored in the column. /// The CLR represented by this expression. /// Whether this expression represents a collection. @@ -60,7 +66,9 @@ public JsonQueryExpression( bool collection, bool nullable) { - Check.DebugAssert(structuralType is not IEntityType entityType || entityType.FindPrimaryKey() is not null, "JsonQueryExpression over keyless entity type"); + Check.DebugAssert( + structuralType is not IEntityType entityType || entityType.FindPrimaryKey() is not null, + "JsonQueryExpression over keyless entity type"); StructuralType = structuralType; JsonColumn = jsonColumn; @@ -131,7 +139,7 @@ public virtual SqlExpression BindProperty(IProperty property) return new JsonScalarExpression( JsonColumn, - [.. Path, new(property.GetJsonPropertyName()!)], + [.. Path, new PathSegment(property.GetJsonPropertyName()!)], property.ClrType.UnwrapNullableType(), property.FindRelationalTypeMapping()!, IsNullable || property.IsNullable); @@ -245,7 +253,7 @@ public virtual JsonQueryExpression BindCollectionElement(SqlExpression collectio /// /// A new expression which has property set to true. public virtual JsonQueryExpression MakeNullable() - => new JsonQueryExpression( + => new( StructuralType, JsonColumn.MakeNullable(), KeyPropertyMap?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.MakeNullable()), @@ -298,8 +306,8 @@ public virtual JsonQueryExpression Update( && KeyPropertyMap is not null && keyPropertyMap.Count == KeyPropertyMap.Count && KeyPropertyMapEquals(keyPropertyMap)))) - ? this - : new JsonQueryExpression(StructuralType, jsonColumn, keyPropertyMap, Path, Type, IsCollection, IsNullable); + ? this + : new JsonQueryExpression(StructuralType, jsonColumn, keyPropertyMap, Path, Type, IsCollection, IsNullable); /// public override bool Equals(object? obj) diff --git a/src/EFCore.Relational/Query/PathSegment.cs b/src/EFCore.Relational/Query/PathSegment.cs index 9e27268b407..09828a0a2ca 100644 --- a/src/EFCore.Relational/Query/PathSegment.cs +++ b/src/EFCore.Relational/Query/PathSegment.cs @@ -52,11 +52,11 @@ public PathSegment(SqlExpression arrayIndex) public Expression Quote() => this switch { - { PropertyName: string propertyName } + { PropertyName: { } propertyName } => Expression.New( _pathSegmentPropertyConstructor ??= typeof(PathSegment).GetConstructor([typeof(string)])!, Expression.Constant(propertyName)), - { ArrayIndex: SqlExpression arrayIndex } + { ArrayIndex: { } arrayIndex } => Expression.New( _pathSegmentArrayIndexConstructor ??= typeof(PathSegment).GetConstructor([typeof(SqlExpression)])!, arrayIndex.Quote()), diff --git a/src/EFCore.Relational/Query/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs index 5f4483742b3..bfbc714476b 100644 --- a/src/EFCore.Relational/Query/QuerySqlGenerator.cs +++ b/src/EFCore.Relational/Query/QuerySqlGenerator.cs @@ -20,7 +20,7 @@ public class QuerySqlGenerator : SqlExpressionVisitor { private readonly IRelationalCommandBuilderFactory _relationalCommandBuilderFactory; private readonly ISqlGenerationHelper _sqlGenerationHelper; - private readonly HashSet _parameterNames = new(); + private readonly HashSet _parameterNames = []; private IRelationalCommandBuilder _relationalCommandBuilder; /// @@ -166,10 +166,9 @@ private static bool TryUnwrapBareSetOperation(SelectExpression selectExpression, GroupBy: [] } && selectExpression.Projection.Count == s.Source1.Projection.Count - && selectExpression.Projection.Select( - (pe, index) => pe.Expression is ColumnExpression column - && column.TableAlias == s.Alias - && column.Name == s.Source1.Projection[index].Alias) + && selectExpression.Projection.Select((pe, index) => pe.Expression is ColumnExpression column + && column.TableAlias == s.Alias + && column.Name == s.Source1.Projection[index].Alias) .All(e => e)) { setOperation = s; @@ -306,9 +305,8 @@ protected virtual bool TryGenerateWithoutWrappingSelect(SelectExpression selectE GroupBy.Count: 0, } && selectExpression.Projection.Count == valuesExpression.ColumnNames.Count - && selectExpression.Projection.Select( - (pe, index) => pe.Expression is ColumnExpression column - && column.Name == valuesExpression.ColumnNames[index]) + && selectExpression.Projection.Select((pe, index) => pe.Expression is ColumnExpression column + && column.Name == valuesExpression.ColumnNames[index]) .All(e => e)) { GenerateValues(valuesExpression); @@ -1577,7 +1575,7 @@ protected virtual void GenerateValues(ValuesExpression valuesExpression) // and generate a SELECT for it with the names, and a UNION ALL over the rest of the values. _relationalCommandBuilder.Append("SELECT "); - Check.DebugAssert(rowValues.Count > 0, "rowValues.Count > 0"); + Check.DebugAssert(rowValues.Count > 0); var firstRowValues = rowValues[0].Values; for (var i = 0; i < firstRowValues.Count; i++) { diff --git a/src/EFCore.Relational/Query/RelationalAggregateMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/RelationalAggregateMethodCallTranslatorProvider.cs index c8c58ce5f8b..f1e2802de69 100644 --- a/src/EFCore.Relational/Query/RelationalAggregateMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/RelationalAggregateMethodCallTranslatorProvider.cs @@ -25,7 +25,7 @@ public RelationalAggregateMethodCallTranslatorProvider(RelationalAggregateMethod var sqlExpressionFactory = dependencies.SqlExpressionFactory; _translators.AddRange( - new IAggregateMethodCallTranslator[] { new QueryableAggregateMethodTranslator(sqlExpressionFactory) }); + [new QueryableAggregateMethodTranslator(sqlExpressionFactory)]); } /// diff --git a/src/EFCore.Relational/Query/RelationalExpressionQuotingUtilities.cs b/src/EFCore.Relational/Query/RelationalExpressionQuotingUtilities.cs index 3a53643f098..8a0b8e0e1e4 100644 --- a/src/EFCore.Relational/Query/RelationalExpressionQuotingUtilities.cs +++ b/src/EFCore.Relational/Query/RelationalExpressionQuotingUtilities.cs @@ -128,10 +128,9 @@ IStoreFunction function public static Expression QuoteTags(ISet tags) => ListInit( New(typeof(HashSet)), - tags.Select( - t => ElementInit( - _hashSetAddMethod ??= typeof(HashSet).GetMethod(nameof(HashSet.Add))!, - Constant(t)))); + tags.Select(t => ElementInit( + _hashSetAddMethod ??= typeof(HashSet).GetMethod(nameof(HashSet.Add))!, + Constant(t)))); /// /// Quotes the annotations on a . @@ -141,12 +140,11 @@ public static Expression QuoteAnnotations(IReadOnlyDictionary)) : ListInit( New(_dictionaryConstructor ??= typeof(IDictionary).GetConstructor([])!), - annotations.Select( - a => ElementInit( - _dictionaryAddMethod ??= typeof(Dictionary).GetMethod("Add")!, + annotations.Select(a => ElementInit( + _dictionaryAddMethod ??= typeof(Dictionary).GetMethod("Add")!, + Constant(a.Key), + New( + _annotationConstructor ??= typeof(Annotation).GetConstructor([typeof(string), typeof(object)])!, Constant(a.Key), - New( - _annotationConstructor ??= typeof(Annotation).GetConstructor([typeof(string), typeof(object)])!, - Constant(a.Key), - Constant(a.Value))))); + Constant(a.Value))))); } diff --git a/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessorParameters.cs b/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessorParameters.cs index d0bc742fd83..75d7e04e4f8 100644 --- a/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessorParameters.cs +++ b/src/EFCore.Relational/Query/RelationalParameterBasedSqlProcessorParameters.cs @@ -24,7 +24,9 @@ public sealed record RelationalParameterBasedSqlProcessorParameters /// A value indicating if relational nulls should be used. /// Which translation mode should be used. [EntityFrameworkInternal] - public RelationalParameterBasedSqlProcessorParameters(bool useRelationalNulls, ParameterTranslationMode collectionParameterTranslationMode) + public RelationalParameterBasedSqlProcessorParameters( + bool useRelationalNulls, + ParameterTranslationMode collectionParameterTranslationMode) { UseRelationalNulls = useRelationalNulls; CollectionParameterTranslationMode = collectionParameterTranslationMode; diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.CreateSelect.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.CreateSelect.cs index 8dd443fe376..9774492a1a4 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.CreateSelect.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.CreateSelect.cs @@ -56,8 +56,7 @@ SelectExpression CreateRootSelectExpressionCore(IEntityType entityType) } else { - var innerColumns = keyProperties.Select( - p => CreateColumnExpression(p, table, alias, nullable: false)); + var innerColumns = keyProperties.Select(p => CreateColumnExpression(p, table, alias, nullable: false)); var joinPredicate = joinColumns .Zip(innerColumns, _sqlExpressionFactory.Equal) @@ -251,8 +250,7 @@ [new TableExpression(alias, table)], case RelationalAnnotationNames.TphMappingStrategy: case null: { - if (entityType.GetFunctionMappings().SingleOrDefault(e => e.IsDefaultFunctionMapping) is IFunctionMapping - functionMapping) + if (entityType.GetFunctionMappings().SingleOrDefault(e => e.IsDefaultFunctionMapping) is { } functionMapping) { var storeFunction = functionMapping.Table; @@ -349,7 +347,7 @@ SelectExpression GenerateSingleTableSelect(ITableBase table, TableExpressionBase var identifier = new List<(ColumnExpression Column, ValueComparer Comparer)>(); - if (entityType.FindPrimaryKey() is IKey primaryKey) + if (entityType.FindPrimaryKey() is { } primaryKey) { foreach (var property in primaryKey.Properties) { @@ -491,6 +489,8 @@ private void AddEntitySelectConditions(SelectExpression selectExpression, IEntit } } + return; + bool HasSiblings(IEntityType entityType) => entityType.BaseType?.GetDirectlyDerivedTypes().Any(i => i != entityType) == true; @@ -509,10 +509,9 @@ private void AddJsonNavigationBindings( Dictionary tableMap) { foreach (var ownedJsonNavigation in entityType.GetNavigationsInHierarchy() - .Where( - n => n.ForeignKey.IsOwnership - && n.TargetEntityType.IsMappedToJson() - && n.ForeignKey.PrincipalToDependent == n)) + .Where(n => n.ForeignKey.IsOwnership + && n.TargetEntityType.IsMappedToJson() + && n.ForeignKey.PrincipalToDependent == n)) { // Find the containing column for the owned JSON entity type, and then the table in the table map that // contains that column. @@ -606,7 +605,7 @@ protected virtual SelectExpression CreateSelect( // Skip also properties with no JSON name (i.e. shadow keys containing the index in the collection, which don't actually exist // in the JSON document and can't be bound to) - if (property.GetJsonPropertyName() is string jsonPropertyName) + if (property.GetJsonPropertyName() is { } jsonPropertyName) { propertyExpressions[property] = CreateColumnExpression( tableExpressionBase, jsonPropertyName, property.ClrType, property.GetRelationalTypeMapping(), @@ -629,10 +628,9 @@ protected virtual SelectExpression CreateSelect( var containerColumn = table.FindColumn(containerColumnName)!; var containerColumnTypeMapping = containerColumn.StoreTypeMapping; foreach (var ownedJsonNavigation in entityType.GetNavigationsInHierarchy() - .Where( - n => n.ForeignKey.IsOwnership - && n.TargetEntityType.IsMappedToJson() - && n.ForeignKey.PrincipalToDependent == n)) + .Where(n => n.ForeignKey.IsOwnership + && n.TargetEntityType.IsMappedToJson() + && n.ForeignKey.PrincipalToDependent == n)) { var targetEntityType = ownedJsonNavigation.TargetEntityType; var jsonNavigationName = ownedJsonNavigation.TargetEntityType.GetJsonPropertyName(); @@ -652,7 +650,8 @@ protected virtual SelectExpression CreateSelect( // need to remap key property map to use target entity key properties var newKeyPropertyMap = new Dictionary(); - var targetPrimaryKeyProperties = targetEntityType.FindPrimaryKey()!.Properties.Take(jsonQueryExpression.KeyPropertyMap!.Count); + var targetPrimaryKeyProperties = + targetEntityType.FindPrimaryKey()!.Properties.Take(jsonQueryExpression.KeyPropertyMap!.Count); var sourcePrimaryKeyProperties = entityType.FindPrimaryKey()!.Properties.Take(jsonQueryExpression.KeyPropertyMap.Count); foreach (var (target, source) in targetPrimaryKeyProperties.Zip(sourcePrimaryKeyProperties, (t, s) => (t, s))) @@ -712,7 +711,7 @@ private static ColumnExpression CreateColumnExpression(ProjectionExpression subq => new( subqueryProjection.Alias, tableAlias, - column: subqueryProjection.Expression is ColumnExpression { Column: IColumnBase column } ? column : null, + column: subqueryProjection.Expression is ColumnExpression { Column: { } column } ? column : null, subqueryProjection.Type, subqueryProjection.Expression.TypeMapping!, subqueryProjection.Expression switch diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs index 096b5c2fb84..cfe3bd09a37 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs @@ -93,7 +93,8 @@ bool TranslateSetters( return false; } - if (!_sqlTranslator.TryBindMember(_sqlTranslator.Visit(baseExpression), member, out var translatedBaseExpression, out var propertyBase)) + if (!_sqlTranslator.TryBindMember( + _sqlTranslator.Visit(baseExpression), member, out var translatedBaseExpression, out var propertyBase)) { AddTranslationErrorDetails(RelationalStrings.InvalidPropertyInSetProperty(propertySelector.Print())); return false; @@ -147,7 +148,7 @@ bool TranslateSetters( } if (!IsColumnOnSameTable(column, propertySelector) - || TranslateSqlSetterValueSelector(source, valueSelector, column) is not SqlExpression translatedValueSelector) + || TranslateSqlSetterValueSelector(source, valueSelector, column) is not { } translatedValueSelector) { return false; } @@ -169,10 +170,11 @@ bool TranslateSetters( if (complexType.IsMappedToJson()) { - throw new InvalidOperationException(RelationalStrings.ExecuteUpdateOverJsonIsNotSupported(complexType.DisplayName())); + throw new InvalidOperationException( + RelationalStrings.ExecuteUpdateOverJsonIsNotSupported(complexType.DisplayName())); } - if (TranslateSetterValueSelector(source, valueSelector, shaper.Type) is not Expression translatedValueSelector + if (TranslateSetterValueSelector(source, valueSelector, shaper.Type) is not { } translatedValueSelector || !TryProcessComplexType(shaper, translatedValueSelector)) { return false; @@ -234,7 +236,7 @@ bool TryProcessComplexType(StructuralTypeShaperExpression shaperExpression, Expr var rewrittenValueSelector = CreatePropertyAccessExpression(valueExpression, property); if (TranslateSqlSetterValueSelector( - source, rewrittenValueSelector, column) is not SqlExpression translatedValueSelector) + source, rewrittenValueSelector, column) is not { } translatedValueSelector) { return false; } @@ -251,7 +253,8 @@ bool TryProcessComplexType(StructuralTypeShaperExpression shaperExpression, Expr if (complexProperty.ComplexType.IsMappedToJson()) { - throw new InvalidOperationException(RelationalStrings.ExecuteUpdateOverJsonIsNotSupported(complexProperty.ComplexType.DisplayName())); + throw new InvalidOperationException( + RelationalStrings.ExecuteUpdateOverJsonIsNotSupported(complexProperty.ComplexType.DisplayName())); } var nestedShaperExpression = (StructuralTypeShaperExpression)projection.BindComplexProperty(complexProperty); @@ -317,8 +320,8 @@ constantExpression.Value is null } case MemberInitExpression memberInitExpression - when memberInitExpression.Bindings.SingleOrDefault( - mb => mb.Member.Name == property.Name) is MemberAssignment memberAssignment: + when memberInitExpression.Bindings.SingleOrDefault(mb => mb.Member.Name == property.Name) is MemberAssignment + memberAssignment: return memberAssignment.Expression; default: @@ -382,8 +385,8 @@ SqlParameterExpression parameter remappedValueSelector = Expression.Convert(remappedValueSelector, propertyType); } - if (_sqlTranslator.TranslateProjection(remappedValueSelector, applyDefaultTypeMapping: false) is not Expression - translatedValueSelector) + if (_sqlTranslator.TranslateProjection(remappedValueSelector, applyDefaultTypeMapping: false) is not + { } translatedValueSelector) { AddTranslationErrorDetails(RelationalStrings.InvalidValueInSetProperty(valueSelector.Print())); return null; @@ -427,7 +430,7 @@ SqlParameterExpression parameter return null; } - if (entityType.FindPrimaryKey() is not IKey pk) + if (entityType.FindPrimaryKey() is not { } pk) { AddTranslationErrorDetails( RelationalStrings.ExecuteOperationOnKeylessEntityTypeWithUnsupportedOperator( @@ -477,7 +480,7 @@ SqlParameterExpression parameter transparentIdentifierParameter) : valueExpression; - rewrittenSetters[i] = new(propertyExpression, valueExpression); + rewrittenSetters[i] = new ExecuteUpdateSetter(propertyExpression, valueExpression); } tableExpression = (TableExpression)outerSelectExpression.Tables[0]; @@ -597,6 +600,6 @@ private sealed class ParameterBasedComplexPropertyChainExpression( : Expression { public SqlParameterExpression ParameterExpression { get; } = parameterExpression; - public List ComplexPropertyChain { get; } = new() { firstComplexProperty }; + public List ComplexPropertyChain { get; } = [firstComplexProperty]; } } diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 61db3777263..189a569c715 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; -using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; @@ -64,7 +63,8 @@ public RelationalQueryableMethodTranslatingExpressionVisitor( _typeMappingSource = relationalDependencies.TypeMappingSource; _sqlExpressionFactory = sqlExpressionFactory; _subquery = false; - _collectionParameterTranslationMode = RelationalOptionsExtension.Extract(queryCompilationContext.ContextOptions).ParameterizedCollectionMode; + _collectionParameterTranslationMode = + RelationalOptionsExtension.Extract(queryCompilationContext.ContextOptions).ParameterizedCollectionMode; } /// @@ -90,7 +90,8 @@ protected RelationalQueryableMethodTranslatingExpressionVisitor( _typeMappingSource = parentVisitor._typeMappingSource; _sqlExpressionFactory = parentVisitor._sqlExpressionFactory; _subquery = true; - _collectionParameterTranslationMode = RelationalOptionsExtension.Extract(parentVisitor._queryCompilationContext.ContextOptions).ParameterizedCollectionMode; + _collectionParameterTranslationMode = RelationalOptionsExtension.Extract(parentVisitor._queryCompilationContext.ContextOptions) + .ParameterizedCollectionMode; } /// @@ -156,7 +157,7 @@ protected override Expression VisitExtension(Expression extensionExpression) case EntityQueryRootExpression entityQueryRootExpression when entityQueryRootExpression.GetType() == typeof(EntityQueryRootExpression) && entityQueryRootExpression.EntityType.GetSqlQueryMappings().FirstOrDefault(m => m.IsDefaultSqlQueryMapping)?.SqlQuery is - ISqlQuery sqlQuery: + { } sqlQuery: { var table = entityQueryRootExpression.EntityType.GetDefaultMappings().Single().Table; var alias = _sqlAliasManager.GenerateTableAlias(table); @@ -242,7 +243,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp && method.IsGenericMethod && method.GetGenericMethodDefinition() == QueryableMethods.Contains && methodCallExpression.Arguments[0] is ParameterQueryRootExpression parameterSource - && TranslateExpression(methodCallExpression.Arguments[1]) is SqlExpression item + && TranslateExpression(methodCallExpression.Arguments[1]) is { } item && _sqlTranslator.Visit(parameterSource.QueryParameterExpression) is SqlParameterExpression sqlParameterExpression && (parameterSource.QueryParameterExpression.TranslationMode is ParameterTranslationMode.Constant or null)) @@ -269,15 +270,15 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp { case IProperty { IsPrimitiveCollection: true } scalarProperty when translatedExpression is SqlExpression sqlExpression - && TranslatePrimitiveCollection( - sqlExpression, - scalarProperty, - _sqlAliasManager.GenerateTableAlias(GenerateTableAlias(sqlExpression))) is { } primitiveCollectionTranslation: + && TranslatePrimitiveCollection( + sqlExpression, + scalarProperty, + _sqlAliasManager.GenerateTableAlias(GenerateTableAlias(sqlExpression))) is { } primitiveCollectionTranslation: { return primitiveCollectionTranslation; } - case IComplexProperty { IsCollection: true, ComplexType: var complexType } complexProperty: + case IComplexProperty { IsCollection: true, ComplexType: var complexType }: Check.DebugAssert(complexType.IsMappedToJson()); if (translatedExpression is not CollectionResultExpression { QueryExpression: JsonQueryExpression jsonQuery }) @@ -296,9 +297,8 @@ string GenerateTableAlias(SqlExpression sqlExpression) { ColumnExpression c => c.Name, JsonScalarExpression jsonScalar - => jsonScalar.Path.LastOrDefault(s => s.PropertyName is not null) is PathSegment lastPropertyNameSegment - ? lastPropertyNameSegment.PropertyName! - : GenerateTableAlias(jsonScalar.Json), + => jsonScalar.Path.LastOrDefault(s => s.PropertyName is not null).PropertyName + ?? GenerateTableAlias(jsonScalar.Json), ScalarSubqueryExpression scalarSubquery => scalarSubquery.Subquery.Projection[0].Alias, _ => "collection" @@ -311,7 +311,7 @@ JsonScalarExpression jsonScalar var queryParameter = parameterQueryRootExpression.QueryParameterExpression; var sqlParameterExpression = _sqlTranslator.Visit(queryParameter) as SqlParameterExpression; - Check.DebugAssert(sqlParameterExpression is not null, "sqlParameterExpression is not null"); + Check.DebugAssert(sqlParameterExpression is not null); var tableAlias = _sqlAliasManager.GenerateTableAlias(sqlParameterExpression.Name.TrimStart('_')); @@ -392,7 +392,7 @@ ParameterTranslationMode.Constant or ParameterTranslationMode.MultipleParameters // Note that we specifically don't apply the default type mapping to the translation, to allow it to get inferred later based // on usage. if (TranslateExpression(inlineQueryRootExpression.Values[i], applyDefaultTypeMapping: false) - is not SqlExpression translatedValue) + is not { } translatedValue) { return null; } @@ -420,17 +420,17 @@ ParameterTranslationMode.Constant or ParameterTranslationMode.MultipleParameters var sqlExpression = sqlExpressions[i]; rowExpressions[i] = new RowValueExpression( - [ - // Since VALUES may not guarantee row ordering, we add an _ord value by which we'll order. - _sqlExpressionFactory.Constant(i, intTypeMapping), - // If no type mapping was inferred (i.e. no column in the inline collection), it's left null, to allow it to get - // inferred later based on usage. Note that for the element in the VALUES expression, we'll also apply an explicit - // CONVERT to make sure the database gets the right type (see - // RelationalTypeMappingPostprocessor.ApplyTypeMappingsOnValuesExpression) - sqlExpression.TypeMapping is null && inferredTypeMaping is not null - ? _sqlExpressionFactory.ApplyTypeMapping(sqlExpression, inferredTypeMaping) - : sqlExpression - ]); + [ + // Since VALUES may not guarantee row ordering, we add an _ord value by which we'll order. + _sqlExpressionFactory.Constant(i, intTypeMapping), + // If no type mapping was inferred (i.e. no column in the inline collection), it's left null, to allow it to get + // inferred later based on usage. Note that for the element in the VALUES expression, we'll also apply an explicit + // CONVERT to make sure the database gets the right type (see + // RelationalTypeMappingPostprocessor.ApplyTypeMappingsOnValuesExpression) + sqlExpression.TypeMapping is null && inferredTypeMaping is not null + ? _sqlExpressionFactory.ApplyTypeMapping(sqlExpression, inferredTypeMaping) + : sqlExpression + ]); } var alias = _sqlAliasManager.GenerateTableAlias("values"); @@ -558,7 +558,7 @@ protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression s { // Note that we don't apply the default type mapping to the item in order to allow it to be inferred from e.g. the subquery // projection on the other side. - if (TranslateExpression(item, applyDefaultTypeMapping: false) is not SqlExpression translatedItem + if (TranslateExpression(item, applyDefaultTypeMapping: false) is not { } translatedItem || !TryGetProjection(source, out var projection)) { // If the item can't be translated, we can't translate to an IN expression. @@ -764,8 +764,8 @@ protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression s var original2 = resultSelector.Parameters[1]; var newResultSelectorBody = new ReplacingExpressionVisitor( - new Expression[] { original1, original2 }, - new[] { groupByShaper.KeySelector, groupByShaper }) + [original1, original2], + [groupByShaper.KeySelector, groupByShaper]) .Visit(resultSelector.Body); newResultSelectorBody = ExpandSharedTypeEntities(selectExpression, newResultSelectorBody); @@ -1281,11 +1281,11 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp static bool SupportsLiftingDefaultIfEmpty(MethodInfo methodInfo) => methodInfo.IsGenericMethod - && methodInfo.GetGenericMethodDefinition() is var definition - && (definition == QueryableMethods.Select - || definition == QueryableMethods.OrderBy - || definition == QueryableMethods.OrderByDescending - || definition == QueryableMethods.Reverse); + && methodInfo.GetGenericMethodDefinition() is var definition + && (definition == QueryableMethods.Select + || definition == QueryableMethods.OrderBy + || definition == QueryableMethods.OrderByDescending + || definition == QueryableMethods.Reverse); } } @@ -1716,7 +1716,7 @@ when JsonQueryExpressionIsRootedIn(memberJqe, baselineJsonQuery): { if (subquery is MethodCallExpression { Method.IsGenericMethod: true } selectMethodCall && selectMethodCall.Method.GetGenericMethodDefinition() == QueryableMethods.Select - && selectMethodCall.Arguments[1].UnwrapLambdaFromQuote() is LambdaExpression selectorLambda + && selectMethodCall.Arguments[1].UnwrapLambdaFromQuote() is { } selectorLambda && StripIncludes(selectorLambda.Body) == selectorLambda.Parameters[0]) { subquery = selectMethodCall.Arguments[0]; @@ -1800,7 +1800,7 @@ protected override Expression VisitExtension(Expression extensionExpression) ? entityType.FindNavigation(member.MemberInfo) : entityType.FindNavigation(member.Name!); - if (navigation is { TargetEntityType: IEntityType targetEntityType } + if (navigation is { TargetEntityType: var targetEntityType } && targetEntityType.IsOwned()) { return ExpandOwnedNavigation(navigation); @@ -1879,13 +1879,12 @@ Expression ExpandOwnedNavigation(INavigation navigation) ? Expression.AndAlso( outerKey is NewArrayExpression newArrayExpression ? newArrayExpression.Expressions - .Select( - e => - { - var left = (e as UnaryExpression)?.Operand ?? e; + .Select(e => + { + var left = (e as UnaryExpression)?.Operand ?? e; - return Expression.NotEqual(left, Expression.Constant(null, left.Type)); - }) + return Expression.NotEqual(left, Expression.Constant(null, left.Type)); + }) .Aggregate(Expression.AndAlso) : Expression.NotEqual(outerKey, Expression.Constant(null, outerKey.Type)), keyComparison) @@ -1961,13 +1960,13 @@ static TableExpressionBase FindRootTableExpressionForColumn(SelectExpression sel // See comments on indexing-related hacks in VisitMethodCall above if (_bindComplexProperties - && type.FindComplexProperty(memberName) is IComplexProperty { IsCollection: true } complexProperty) + && type.FindComplexProperty(memberName) is { IsCollection: true } complexProperty) { Check.DebugAssert(complexProperty.ComplexType.IsMappedToJson()); if (queryableTranslator._sqlTranslator.TryBindMember( - queryableTranslator._sqlTranslator.Visit(source), MemberIdentity.Create(memberName), - out var translatedExpression, out _) + queryableTranslator._sqlTranslator.Visit(source), MemberIdentity.Create(memberName), + out var translatedExpression, out _) && translatedExpression is CollectionResultExpression { QueryExpression: JsonQueryExpression jsonQuery }) { return jsonQuery; @@ -2038,7 +2037,7 @@ private ShapedQueryExpression TranslateTwoParameterSelector(ShapedQueryExpressio var replacement2 = AccessField(transparentIdentifierType, transparentIdentifierParameter, "Inner"); var newResultSelector = Expression.Lambda( new ReplacingExpressionVisitor( - new[] { original1, original2 }, new[] { replacement1, replacement2 }) + [original1, original2], [replacement1, replacement2]) .Visit(resultSelector.Body), transparentIdentifierParameter); @@ -2173,7 +2172,7 @@ private static Expression MatchShaperNullabilityForSetOperation(Expression shape } if (selector == null - || TranslateExpression(selector) is not SqlExpression translatedSelector) + || TranslateExpression(selector) is not { } translatedSelector) { return null; } @@ -2194,7 +2193,8 @@ private static Expression MatchShaperNullabilityForSetOperation(Expression shape selectExpression.ClearOrdering(); // Sum case. Projection is always non-null. We read nullable value. - Expression shaper = new ProjectionBindingExpression(source.QueryExpression, new ProjectionMember(), translation.Type.MakeNullable()); + Expression shaper = new ProjectionBindingExpression( + source.QueryExpression, new ProjectionMember(), translation.Type.MakeNullable()); if (resultType != shaper.Type) { diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs index fa7ced8e33a..77b611b08cd 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs @@ -85,8 +85,7 @@ private static readonly MethodInfo InverseCollectionFixupMethod /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [EntityFrameworkInternal] + [MethodImpl(MethodImplOptions.AggressiveInlining), EntityFrameworkInternal] public static TValue ThrowReadValueException( Exception exception, object? value, @@ -1028,9 +1027,6 @@ static async Task InitializeReaderAsync( case not JsonTokenType.StartArray: throw new InvalidOperationException(CoreStrings.JsonReaderInvalidTokenType(tokenType.ToString())); - - default: - break; } var collectionAccessor = relationship.GetCollectionAccessor(); diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index a6c6ea9b389..1027a6b380e 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -432,8 +432,7 @@ public LambdaExpression ProcessShaper( if (_isAsync) { var tasks = NewArrayInit( - typeof(Func), _collectionPopulatingExpressions.Select( - e => Lambda>(e))); + typeof(Func), _collectionPopulatingExpressions.Select(e => Lambda>(e))); relatedDataLoaders = Lambda>( Call(TaskAwaiterMethodInfo, tasks), @@ -456,11 +455,11 @@ public LambdaExpression ProcessShaper( var initializationBlock = Block(_variables, _expressions); var conditionalMaterializationExpressions = new List - { - IfThen( - Equal(_valuesArrayExpression, Constant(null, typeof(object[]))), - initializationBlock) - }; + { + IfThen( + Equal(_valuesArrayExpression, Constant(null, typeof(object[]))), + initializationBlock) + }; conditionalMaterializationExpressions.AddRange(_collectionPopulatingExpressions); @@ -478,7 +477,6 @@ public LambdaExpression ProcessShaper( relationalCommandResolver = _generateCommandResolver ? _parentVisitor.CreateRelationalCommandResolverExpression(_selectExpression) : Constant(null, typeof(RelationalCommandCache)); - ; readerColumns = _readerColumns; collectionId = _collectionId; @@ -532,11 +530,11 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) var updatedExpression = newExpression.Update( [ _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( - ValueBuffer.Empty, - static _ => ValueBuffer.Empty, - "emptyValueBuffer", - typeof(ValueBuffer)), - newExpression.Arguments[1] + ValueBuffer.Empty, + static _ => ValueBuffer.Empty, + "emptyValueBuffer", + typeof(ValueBuffer)), + newExpression.Arguments[1] ]); return Assign(binaryExpression.Left, updatedExpression); @@ -551,11 +549,11 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) var updatedExpression = newExpression.Update( [ _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( - ValueBuffer.Empty, - static _ => ValueBuffer.Empty, - "emptyValueBuffer", - typeof(ValueBuffer)), - newExpression.Arguments[1] + ValueBuffer.Empty, + static _ => ValueBuffer.Empty, + "emptyValueBuffer", + typeof(ValueBuffer)), + newExpression.Arguments[1] ]); return Assign(binaryExpression.Left, updatedExpression); @@ -599,9 +597,9 @@ protected override Expression VisitExtension(Expression extensionExpression) switch (extensionExpression) { case RelationalStructuralTypeShaperExpression - { - ValueBufferExpression: ProjectionBindingExpression projectionBindingExpression - } shaper + { + ValueBufferExpression: ProjectionBindingExpression projectionBindingExpression + } shaper when !_inline: { // we can't cache ProjectionBindingExpression results for non-tracking queries @@ -658,7 +656,8 @@ protected override Expression VisitExtension(Expression extensionExpression) // json entity converted to query root and projected var entityParameter = Parameter(shaper.Type); _variables.Add(entityParameter); - var entityMaterializationExpression = (BlockExpression)_parentVisitor.InjectStructuralTypeMaterializers(shaper); + var entityMaterializationExpression = + (BlockExpression)_parentVisitor.InjectStructuralTypeMaterializers(shaper); var mappedProperties = queryableJsonEntityProjectionInfo.PropertyIndexMap.Keys.ToList(); Check.DebugAssert(mappedProperties.All(p => p is IProperty)); @@ -757,10 +756,10 @@ protected override Expression VisitExtension(Expression extensionExpression) } case CollectionResultExpression - { - QueryExpression: ProjectionBindingExpression projectionBindingExpression, - Relationship: IPropertyBase relationship, - } collectionResult + { + QueryExpression: ProjectionBindingExpression projectionBindingExpression, + Relationship: { } relationship, + } collectionResult when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonProjectionInfo: { var relatedStructuralType = relationship switch @@ -978,8 +977,8 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP Lambda>( NewArrayInit( typeof(Func), - relationalCollectionShaperExpression.ParentIdentifierValueComparers.Select( - vc => vc.ObjectEqualsExpression)), + relationalCollectionShaperExpression.ParentIdentifierValueComparers.Select(vc + => vc.ObjectEqualsExpression)), Parameter(typeof(MaterializerLiftableConstantContext), "_")), "parentIdentifierValueComparers", typeof(Func[])), @@ -989,8 +988,8 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP Lambda>( NewArrayInit( typeof(Func), - relationalCollectionShaperExpression.OuterIdentifierValueComparers.Select( - vc => vc.ObjectEqualsExpression)), + relationalCollectionShaperExpression.OuterIdentifierValueComparers.Select(vc + => vc.ObjectEqualsExpression)), Parameter(typeof(MaterializerLiftableConstantContext), "_")), "outerIdentifierValueComparers", typeof(Func[])), @@ -1000,8 +999,8 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP Lambda>( NewArrayInit( typeof(Func), - relationalCollectionShaperExpression.SelfIdentifierValueComparers.Select( - vc => vc.ObjectEqualsExpression)), + relationalCollectionShaperExpression.SelfIdentifierValueComparers.Select(vc + => vc.ObjectEqualsExpression)), Parameter(typeof(MaterializerLiftableConstantContext), "_")), "selfIdentifierValueComparers", typeof(Func[])), @@ -1116,8 +1115,8 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP Lambda>( NewArrayInit( typeof(Func), - relationalSplitCollectionShaperExpression.IdentifierValueComparers.Select( - vc => vc.ObjectEqualsExpression)), + relationalSplitCollectionShaperExpression.IdentifierValueComparers.Select(vc + => vc.ObjectEqualsExpression)), Parameter(typeof(MaterializerLiftableConstantContext), "_")), "identifierValueComparers", typeof(Func[])), @@ -1305,8 +1304,8 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP Lambda>( NewArrayInit( typeof(Func), - relationalCollectionShaperExpression.ParentIdentifierValueComparers.Select( - vc => vc.ObjectEqualsExpression)), + relationalCollectionShaperExpression.ParentIdentifierValueComparers.Select(vc + => vc.ObjectEqualsExpression)), Parameter(typeof(MaterializerLiftableConstantContext), "_")), "parentIdentifierValueComparers", typeof(Func[])), @@ -1316,8 +1315,8 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP Lambda>( NewArrayInit( typeof(Func), - relationalCollectionShaperExpression.OuterIdentifierValueComparers.Select( - vc => vc.ObjectEqualsExpression)), + relationalCollectionShaperExpression.OuterIdentifierValueComparers.Select(vc + => vc.ObjectEqualsExpression)), Parameter(typeof(MaterializerLiftableConstantContext), "_")), "parentIdentifierValueComparers", typeof(Func[])), @@ -1327,8 +1326,8 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP Lambda>( NewArrayInit( typeof(Func), - relationalCollectionShaperExpression.SelfIdentifierValueComparers.Select( - vc => vc.ObjectEqualsExpression)), + relationalCollectionShaperExpression.SelfIdentifierValueComparers.Select(vc + => vc.ObjectEqualsExpression)), Parameter(typeof(MaterializerLiftableConstantContext), "_")), "parentIdentifierValueComparers", typeof(Func[])), @@ -1439,8 +1438,8 @@ when GetProjectionIndex(projectionBindingExpression) is JsonProjectionInfo jsonP Lambda>( NewArrayInit( typeof(Func), - relationalSplitCollectionShaperExpression.IdentifierValueComparers.Select( - vc => vc.ObjectEqualsExpression)), + relationalSplitCollectionShaperExpression.IdentifierValueComparers.Select(vc + => vc.ObjectEqualsExpression)), Parameter(typeof(MaterializerLiftableConstantContext), "_")), "identifierValueComparers", typeof(Func[])), @@ -1604,7 +1603,9 @@ private Expression CreateJsonShapers( { nestedRelationships = nestedRelationships.Concat( entityType.GetNavigations() - .Where(n => n.TargetEntityType.IsMappedToJson() && n.ForeignKey.IsOwnership && n == n.ForeignKey.PrincipalToDependent)); + .Where(n => n.TargetEntityType.IsMappedToJson() + && n.ForeignKey.IsOwnership + && n == n.ForeignKey.PrincipalToDependent)); } foreach (var nestedRelationship in nestedRelationships) @@ -1887,7 +1888,7 @@ protected override Expression VisitSwitch(SwitchExpression switchExpression) [ { Body: BlockExpression { Expressions.Count: > 0 } body, - TestValues: [Expression onlyValueExpression] + TestValues: [{ } onlyValueExpression] } ] } @@ -2270,9 +2271,9 @@ protected override Expression VisitConditional(ConditionalExpression conditional resultBlockVariables.AddRange(ifFalseBlock.Variables.ToList()); - var instanceAssignment = ifFalseBlock.Expressions.OfType().Single( - e => e is { NodeType: ExpressionType.Assign, Left: ParameterExpression instance, Right: BlockExpression } - && instance.Type == structuralType.ClrType); + var instanceAssignment = ifFalseBlock.Expressions.OfType().Single(e + => e is { NodeType: ExpressionType.Assign, Left: ParameterExpression instance, Right: BlockExpression } + && instance.Type == structuralType.ClrType); var instanceAssignmentBody = (BlockExpression)instanceAssignment.Right; var newInstanceAssignmentVariables = instanceAssignmentBody.Variables.ToList(); @@ -2336,9 +2337,9 @@ protected override Expression VisitConditional(ConditionalExpression conditional var startTrackingAssignment = ifFalseBlock.Expressions .OfType() - .Single( - e => e is { NodeType: ExpressionType.Assign, Left: ParameterExpression instance, Right: ConditionalExpression } - && instance.Type == typeof(InternalEntityEntry)); + .Single(e => e is + { NodeType: ExpressionType.Assign, Left: ParameterExpression instance, Right: ConditionalExpression } + && instance.Type == typeof(InternalEntityEntry)); var startTrackingExpression = IfThen( @@ -2483,7 +2484,10 @@ internal void ProcessTopLevelComplexJsonProperties( { // Note that the following processes only top-level complex properties (where the projection is a dictionary of properties to their projection index). // For nested JSON types, CreateJsonShapers calls itself recursively. - if (shaper is RelationalStructuralTypeShaperExpression { ValueBufferExpression: ProjectionBindingExpression projectionBindingExpression } + if (shaper is RelationalStructuralTypeShaperExpression + { + ValueBufferExpression: ProjectionBindingExpression projectionBindingExpression + } && GetProjectionIndex(projectionBindingExpression) is Dictionary propertyMap) { foreach (var (property, projectionIndex) in propertyMap) @@ -2599,7 +2603,7 @@ internal ParameterExpression GenerateJsonReader(int jsonColumnIndex, ITypeBase s var keyAccessInfo = jsonProjectionInfo.KeyAccessInfo[i]; switch (keyAccessInfo) { - case { ConstantKeyValue: int constant }: + case { ConstantKeyValue: { } constant }: // if key access was a constant (and we have the actual value) add it directly to key values array // adding 1 to the value as we start keys from 1 and the array starts at 0 keyValues[i] = Convert( @@ -2607,7 +2611,7 @@ internal ParameterExpression GenerateJsonReader(int jsonColumnIndex, ITypeBase s typeof(object)); break; - case { KeyProperty: IProperty keyProperty }: + case { KeyProperty: { } keyProperty }: // if key value has IProperty, it must be a PK of the owner var projection = _selectExpression.Projection[keyAccessInfo.KeyProjectionIndex!.Value]; keyValues[i] = Convert( @@ -2699,13 +2703,13 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) Left: MethodCallExpression { Method: { IsGenericMethod: true } method, - Arguments: [_, _, Expression leftExpression] + Arguments: [_, _, { } leftExpression] }, - Right: Expression rightExpression + Right: var rightExpression } && leftExpression.TryGetNonNullConstantValue(out var property) && rightExpression is ConstantExpression or LiftableConstantExpression - && rightExpression.GetConstantValue() == null + && rightExpression.GetConstantValue() == null && method.GetGenericMethodDefinition() == Infrastructure.ExpressionExtensions.ValueBufferTryReadValueMethod) { return mappedProperties.Contains(property) @@ -2721,7 +2725,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp if (methodCallExpression is { Method: { IsGenericMethod: true } method, - Arguments: [_, _, Expression argumentExpression] + Arguments: [_, _, { } argumentExpression] } && argumentExpression.TryGetNonNullConstantValue(out var property) && method.GetGenericMethodDefinition() == Infrastructure.ExpressionExtensions.ValueBufferTryReadValueMethod @@ -3200,6 +3204,7 @@ private sealed class JsonCorrectOrderOfEntitiesForChangeTrackerValidator(SelectE private bool _insideCollection; private bool _insideInclude; private SelectExpression _selectExpression = selectExpression; + private readonly List<(IEntityType JsonEntityType, List<(IProperty? KeyProperty, int? ConstantKeyValue, int? KeyProjectionIndex)> KeyAccessInfo)> _projectedKeyAccessInfos = []; @@ -3227,9 +3232,8 @@ public void Validate(Expression expression) { for (var i = _projectedKeyAccessInfos.Count - 1; i >= 0; i--) { - if (_includedJsonEntityTypes.Any( - t => t == _projectedKeyAccessInfos[i].JsonEntityType - || _projectedKeyAccessInfos[i].JsonEntityType.IsInOwnershipPath(t))) + if (_includedJsonEntityTypes.Any(t => t == _projectedKeyAccessInfos[i].JsonEntityType + || _projectedKeyAccessInfos[i].JsonEntityType.IsInOwnershipPath(t))) { _projectedKeyAccessInfos.RemoveAt(i); } @@ -3427,7 +3431,8 @@ protected override Expression VisitExtension(Expression extensionExpression) RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution( nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution))); - case JsonProjectionInfo jsonCollectionProjectionInfo when collectionResultExpression.Relationship is INavigation navigation: + case JsonProjectionInfo jsonCollectionProjectionInfo + when collectionResultExpression.Relationship is INavigation navigation: { var jsonEntityType = navigation.TargetEntityType; diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs index 1c97795b66a..df54cef0bb0 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs @@ -63,7 +63,8 @@ public RelationalShapedQueryCompilingExpressionVisitor( _threadSafetyChecksEnabled = dependencies.CoreSingletonOptions.AreThreadSafetyChecksEnabled; _detailedErrorsEnabled = dependencies.CoreSingletonOptions.AreDetailedErrorsEnabled; _useRelationalNulls = RelationalOptionsExtension.Extract(queryCompilationContext.ContextOptions).UseRelationalNulls; - _collectionParameterTranslationMode = RelationalOptionsExtension.Extract(queryCompilationContext.ContextOptions).ParameterizedCollectionMode; + _collectionParameterTranslationMode = + RelationalOptionsExtension.Extract(queryCompilationContext.ContextOptions).ParameterizedCollectionMode; _isPrecompiling = queryCompilationContext.IsPrecompiling; } @@ -713,22 +714,21 @@ Expression GenerateRelationalCommandExpression(Dictionary param Constant(relationalCommandTemplate.LogCommandText, typeof(string)), NewArrayInit( typeof(IRelationalParameter), - relationalCommandTemplate.Parameters.Cast().Select( - p => (Expression)New( - _typeMappedRelationalParameterConstructor ??= typeof(TypeMappedRelationalParameter) - .GetConstructor( - [ - typeof(string), - typeof(string), - typeof(RelationalTypeMapping), - typeof(bool?), - typeof(ParameterDirection) - ])!, - Constant(p.InvariantName), - Constant(p.Name), - RelationalExpressionQuotingUtilities.QuoteTypeMapping(p.RelationalTypeMapping), - Constant(p.IsNullable, typeof(bool?)), - Constant(p.Direction))).ToArray())), + relationalCommandTemplate.Parameters.Cast().Select(p => (Expression)New( + _typeMappedRelationalParameterConstructor ??= typeof(TypeMappedRelationalParameter) + .GetConstructor( + [ + typeof(string), + typeof(string), + typeof(RelationalTypeMapping), + typeof(bool?), + typeof(ParameterDirection) + ])!, + Constant(p.InvariantName), + Constant(p.Name), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(p.RelationalTypeMapping), + Constant(p.IsNullable, typeof(bool?)), + Constant(p.Direction))).ToArray())), liftableConstantContextParameter), "relationalCommandTemplate", typeof(IRelationalCommandTemplate)); @@ -783,7 +783,7 @@ private sealed class SqlParameterLocator : ExpressionVisitor public IReadOnlySet LocateParameters(Expression selectExpression) { - _parameters = new HashSet(); + _parameters = []; Visit(selectExpression); return _parameters; } diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.StructuralEquality.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.StructuralEquality.cs index 93491a9102e..3429b624107 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.StructuralEquality.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.StructuralEquality.cs @@ -172,11 +172,10 @@ bool TryRewriteEntityEquality([NotNullWhen(true)] out SqlExpression? result) .ToList(); if (requiredNonPkProperties.Count > 0) { - condition = requiredNonPkProperties.Select( - p => Infrastructure.ExpressionExtensions.CreateEqualsExpression( - CreatePropertyAccessExpression(nonNullEntityReference, p), - Expression.Constant(null, p.ClrType.MakeNullable()), - nodeType != ExpressionType.Equal)) + condition = requiredNonPkProperties.Select(p => Infrastructure.ExpressionExtensions.CreateEqualsExpression( + CreatePropertyAccessExpression(nonNullEntityReference, p), + Expression.Constant(null, p.ClrType.MakeNullable()), + nodeType != ExpressionType.Equal)) .Aggregate((l, r) => nodeType == ExpressionType.Equal ? Expression.OrElse(l, r) : Expression.AndAlso(l, r)); } @@ -190,11 +189,10 @@ bool TryRewriteEntityEquality([NotNullWhen(true)] out SqlExpression? result) // - if entity is to be null, all the properties must be null // - if the entity is to be not null, at least one property must be not null var optionalPropertiesCondition = allNonPrincipalSharedNonPkProperties - .Select( - p => Infrastructure.ExpressionExtensions.CreateEqualsExpression( - CreatePropertyAccessExpression(nonNullEntityReference, p), - Expression.Constant(null, p.ClrType.MakeNullable()), - nodeType != ExpressionType.Equal)) + .Select(p => Infrastructure.ExpressionExtensions.CreateEqualsExpression( + CreatePropertyAccessExpression(nonNullEntityReference, p), + Expression.Constant(null, p.ClrType.MakeNullable()), + nodeType != ExpressionType.Equal)) .Aggregate((l, r) => nodeType == ExpressionType.Equal ? Expression.AndAlso(l, r) : Expression.OrElse(l, r)); condition = condition == null @@ -216,11 +214,10 @@ bool TryRewriteEntityEquality([NotNullWhen(true)] out SqlExpression? result) } result = (SqlExpression)Visit( - nullComparedEntityTypePrimaryKeyProperties.Select( - p => Infrastructure.ExpressionExtensions.CreateEqualsExpression( - CreatePropertyAccessExpression(nonNullEntityReference, p), - Expression.Constant(null, p.ClrType.MakeNullable()), - nodeType != ExpressionType.Equal)) + nullComparedEntityTypePrimaryKeyProperties.Select(p => Infrastructure.ExpressionExtensions.CreateEqualsExpression( + CreatePropertyAccessExpression(nonNullEntityReference, p), + Expression.Constant(null, p.ClrType.MakeNullable()), + nodeType != ExpressionType.Equal)) .Aggregate((l, r) => nodeType == ExpressionType.Equal ? Expression.OrElse(l, r) : Expression.AndAlso(l, r))); return true; @@ -268,15 +265,13 @@ bool TryRewriteEntityEquality([NotNullWhen(true)] out SqlExpression? result) } result = (SqlExpression)Visit( - primaryKeyProperties.Select( - p => Infrastructure.ExpressionExtensions.CreateEqualsExpression( - CreatePropertyAccessExpression(left, p), - CreatePropertyAccessExpression(right, p), - nodeType != ExpressionType.Equal)) - .Aggregate( - (l, r) => nodeType == ExpressionType.Equal - ? Expression.AndAlso(l, r) - : Expression.OrElse(l, r))); + primaryKeyProperties.Select(p => Infrastructure.ExpressionExtensions.CreateEqualsExpression( + CreatePropertyAccessExpression(left, p), + CreatePropertyAccessExpression(right, p), + nodeType != ExpressionType.Equal)) + .Aggregate((l, r) => nodeType == ExpressionType.Equal + ? Expression.AndAlso(l, r) + : Expression.OrElse(l, r))); return true; } @@ -338,7 +333,11 @@ bool TryRewriteComplexTypeEquality(bool collection, [NotNullWhen(true)] out SqlE // into complex properties to generate a flattened list of comparisons. // The moment we reach a a complex property that's mapped to JSON, we stop and generate a single comparison // for the whole complex type. - bool TryGenerateComparisons(IComplexType type, Expression left, Expression right, [NotNullWhen(true)] ref SqlExpression? comparisons) + bool TryGenerateComparisons( + IComplexType type, + Expression left, + Expression right, + [NotNullWhen(true)] ref SqlExpression? comparisons) { if (type.IsMappedToJson()) { @@ -363,7 +362,9 @@ SqlExpression Process(Expression expression) // JsonScalarExpression, which is our current representation for a complex JSON in the SQL tree // (as opposed to in the shaper) - see #36392. StructuralTypeReferenceExpression - { Parameter: StructuralTypeShaperExpression { ValueBufferExpression: JsonQueryExpression jsonQuery } } + { + Parameter: { ValueBufferExpression: JsonQueryExpression jsonQuery } + } => new JsonScalarExpression( jsonQuery.JsonColumn, jsonQuery.Path, @@ -390,18 +391,20 @@ SqlConstantExpression constant typeMapping: null), SqlParameterExpression parameter - => (SqlParameterExpression)Visit(_queryCompilationContext.RegisterRuntimeParameter( - $"{RuntimeParameterPrefix}{parameter.Name}", - Expression.Lambda( - Expression.Call( - SerializeComplexTypeToJsonMethod, - Expression.Constant(complexType), - Expression.MakeIndex( - Expression.Property(QueryCompilationContext.QueryContextParameter, nameof(QueryContext.Parameters)), - indexer: typeof(Dictionary).GetProperty("Item", [typeof(string)]), - [Expression.Constant(parameter.Name, typeof(string))]), - Expression.Constant(collection)), - QueryCompilationContext.QueryContextParameter))), + => (SqlParameterExpression)Visit( + _queryCompilationContext.RegisterRuntimeParameter( + $"{RuntimeParameterPrefix}{parameter.Name}", + Expression.Lambda( + Expression.Call( + SerializeComplexTypeToJsonMethod, + Expression.Constant(complexType), + Expression.MakeIndex( + Expression.Property( + QueryCompilationContext.QueryContextParameter, nameof(QueryContext.Parameters)), + indexer: typeof(Dictionary).GetProperty("Item", [typeof(string)]), + [Expression.Constant(parameter.Name, typeof(string))]), + Expression.Constant(collection)), + QueryCompilationContext.QueryContextParameter))), _ => throw new UnreachableException() }; @@ -462,7 +465,7 @@ private bool TryTranslatePropertyAccess(Expression target, IPropertyBase propert return translation is not null; } - Expression CreatePropertyAccessExpression(Expression target, IPropertyBase property) + private Expression CreatePropertyAccessExpression(Expression target, IPropertyBase property) { switch (target) { @@ -495,7 +498,8 @@ sqlConstantExpression.Value is null var newParameterName = $"{RuntimeParameterPrefix}{sqlParameterExpression.Name}_{property.Name}"; - return _queryCompilationContext.RegisterRuntimeParameter($"{RuntimeParameterPrefix}{sqlParameterExpression.Name}_{property.Name}", lambda); + return _queryCompilationContext.RegisterRuntimeParameter( + $"{RuntimeParameterPrefix}{sqlParameterExpression.Name}_{property.Name}", lambda); } case ParameterBasedComplexPropertyChainExpression chainExpression: @@ -524,8 +528,8 @@ sqlConstantExpression.Value is null } case MemberInitExpression memberInitExpression - when memberInitExpression.Bindings.SingleOrDefault( - mb => mb.Member.Name == property.Name) is MemberAssignment memberAssignment: + when memberInitExpression.Bindings.SingleOrDefault(mb => mb.Member.Name == property.Name) is MemberAssignment + memberAssignment: return memberAssignment.Expression; default: diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index 6b44c7c6784..5eed4a051e7 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -1,9 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections; using System.Diagnostics.CodeAnalysis; -using System.Text; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; @@ -130,7 +128,7 @@ protected virtual void AddTranslationErrorDetails(string details) { // This is the case of a structural type getting projected out via Select (possibly also an owned entity one day, if we stop // expanding them in pre-visitation) - StructuralTypeReferenceExpression { Parameter: StructuralTypeShaperExpression shaper } + StructuralTypeReferenceExpression { Parameter: { } shaper } => shaper, // Complex JSON collection getting projected out via Select @@ -631,12 +629,14 @@ protected override Expression VisitMember(MemberExpression memberExpression) { // Fold member access into conditional, i.e. transform // (test ? expr1 : expr2).Member -> (test ? expr1.Member : expr2.Member) - if (memberExpression.Expression is ConditionalExpression cond) { - return Visit(Expression.Condition( - cond.Test, - Expression.MakeMemberAccess(cond.IfTrue, memberExpression.Member), - Expression.MakeMemberAccess(cond.IfFalse, memberExpression.Member) - )); + if (memberExpression.Expression is ConditionalExpression cond) + { + return Visit( + Expression.Condition( + cond.Test, + Expression.MakeMemberAccess(cond.IfTrue, memberExpression.Member), + Expression.MakeMemberAccess(cond.IfFalse, memberExpression.Member) + )); } var innerExpression = Visit(memberExpression.Expression); @@ -869,7 +869,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp case { Method.Name: nameof(Math.Max) or nameof(Math.Min), - Arguments: [Expression argument1, Expression argument2] + Arguments: [{ } argument1, { } argument2] } when method.DeclaringType == typeof(Math): { var translatedArguments = new List(); @@ -882,7 +882,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp nameof(Math.Max) => GenerateGreatest(translatedArguments, returnType), nameof(Math.Min) => GenerateLeast(translatedArguments, returnType), _ => throw new UnreachableException() - } is SqlExpression translatedFunctionCall + } is { } translatedFunctionCall ? translatedFunctionCall : QueryCompilationContext.NotTranslatedExpression; @@ -1240,7 +1240,7 @@ private SqlExpression BindProperty(StructuralTypeReferenceExpression typeReferen { switch (typeReference) { - case { Parameter: StructuralTypeShaperExpression shaper }: + case { Parameter: { } shaper }: { var valueBufferExpression = Visit(shaper.ValueBufferExpression); if (valueBufferExpression is JsonQueryExpression jsonQueryExpression) @@ -1292,7 +1292,7 @@ private SqlExpression BindProperty(StructuralTypeReferenceExpression typeReferen // If all non principal shared properties are nullable then we need additional condition var atLeastOneNonNullValueInNullableColumnsCondition = nonPrincipalSharedNonPkProperties .Select(p => projection.BindProperty(p)) - .Select(c => (SqlExpression)_sqlExpressionFactory.NotEqual(c, _sqlExpressionFactory.Constant(null, c.Type))) + .Select(c => _sqlExpressionFactory.NotEqual(c, _sqlExpressionFactory.Constant(null, c.Type))) .Aggregate((a, b) => _sqlExpressionFactory.OrElse(a, b)); condition = condition == null @@ -1314,7 +1314,7 @@ private SqlExpression BindProperty(StructuralTypeReferenceExpression typeReferen // single result so either it is regular entity or a collection which always have their own table. } - case { Subquery: ShapedQueryExpression subquery }: + case { Subquery: { } subquery }: { var entityShaper = (StructuralTypeShaperExpression)subquery.ShaperExpression; var subSelectExpression = (SelectExpression)subquery.QueryExpression; @@ -1337,7 +1337,7 @@ private Expression BindComplexProperty(StructuralTypeReferenceExpression typeRef { switch (typeReference) { - case { Parameter: StructuralTypeShaperExpression shaper }: + case { Parameter: { } shaper }: switch (Visit(shaper.ValueBufferExpression)) { case StructuralTypeProjectionExpression structuralTypeProjection: @@ -1356,7 +1356,8 @@ private Expression BindComplexProperty(StructuralTypeReferenceExpression typeRef var nestedJsonQuery = jsonQuery.BindRelationship(complexProperty); return complexProperty.IsCollection - ? new CollectionResultExpression(nestedJsonQuery, complexProperty, elementType: complexProperty.ComplexType.ClrType) + ? new CollectionResultExpression( + nestedJsonQuery, complexProperty, elementType: complexProperty.ComplexType.ClrType) : new StructuralTypeReferenceExpression( new RelationalStructuralTypeShaperExpression( complexProperty.ComplexType, @@ -1367,7 +1368,7 @@ private Expression BindComplexProperty(StructuralTypeReferenceExpression typeRef throw new UnreachableException(); } - case { Subquery: ShapedQueryExpression }: + case { Subquery: not null }: throw new InvalidOperationException("Complex property binding over a subquery"); // TODO: #36296 default: @@ -1746,7 +1747,7 @@ public Expression Convert(Type type) } return StructuralType is IEntityType entityType - && entityType.GetDerivedTypes().FirstOrDefault(et => et.ClrType == type) is IEntityType derivedEntityType + && entityType.GetDerivedTypes().FirstOrDefault(et => et.ClrType == type) is { } derivedEntityType ? new StructuralTypeReferenceExpression(this, derivedEntityType) : QueryCompilationContext.NotTranslatedExpression; } diff --git a/src/EFCore.Relational/Query/RelationalStructuralTypeShaperExpression.cs b/src/EFCore.Relational/Query/RelationalStructuralTypeShaperExpression.cs index 36f27101064..8fd0aede428 100644 --- a/src/EFCore.Relational/Query/RelationalStructuralTypeShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalStructuralTypeShaperExpression.cs @@ -85,7 +85,7 @@ protected override LambdaExpression GenerateMaterializationCondition(ITypeBase t : Constant(entityType, typeof(IEntityType)); expressions.Add(Switch(discriminatorValueVariable, defaultBlock, switchCases)); - baseCondition = Lambda(Block(new[] { discriminatorValueVariable }, expressions), valueBufferParameter); + baseCondition = Lambda(Block([discriminatorValueVariable], expressions), valueBufferParameter); } else { @@ -113,10 +113,9 @@ protected override LambdaExpression GenerateMaterializationCondition(ITypeBase t if (requiredNonPkProperties.Count > 0) { condition = requiredNonPkProperties - .Select( - p => NotEqual( - valueBufferParameter.CreateValueBufferReadValueExpression(typeof(object), p.GetIndex(), p), - Constant(null))) + .Select(p => NotEqual( + valueBufferParameter.CreateValueBufferReadValueExpression(typeof(object), p.GetIndex(), p), + Constant(null))) .Aggregate(AndAlso); } @@ -126,10 +125,9 @@ protected override LambdaExpression GenerateMaterializationCondition(ITypeBase t && allNonPrincipalSharedNonPkProperties.All(p => p.IsNullable)) { var atLeastOneNonNullValueInNullablePropertyCondition = allNonPrincipalSharedNonPkProperties - .Select( - p => NotEqual( - valueBufferParameter.CreateValueBufferReadValueExpression(typeof(object), p.GetIndex(), p), - Constant(null))) + .Select(p => NotEqual( + valueBufferParameter.CreateValueBufferReadValueExpression(typeof(object), p.GetIndex(), p), + Constant(null))) .Aggregate(OrElse); condition = condition == null diff --git a/src/EFCore.Relational/Query/RelationalTypeMappingPostprocessor.cs b/src/EFCore.Relational/Query/RelationalTypeMappingPostprocessor.cs index e2851f99d60..07ebd1da061 100644 --- a/src/EFCore.Relational/Query/RelationalTypeMappingPostprocessor.cs +++ b/src/EFCore.Relational/Query/RelationalTypeMappingPostprocessor.cs @@ -140,7 +140,7 @@ protected virtual ValuesExpression ApplyTypeMappingsOnValuesExpression(ValuesExp switch (valuesExpression) { // Regular VALUES over a collection of scalar values. Apply the inferred type mappings on each of the values. - case { RowValues: IReadOnlyList rowValues }: + case { RowValues: { } rowValues }: { var newRowValues = new RowValueExpression[rowValues.Count]; for (var i = 0; i < newRowValues.Length; i++) @@ -152,7 +152,7 @@ protected virtual ValuesExpression ApplyTypeMappingsOnValuesExpression(ValuesExp var value = rowValue.Values[j]; if (value.TypeMapping is null - && inferredTypeMappings[j] is RelationalTypeMapping inferredTypeMapping) + && inferredTypeMappings[j] is { } inferredTypeMapping) { value = _sqlExpressionFactory.ApplyTypeMapping(value, inferredTypeMapping); } @@ -176,7 +176,7 @@ protected virtual ValuesExpression ApplyTypeMappingsOnValuesExpression(ValuesExp // VALUES over a values parameter (i.e. a parameter representing the entire collection, that will be constantized into the SQL // later). Apply the inferred type mapping on the parameter. case { ValuesParameter: { TypeMapping: null } valuesParameter } - when inferredTypeMappings[1] is RelationalTypeMapping elementTypeMapping: + when inferredTypeMappings[1] is { } elementTypeMapping: { if (RelationalDependencies.TypeMappingSource.FindMapping( valuesParameter.Type, QueryCompilationContext.Model, elementTypeMapping) is not @@ -241,7 +241,7 @@ private sealed class ColumnTypeMappingScanner : ExpressionVisitor protected override Expression VisitExtension(Expression node) { - if (node is TableExpressionBase { Alias: string tableAlias } table) + if (node is TableExpressionBase { Alias: { } tableAlias } table) { _tableAliasMap[tableAlias] = table.UnwrapJoin(); } diff --git a/src/EFCore.Relational/Query/SqlAliasManager.cs b/src/EFCore.Relational/Query/SqlAliasManager.cs index df484e8cecb..3edec3f5dda 100644 --- a/src/EFCore.Relational/Query/SqlAliasManager.cs +++ b/src/EFCore.Relational/Query/SqlAliasManager.cs @@ -152,7 +152,7 @@ public virtual Expression PostprocessAliases(Expression expression) private sealed class TableAliasCollector : ExpressionVisitor { - private readonly HashSet _tableAliases = new(); + private readonly HashSet _tableAliases = []; internal static HashSet Collect(Expression expression) { @@ -168,7 +168,7 @@ protected override Expression VisitExtension(Expression node) case ShapedQueryExpression shapedQuery: return shapedQuery.UpdateQueryExpression(Visit(shapedQuery.QueryExpression)); - case TableExpressionBase { Alias: string alias }: + case TableExpressionBase { Alias: { } alias }: _tableAliases.Add(alias); return base.VisitExtension(node); @@ -189,7 +189,7 @@ protected override Expression VisitExtension(Expression node) ShapedQueryExpression shapedQuery => shapedQuery.UpdateQueryExpression(Visit(shapedQuery.QueryExpression)), // Note that this skips joins (which wrap the table that has the actual alias), as well as the top-level select - TableExpressionBase { Alias: string alias } table when aliasRewritingMap.TryGetValue(alias, out var newAlias) + TableExpressionBase { Alias: { } alias } table when aliasRewritingMap.TryGetValue(alias, out var newAlias) => base.VisitExtension(table.WithAlias(newAlias)), ColumnExpression column when aliasRewritingMap.TryGetValue(column.TableAlias, out var newTableAlias) diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs index 40a6d13949f..3ba532a7462 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -230,7 +230,7 @@ private SqlExpression ApplyTypeMappingOnSqlBinary( ? leftTypeMapping : rightTypeMapping?.Size == inferredSize && rightTypeMapping?.IsFixedLength == inferredFixedLength - && rightTypeMapping?.IsUnicode == inferredUnicode + && rightTypeMapping.IsUnicode == inferredUnicode ? rightTypeMapping : _typeMappingSource.FindMapping( baseTypeMapping.ClrType, @@ -288,15 +288,15 @@ private InExpression ApplyTypeMappingOnIn(InExpression inExpression) RelationalTypeMapping? valuesTypeMapping = null; switch (inExpression) { - case { Subquery: SelectExpression subquery }: + case { Subquery: { } subquery }: valuesTypeMapping = subquery.Projection[0].Expression.TypeMapping; break; - case { ValuesParameter: SqlParameterExpression parameter }: + case { ValuesParameter: { } parameter }: valuesTypeMapping = (RelationalTypeMapping?)parameter.TypeMapping?.ElementTypeMapping; break; - case { Values: IReadOnlyList values }: + case { Values: { } values }: // Note: there could be conflicting type mappings inside the values; we take the first. foreach (var value in values) { @@ -322,16 +322,17 @@ private InExpression ApplyTypeMappingOnIn(InExpression inExpression) switch (inExpression) { - case { Subquery: SelectExpression subquery }: + case { Subquery: { } subquery }: inExpression = inExpression.Update(item, subquery); break; - case { ValuesParameter: SqlParameterExpression parameter }: - var collectionTypeMapping = Dependencies.TypeMappingSource.FindMapping(parameter.Type, Dependencies.Model, item.TypeMapping); + case { ValuesParameter: { } parameter }: + var collectionTypeMapping = + Dependencies.TypeMappingSource.FindMapping(parameter.Type, Dependencies.Model, item.TypeMapping); inExpression = inExpression.Update(item, (SqlParameterExpression)ApplyTypeMapping(parameter, collectionTypeMapping)); break; - case { Values: IReadOnlyList values }: + case { Values: { } values }: SqlExpression[]? newValues = null; if (missingTypeMappingInValues) @@ -382,7 +383,7 @@ private SqlExpression ApplyTypeMappingOnJsonScalar( } // Resolve the array type mapping for the given element mapping. - if (_typeMappingSource.FindMapping(array.Type, Dependencies.Model, elementMapping) is not RelationalTypeMapping arrayMapping) + if (_typeMappingSource.FindMapping(array.Type, Dependencies.Model, elementMapping) is not { } arrayMapping) { throw new UnreachableException($"Couldn't find collection type mapping for element type mapping {elementMapping.ClrType.Name}"); } @@ -662,23 +663,23 @@ private SqlExpression Not(SqlExpression operand, SqlExpression? existingExpressi => AndAlso(Not(binary.Left), Not(binary.Right)), SqlBinaryExpression - { - OperatorType: ExpressionType.Equal, - Right: SqlConstantExpression { Value: bool }, - Left: SqlConstantExpression { Value: bool } + { + OperatorType: ExpressionType.Equal, + Right: SqlConstantExpression { Value: bool }, + Left: SqlConstantExpression { Value: bool } or SqlParameterExpression { IsNullable: false } or ColumnExpression { IsNullable: false } - } binary + } binary => Equal(binary.Left, Not(binary.Right)), SqlBinaryExpression - { - OperatorType: ExpressionType.Equal, - Left: SqlConstantExpression { Value: bool }, - Right: SqlConstantExpression { Value: bool } + { + OperatorType: ExpressionType.Equal, + Left: SqlConstantExpression { Value: bool }, + Right: SqlConstantExpression { Value: bool } or SqlParameterExpression { IsNullable: false } or ColumnExpression { IsNullable: false } - } binary + } binary => Equal(Not(binary.Left), binary.Right), // !(a == b) -> a != b diff --git a/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs index 991b1dc91f8..ee52be5c94a 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CaseExpression.cs @@ -118,12 +118,11 @@ public override Expression Quote() var whenClauses = NewArrayInit( typeof(CaseWhenClause), initializers: WhenClauses - .Select( - c => New( - _caseWhenClauseQuotingConstructor ??= - typeof(CaseWhenClause).GetConstructor([typeof(SqlExpression), typeof(SqlExpression)])!, - c.Test.Quote(), - c.Result.Quote()))); + .Select(c => New( + _caseWhenClauseQuotingConstructor ??= + typeof(CaseWhenClause).GetConstructor([typeof(SqlExpression), typeof(SqlExpression)])!, + c.Test.Quote(), + c.Result.Quote()))); return Operand is null ? New( diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs index d9a8555dcfa..af41777a850 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs @@ -278,9 +278,10 @@ protected override Expression VisitExtension(Expression expression) }; } - case CollectionResultExpression { + case CollectionResultExpression + { QueryExpression: ProjectionBindingExpression innerProjectionBindingExpression - } collectionResultExpression: + } collectionResultExpression: { var navigation = collectionResultExpression.Relationship switch { @@ -453,8 +454,8 @@ protected override Expression VisitExtension(Expression expression) var identityMap = true; for (var j = 0; j < selectExpression.Projection.Count; j++) { - var newIndex = innerProjections.FindIndex( - e => string.Equals(e, selectExpression.Projection[j].Alias, StringComparison.Ordinal)); + var newIndex = innerProjections.FindIndex(e => string.Equals( + e, selectExpression.Projection[j].Alias, StringComparison.Ordinal)); if (newIndex == -1) { // If for whatever reason outer has additional projection which cannot be remapped we avoid lift diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index eef7e91c6a5..c09bf1a72f8 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -355,7 +355,10 @@ void ProcessComplexType(StructuralTypeProjectionExpression complexTypeProjection { // Non-JSON non-collection type (table splitting): recurse inside and process all properties, // as each property is mapped to its own column. - case StructuralTypeShaperExpression { ValueBufferExpression: StructuralTypeProjectionExpression projection }: + case StructuralTypeShaperExpression + { + ValueBufferExpression: StructuralTypeProjectionExpression projection + }: ProcessComplexType(projection); continue; @@ -655,8 +658,8 @@ Expression AddGroupByKeySelectorToProjection( { var index = selectExpression.AddToProjection(sqlExpression); var clientProjectionToAdd = Constant(index); - var existingIndex = clientProjectionList.FindIndex( - e => ExpressionEqualityComparer.Instance.Equals(e, clientProjectionToAdd)); + var existingIndex = clientProjectionList.FindIndex(e + => ExpressionEqualityComparer.Instance.Equals(e, clientProjectionToAdd)); if (existingIndex == -1) { clientProjectionList.Add(clientProjectionToAdd); @@ -714,8 +717,8 @@ Expression AddGroupByKeySelectorToProjection( } shaper: { var clientProjectionToAdd = AddStructuralTypeProjection(projection); - var existingIndex = clientProjectionList.FindIndex( - e => ExpressionEqualityComparer.Instance.Equals(e, clientProjectionToAdd)); + var existingIndex = clientProjectionList.FindIndex(e + => ExpressionEqualityComparer.Instance.Equals(e, clientProjectionToAdd)); if (existingIndex == -1) { clientProjectionList.Add(clientProjectionToAdd); @@ -746,8 +749,8 @@ Expression AddGroupByKeySelectorToProjection( { var index = selectExpression.AddToProjection(column); var clientProjectionToAdd = Constant(index); - var existingIndex = clientProjectionList.FindIndex( - e => ExpressionEqualityComparer.Instance.Equals(e, clientProjectionToAdd)); + var existingIndex = clientProjectionList.FindIndex(e + => ExpressionEqualityComparer.Instance.Equals(e, clientProjectionToAdd)); if (existingIndex == -1) { clientProjectionList.Add(clientProjectionToAdd); @@ -878,13 +881,12 @@ static void UpdateLimit(SelectExpression selectExpression) Throw( New( typeof(InvalidOperationException).GetConstructors() - .Single( - ci => - { - var parameters = ci.GetParameters(); - return parameters.Length == 1 - && parameters[0].ParameterType == typeof(string); - }), + .Single(ci => + { + var parameters = ci.GetParameters(); + return parameters.Length == 1 + && parameters[0].ParameterType == typeof(string); + }), Constant(CoreStrings.SequenceContainsNoElements))), Default(innerShaperExpression.Type)); @@ -1155,8 +1157,8 @@ static Expression RemoveConvert(Expression expression) { var index = selectExpression.AddToProjection(column, null); var clientProjectionToAdd = Constant(index); - var existingIndex = clientProjectionList.FindIndex( - e => ExpressionEqualityComparer.Instance.Equals(e, clientProjectionToAdd)); + var existingIndex = clientProjectionList.FindIndex(e + => ExpressionEqualityComparer.Instance.Equals(e, clientProjectionToAdd)); if (existingIndex == -1) { clientProjectionList.Add(Constant(index)); @@ -1205,7 +1207,7 @@ void GetOrderingsFromInnerTable(TableExpressionBase tableExpressionBase, List pe.Expression) - .OfType().SingleOrDefault() is RowNumberExpression rowNumberExpression) + .OfType().SingleOrDefault() is { } rowNumberExpression) { var rowNumberSubqueryTableAlias = joinedSubquery.Tables.Single().GetRequiredAlias(); foreach (var partition in rowNumberExpression.Partitions) @@ -1289,7 +1291,8 @@ Expression CopyProjectionToOuter(SelectExpression innerSelectExpression, Express case QueryableJsonProjectionInfo queryableJsonProjectionInfo: { - var newPropertyIndexMap = new Dictionary(queryableJsonProjectionInfo.PropertyIndexMap.Count); + var newPropertyIndexMap = + new Dictionary(queryableJsonProjectionInfo.PropertyIndexMap.Count); foreach (var (property, value) in queryableJsonProjectionInfo.PropertyIndexMap) { newPropertyIndexMap[property] = projectionIndexMap[value]; @@ -1300,7 +1303,7 @@ Expression CopyProjectionToOuter(SelectExpression innerSelectExpression, Express { var newKeyAccessInfo = new List<(IProperty?, int?, int?)>(); foreach (var (keyProperty, constantKeyValue, keyProjectionIndex) in childProjectionInfo.JsonProjectionInfo - .KeyAccessInfo) + .KeyAccessInfo) { newKeyAccessInfo.Add( (keyProperty, constantKeyValue, @@ -1390,10 +1393,9 @@ ConstantExpression AddStructuralTypeProjection(StructuralTypeProjectionExpressio } var childrenProjectionInfo = new List<(JsonProjectionInfo, INavigation)>(); - foreach (var ownedNavigation in entityType.GetNavigations().Where( - n => n.TargetEntityType.IsMappedToJson() - && n.ForeignKey.IsOwnership - && n == n.ForeignKey.PrincipalToDependent)) + foreach (var ownedNavigation in entityType.GetNavigations().Where(n => n.TargetEntityType.IsMappedToJson() + && n.ForeignKey.IsOwnership + && n == n.ForeignKey.PrincipalToDependent)) { var jsonQueryExpression = (JsonQueryExpression)projection.BindNavigation(ownedNavigation)!.ValueBufferExpression; var jsonProjectionInfo = (JsonProjectionInfo)AddJsonProjection(jsonQueryExpression).Value!; @@ -1487,6 +1489,7 @@ ConstantExpression AddJsonProjection(JsonQueryExpression jsonQueryExpression) keyAccessInfo.Add((null, null, AddToProjection(elementAccessSegment.ArrayIndex!))); } } + break; case IComplexType complexType: @@ -1496,7 +1499,6 @@ ConstantExpression AddJsonProjection(JsonQueryExpression jsonQueryExpression) throw new UnreachableException(); } - return Constant(new JsonProjectionInfo(jsonColumnIndex, keyAccessInfo)); } @@ -1565,7 +1567,7 @@ public void ReplaceProjection(IReadOnlyList clientProjections) /// A projection binding to search. /// The mapped projection for given projection binding. public Expression GetProjection(ProjectionBindingExpression projectionBindingExpression) - => projectionBindingExpression.ProjectionMember is ProjectionMember projectionMember + => projectionBindingExpression.ProjectionMember is { } projectionMember ? _projectionMapping[projectionMember] : _clientProjections[projectionBindingExpression.Index!.Value]; @@ -1635,7 +1637,8 @@ public void ApplyPredicate(SqlExpression sqlExpression) Left: ColumnExpression leftColumn, Right: SqlConstantExpression { Value: string s1 } } - when TryGetTable(leftColumn, out var table, out _) && table is TpcTablesExpression + when TryGetTable(leftColumn, out var table, out _) + && table is TpcTablesExpression { DiscriminatorColumn: var discriminatorColumn, DiscriminatorValues: var discriminatorValues @@ -1658,7 +1661,8 @@ when TryGetTable(leftColumn, out var table, out _) && table is TpcTablesExpressi Left: SqlConstantExpression { Value: string s2 }, Right: ColumnExpression rightColumn } - when TryGetTable(rightColumn, out var table, out _) && table is TpcTablesExpression + when TryGetTable(rightColumn, out var table, out _) + && table is TpcTablesExpression { DiscriminatorColumn: var discriminatorColumn, DiscriminatorValues: var discriminatorValues @@ -1680,9 +1684,10 @@ when TryGetTable(rightColumn, out var table, out _) && table is TpcTablesExpress case InExpression { Item: ColumnExpression itemColumn, - Values: IReadOnlyList valueExpressions + Values: { } valueExpressions } - when TryGetTable(itemColumn, out var table, out _) && table is TpcTablesExpression + when TryGetTable(itemColumn, out var table, out _) + && table is TpcTablesExpression { DiscriminatorColumn: var discriminatorColumn, DiscriminatorValues: var discriminatorValues @@ -2345,10 +2350,10 @@ StructuralTypeProjectionExpression ProcessStructuralType( // Set operation over type that contains a structural type mapped to table splitting - // recurse to continue processing all the properties of the structural type case - ( + ( StructuralTypeShaperExpression { ValueBufferExpression: StructuralTypeProjectionExpression projection1 }, StructuralTypeShaperExpression { ValueBufferExpression: StructuralTypeProjectionExpression projection2 } - ): + ): var resultComplexProjection = ProcessStructuralType(projection1, projection2); var outerShaper = new RelationalStructuralTypeShaperExpression( @@ -2361,19 +2366,19 @@ StructuralTypeProjectionExpression ProcessStructuralType( // Set operation over type that contains a JSON-mapped complex type (non-collection) case - ( + ( StructuralTypeShaperExpression { ValueBufferExpression: JsonQueryExpression jsonQuery1 } shaper1, StructuralTypeShaperExpression { ValueBufferExpression: JsonQueryExpression jsonQuery2 } shaper2 - ): + ): ProcessJson(jsonQuery1, jsonQuery2); continue; // Set operation over type that contains a JSON-mapped complex type (collection) case - ( + ( CollectionResultExpression { QueryExpression: JsonQueryExpression jsonQuery1 } collection1, CollectionResultExpression { QueryExpression: JsonQueryExpression jsonQuery2 } collection2 - ): + ): ProcessJson(jsonQuery1, jsonQuery2); continue; @@ -2389,19 +2394,19 @@ void ProcessJson(JsonQueryExpression jsonQuery1, JsonQueryExpression jsonQuery2) // Convert the JsonQueryExpression to a JsonScalarExpression, which is our current representation for a complex // JSON in the SQL tree (as opposed to in the shaper) - see #36392. var jsonScalar1 = new JsonScalarExpression( - jsonQuery1.JsonColumn, - jsonQuery1.Path, - jsonQuery1.Type, - jsonQuery1.JsonColumn.TypeMapping, - jsonQuery1.IsNullable); + jsonQuery1.JsonColumn, + jsonQuery1.Path, + jsonQuery1.Type, + jsonQuery1.JsonColumn.TypeMapping, + jsonQuery1.IsNullable); var jsonScalar2 = new JsonScalarExpression( - jsonQuery2.JsonColumn, - jsonQuery2.Path, - jsonQuery2.Type, - jsonQuery2.JsonColumn.TypeMapping, - jsonQuery2.IsNullable); + jsonQuery2.JsonColumn, + jsonQuery2.Path, + jsonQuery2.Type, + jsonQuery2.JsonColumn.TypeMapping, + jsonQuery2.IsNullable); - var alias = GenerateUniqueColumnAlias(complexProperty.Name.ToString()); + var alias = GenerateUniqueColumnAlias(complexProperty.Name); var innerProjection = new ProjectionExpression(jsonScalar1, alias); select1._projection.Add(innerProjection); select2._projection.Add(new ProjectionExpression(jsonScalar2, alias)); @@ -2421,7 +2426,8 @@ void ProcessJson(JsonQueryExpression jsonQuery1, JsonQueryExpression jsonQuery2) collection: jsonQuery1.IsCollection, jsonQuery1.IsNullable || jsonQuery2.IsNullable); - var outerShaper = new CollectionResultExpression(outerJsonQuery, complexProperty, complexProperty.ComplexType.ClrType); + var outerShaper = new CollectionResultExpression( + outerJsonQuery, complexProperty, complexProperty.ComplexType.ClrType); complexPropertyCache[complexProperty] = outerShaper; } @@ -2545,7 +2551,7 @@ [new ProjectionExpression(nullSqlExpression, "empty")], // ChildIdentifiers shouldn't be required to be updated since during translation they should be empty. for (var i = 0; i < _identifier.Count; i++) { - if (_identifier[i].Column is ColumnExpression column) + if (_identifier[i].Column is { } column) { _identifier[i] = (column.MakeNullable(), _identifier[i].Comparer); } @@ -2658,8 +2664,8 @@ static IReadOnlyDictionary GetPropertyExpressions( // This may not be table which originates Owned type if (derivedTpt) { - baseTableIndex = selectExpression._tables.FindIndex( - teb => ((TableExpression)teb.UnwrapJoin()).Table == principalTables[0]); + baseTableIndex = + selectExpression._tables.FindIndex(teb => ((TableExpression)teb.UnwrapJoin()).Table == principalTables[0]); } var tableIndex = baseTableIndex + matchingTableIndex; @@ -2696,8 +2702,7 @@ static IReadOnlyDictionary GetPropertyExpressions( tableMap[table] = alias; - var innerColumns = keyProperties.Select( - p => CreateColumnExpression(p, table, alias, nullable: false)); + var innerColumns = keyProperties.Select(p => CreateColumnExpression(p, table, alias, nullable: false)); var joinPredicate = joinColumns .Zip(innerColumns, sqlExpressionFactory.Equal) .Aggregate(sqlExpressionFactory.AndAlso); @@ -2775,8 +2780,7 @@ static IReadOnlyDictionary GetPropertyExpressions( tableMap[table] = alias; - var innerColumns = keyProperties.Select( - p => CreateColumnExpression(p, table, alias, nullable: false)); + var innerColumns = keyProperties.Select(p => CreateColumnExpression(p, table, alias, nullable: false)); var joinPredicate = joinColumns .Zip(innerColumns, sqlExpressionFactory.Equal) .Aggregate(sqlExpressionFactory.AndAlso); @@ -2878,7 +2882,8 @@ public static Expression GenerateComplexPropertyShaperExpression( // Otherwise, if the source type isn't mapped to JSON, we're just binding to an actual JSON column in a relational table, and not within it. var containerColumnExpression = complexProperty.DeclaringType.IsMappedToJson() ? new ColumnExpression( - complexType.GetJsonPropertyName() ?? throw new UnreachableException($"No JSON property name for complex property {complexProperty.Name}"), + complexType.GetJsonPropertyName() + ?? throw new UnreachableException($"No JSON property name for complex property {complexProperty.Name}"), tableAlias, complexProperty.ClrType, typeMapping: containerColumn.StoreTypeMapping, @@ -3130,7 +3135,7 @@ private void AddJoin( ? innerSelect.Orderings : innerSelect._identifier.Count > 0 ? innerSelect._identifier.Select(e => new OrderingExpression(e.Column, true)) - : new[] { new OrderingExpression(new SqlFragmentExpression("(SELECT 1)", typeof(int)), true) }; + : [new OrderingExpression(new SqlFragmentExpression("(SELECT 1)", typeof(int)), true)]; var rowNumberExpression = new RowNumberExpression( partitions, orderings.ToList(), (limit ?? offset)!.TypeMapping); @@ -3711,7 +3716,7 @@ private SqlRemappingVisitor PushdownIntoSubqueryInternal(bool liftOrderings = tr { // If there's just one table in the select being pushed down, bubble up that table's name as the subquery's alias. var subqueryAlias = - _sqlAliasManager.GenerateTableAlias(_tables is [{ Alias: string singleTableAlias }] ? singleTableAlias : "subquery"); + _sqlAliasManager.GenerateTableAlias(_tables is [{ Alias: { } singleTableAlias }] ? singleTableAlias : "subquery"); var subquery = new SelectExpression( subqueryAlias, _tables.ToList(), _groupBy.ToList(), projections: [], _orderings.ToList(), Annotations, _sqlAliasManager) @@ -4035,9 +4040,8 @@ public bool IsNonComposedFromSql() && Having == null && Orderings.Count == 0 && Tables is [FromSqlExpression fromSql] - && Projection.All( - pe => pe.Expression is ColumnExpression column - && string.Equals(fromSql.Alias, column.TableAlias, StringComparison.OrdinalIgnoreCase)) + && Projection.All(pe => pe.Expression is ColumnExpression column + && string.Equals(fromSql.Alias, column.TableAlias, StringComparison.OrdinalIgnoreCase)) && _projectionMapping.TryGetValue(new ProjectionMember(), out var mapping) && mapping.Type == (fromSql.Table == null ? typeof(int) : typeof(Dictionary)); @@ -4250,7 +4254,7 @@ private static ColumnExpression CreateColumnExpression(ProjectionExpression subq => new( subqueryProjection.Alias, tableAlias, - column: subqueryProjection.Expression is ColumnExpression { Column: IColumnBase column } ? column : null, + column: subqueryProjection.Expression is ColumnExpression { Column: { } column } ? column : null, subqueryProjection.Type, subqueryProjection.Expression.TypeMapping!, nullable: subqueryProjection.Expression switch diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs index dd7279f0927..f6bc6b3980d 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlConstantExpression.cs @@ -81,7 +81,7 @@ public SqlConstantExpression(ConstantExpression constantExpression, RelationalTy public virtual object? Value { get; } /// - /// Whether the expression contains sensitive values. + /// Whether the expression contains sensitive values. /// public virtual bool IsSensitive { get; } diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs index 0a0a3f5eb69..25d534c3906 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs @@ -103,9 +103,11 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) protected virtual void PrintAnnotations(ExpressionPrinter expressionPrinter) { var annotations = GetAnnotations(); + // ReSharper disable once PossibleMultipleEnumeration if (annotations.Any()) { expressionPrinter.Append("["); + // ReSharper disable once PossibleMultipleEnumeration expressionPrinter.Append(annotations.Select(a => a.Name + "=" + a.Value).Join(" | ")); expressionPrinter.Append("]"); } @@ -177,7 +179,7 @@ public virtual TableExpressionBase AddAnnotation(string name, object? value) /// Gets all annotations on the current object. /// public virtual IEnumerable GetAnnotations() - => Annotations?.Values ?? Enumerable.Empty(); + => Annotations?.Values ?? []; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Relational/Query/SqlExpressions/UpdateExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/UpdateExpression.cs index 994380a3e5d..ceea00670e2 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/UpdateExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/UpdateExpression.cs @@ -144,12 +144,11 @@ public Expression Quote() NewArrayInit( typeof(ColumnValueSetter), ColumnValueSetters - .Select( - s => New( - _columnValueSetterQuotingConstructor ??= - typeof(ColumnValueSetter).GetConstructor([typeof(ColumnExpression), typeof(SqlExpression)])!, - s.Column.Quote(), - s.Value.Quote()))), + .Select(s => New( + _columnValueSetterQuotingConstructor ??= + typeof(ColumnValueSetter).GetConstructor([typeof(ColumnExpression), typeof(SqlExpression)])!, + s.Column.Quote(), + s.Value.Quote()))), RelationalExpressionQuotingUtilities.QuoteTags(Tags)); /// diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs index f5543360c7c..eb35acf1e42 100644 --- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs +++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs @@ -24,7 +24,7 @@ public class SqlNullabilityProcessor : ExpressionVisitor private readonly ISqlExpressionFactory _sqlExpressionFactory; /// - /// Tracks parameters for collection expansion, allowing reuse. + /// Tracks parameters for collection expansion, allowing reuse. /// private readonly Dictionary> _collectionParameterExpansionMap; @@ -112,7 +112,7 @@ protected override Expression VisitExtension(Expression node) return join.Update(newTable, newJoinPredicate); } - case ValuesExpression { ValuesParameter: SqlParameterExpression valuesParameter } valuesExpression: + case ValuesExpression { ValuesParameter: { } valuesParameter } valuesExpression: { Check.DebugAssert(valuesParameter.TypeMapping is not null); Check.DebugAssert(valuesParameter.TypeMapping.ElementTypeMapping is not null); @@ -136,7 +136,9 @@ protected override Expression VisitExtension(Expression node) { // Create parameter for value if we didn't create it yet, // otherwise reuse it. - ExpandParameterIfNeeded(valuesParameter.Name, expandedParameters, queryParameters, expandedParametersCounter, value, elementTypeMapping); + ExpandParameterIfNeeded( + valuesParameter.Name, expandedParameters, queryParameters, expandedParametersCounter, value, + elementTypeMapping); processedValues.Add( new RowValueExpression( @@ -146,6 +148,7 @@ protected override Expression VisitExtension(Expression node) intTypeMapping, ref valuesOrderingCounter))); } + break; } @@ -174,6 +177,7 @@ protected override Expression VisitExtension(Expression node) intTypeMapping, ref valuesOrderingCounter))); } + break; } @@ -206,13 +210,16 @@ SqlExpression ProcessJoinPredicate(SqlExpression predicate) return result; - case SqlBinaryExpression { OperatorType: + case SqlBinaryExpression + { + OperatorType: ExpressionType.AndAlso or ExpressionType.NotEqual or ExpressionType.GreaterThan or ExpressionType.GreaterThanOrEqual or ExpressionType.LessThan - or ExpressionType.LessThanOrEqual } binary: + or ExpressionType.LessThanOrEqual + } binary: return Visit(binary, allowOptimizedExpansion: true, out _); default: @@ -227,7 +234,7 @@ or ExpressionType.LessThan /// we need to add value for it. /// /// Expression where to look for ordering column. - /// Expressions for . + /// Expressions for . /// Type mapping for integer. /// Counter for constants for ordering column. /// Row value with ordering, if needed. @@ -237,7 +244,8 @@ protected virtual IReadOnlyList ProcessValuesOrderingColumn( IReadOnlyList expressions, IntTypeMapping intTypeMapping, ref int counter) - => RelationalQueryableMethodTranslatingExpressionVisitor.ValuesOrderingColumnName.Equals(valuesExpression.ColumnNames[0], StringComparison.Ordinal) + => RelationalQueryableMethodTranslatingExpressionVisitor.ValuesOrderingColumnName.Equals( + valuesExpression.ColumnNames[0], StringComparison.Ordinal) ? [_sqlExpressionFactory.Constant(counter++, intTypeMapping), .. expressions] : expressions; @@ -812,7 +820,7 @@ InExpression ProcessInExpressionValues( List? processedValues = null; (hasNull, nullables) = (false, []); - if (inExpression.ValuesParameter is SqlParameterExpression valuesParameter) + if (inExpression.ValuesParameter is { } valuesParameter) { // The InExpression has a values parameter. Expand it out, embedding its values as constants into the SQL; disable SQL // caching. @@ -841,7 +849,8 @@ InExpression ProcessInExpressionValues( { // Create parameter for value if we didn't create it yet, // otherwise reuse it. - ExpandParameterIfNeeded(valuesParameter.Name, expandedParameters, parameters, expandedParametersCounter, value, elementTypeMapping); + ExpandParameterIfNeeded( + valuesParameter.Name, expandedParameters, parameters, expandedParametersCounter, value, elementTypeMapping); processedValues.Add(expandedParameters[expandedParametersCounter++]); @@ -850,7 +859,9 @@ InExpression ProcessInExpressionValues( case ParameterTranslationMode.Constant: { - processedValues.Add(_sqlExpressionFactory.Constant(value, value?.GetType() ?? typeof(object), sensitive: true, elementTypeMapping)); + processedValues.Add( + _sqlExpressionFactory.Constant( + value, value?.GetType() ?? typeof(object), sensitive: true, elementTypeMapping)); break; } @@ -886,7 +897,8 @@ InExpression ProcessInExpressionValues( { // Create parameter for value if we didn't create it yet, // otherwise reuse it. - ExpandParameterIfNeeded(valuesParameter.Name, expandedParameters, parameters, values.Count + i, values[^1], elementTypeMapping); + ExpandParameterIfNeeded( + valuesParameter.Name, expandedParameters, parameters, values.Count + i, values[^1], elementTypeMapping); processedValues.Add(expandedParameters[expandedParametersCounter++]); } @@ -1290,7 +1302,7 @@ [new CaseWhenClause(result, _sqlExpressionFactory.Constant(true, result.TypeMapp ); } - return result is SqlBinaryExpression sqlBinaryResult + return result is { } sqlBinaryResult && sqlBinaryResult.OperatorType is ExpressionType.AndAlso or ExpressionType.OrElse ? _sqlExpressionFactory.MakeBinary( // invoke MakeBinary simplifications sqlBinaryResult.OperatorType, @@ -1544,7 +1556,7 @@ protected virtual int CalculateParameterBucketSize(int count, RelationalTypeMapp // Note that we can check parameter values for null since we cache by the parameter nullability; but we cannot do the same for bool. private bool IsNull(SqlExpression? expression) => expression is SqlConstantExpression { Value: null } - || expression is SqlParameterExpression { Name: string parameterName } && ParametersDecorator.IsNull(parameterName); + || expression is SqlParameterExpression { Name: { } parameterName } && ParametersDecorator.IsNull(parameterName); private bool IsTrue(SqlExpression? expression) => expression is SqlConstantExpression { Value: true }; @@ -1899,7 +1911,7 @@ protected virtual bool TryMakeNonNullable( #pragma warning restore EF1001 rewrittenSelectExpression = rewrittenSelectExpression.Update( - new[] { rewrittenCollectionTable }, + [rewrittenCollectionTable], selectExpression.Predicate, selectExpression.GroupBy, selectExpression.Having, @@ -2098,22 +2110,20 @@ private SqlExpression ProcessNullNotNull(SqlExpression sqlExpression, bool opera // (a ?? b ?? c) == null -> a == null && b == null && c == null // (a ?? b ?? c) != null -> a != null || b != null || c != null return sqlFunctionExpression.Arguments - .Select( - a => ProcessNullNotNull( - _sqlExpressionFactory.MakeUnary( - sqlUnaryExpression.OperatorType, - a, - typeof(bool), - sqlUnaryExpression.TypeMapping)!, - operandNullable)) - .Aggregate( - (l, r) => _sqlExpressionFactory.MakeBinary( - sqlUnaryExpression.OperatorType == ExpressionType.Equal - ? ExpressionType.AndAlso - : ExpressionType.OrElse, - l, - r, - sqlUnaryExpression.TypeMapping)!); + .Select(a => ProcessNullNotNull( + _sqlExpressionFactory.MakeUnary( + sqlUnaryExpression.OperatorType, + a, + typeof(bool), + sqlUnaryExpression.TypeMapping)!, + operandNullable)) + .Aggregate((l, r) => _sqlExpressionFactory.MakeBinary( + sqlUnaryExpression.OperatorType == ExpressionType.Equal + ? ExpressionType.AndAlso + : ExpressionType.OrElse, + l, + r, + sqlUnaryExpression.TypeMapping)!); } if (!sqlFunctionExpression.IsNullable) @@ -2150,18 +2160,16 @@ private SqlExpression ProcessNullNotNull(SqlExpression sqlExpression, bool opera if (nullabilityPropagationElements.Count > 0) { var result = nullabilityPropagationElements - .Select( - e => ProcessNullNotNull( - _sqlExpressionFactory.MakeUnary( - sqlUnaryExpression.OperatorType, - e, - sqlUnaryExpression.Type, - sqlUnaryExpression.TypeMapping)!, - operandNullable)) - .Aggregate( - (r, e) => sqlUnaryExpression.OperatorType == ExpressionType.Equal - ? _sqlExpressionFactory.OrElse(r, e) - : _sqlExpressionFactory.AndAlso(r, e)); + .Select(e => ProcessNullNotNull( + _sqlExpressionFactory.MakeUnary( + sqlUnaryExpression.OperatorType, + e, + sqlUnaryExpression.Type, + sqlUnaryExpression.TypeMapping)!, + operandNullable)) + .Aggregate((r, e) => sqlUnaryExpression.OperatorType == ExpressionType.Equal + ? _sqlExpressionFactory.OrElse(r, e) + : _sqlExpressionFactory.AndAlso(r, e)); return result; } diff --git a/src/EFCore.Relational/Query/SqlTreePruner.cs b/src/EFCore.Relational/Query/SqlTreePruner.cs index 27c8e0301ed..c23eb7cce67 100644 --- a/src/EFCore.Relational/Query/SqlTreePruner.cs +++ b/src/EFCore.Relational/Query/SqlTreePruner.cs @@ -100,7 +100,7 @@ protected override Expression VisitExtension(Expression node) return scalarSubquery.Update(PruneSelect(scalarSubquery.Subquery, preserveProjection: true)); // Same for subqueries inside InExpression - case InExpression { Subquery: SelectExpression subquery } inExpression: + case InExpression { Subquery: { } subquery } inExpression: var visitedItem = (SqlExpression)Visit(inExpression.Item); var visitedSubquery = PruneSelect(subquery, preserveProjection: true); return inExpression.Update(visitedItem, visitedSubquery); @@ -350,11 +350,11 @@ protected virtual ValuesExpression PruneValues(ValuesExpression values) // If we have a value parameter (row values aren't specific in line), we still prune the column names. // Later in SqlNullabilityProcessor, when the parameterized collection is inline to constants, we'll take // the column names into account. - case ValuesExpression { ValuesParameter: not null }: + case { ValuesParameter: not null }: return new ValuesExpression(values.Alias, rowValues: null, values.ValuesParameter, newColumnNames); // Go over the rows and create new ones without the pruned columns. - case ValuesExpression { RowValues: IReadOnlyList rowValues }: + case { RowValues: { } rowValues }: var newRowValues = new RowValueExpression[rowValues.Count]; for (var i = 0; i < rowValues.Count; i++) diff --git a/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs b/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs index d33c2c3cc63..7d7e87e1372 100644 --- a/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs +++ b/src/EFCore.Relational/Scaffolding/DatabaseModelFactoryOptions.cs @@ -19,8 +19,8 @@ public class DatabaseModelFactoryOptions /// A list of schemas to include. Empty to include all schemas. public DatabaseModelFactoryOptions(IEnumerable? tables = null, IEnumerable? schemas = null) { - Tables = tables ?? Enumerable.Empty(); - Schemas = schemas ?? Enumerable.Empty(); + Tables = tables ?? []; + Schemas = schemas ?? []; } /// diff --git a/src/EFCore.Relational/Storage/Internal/RawRelationalParameter.cs b/src/EFCore.Relational/Storage/Internal/RawRelationalParameter.cs index 38c7b42aa40..f0c90f0a948 100644 --- a/src/EFCore.Relational/Storage/Internal/RawRelationalParameter.cs +++ b/src/EFCore.Relational/Storage/Internal/RawRelationalParameter.cs @@ -21,7 +21,8 @@ public class RawRelationalParameter : RelationalParameterBase /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public RawRelationalParameter(string invariantName, DbParameter parameter) : base(invariantName) + public RawRelationalParameter(string invariantName, DbParameter parameter) + : base(invariantName) => _parameter = parameter; /// diff --git a/src/EFCore.Relational/Storage/JsonTypePlaceholder.cs b/src/EFCore.Relational/Storage/JsonTypePlaceholder.cs index 027ee3465d7..f24fe94192d 100644 --- a/src/EFCore.Relational/Storage/JsonTypePlaceholder.cs +++ b/src/EFCore.Relational/Storage/JsonTypePlaceholder.cs @@ -4,7 +4,7 @@ namespace Microsoft.EntityFrameworkCore.Storage; /// -/// A type representing CLR type of the JsonTypeMapping. +/// A type representing CLR type of the JsonTypeMapping. /// public sealed class JsonTypePlaceholder { diff --git a/src/EFCore.Relational/Storage/RelationalConnection.cs b/src/EFCore.Relational/Storage/RelationalConnection.cs index f5507648334..1799f51c98a 100644 --- a/src/EFCore.Relational/Storage/RelationalConnection.cs +++ b/src/EFCore.Relational/Storage/RelationalConnection.cs @@ -863,7 +863,7 @@ private void HandleTransactionCompleted(object? sender, TransactionEventArgs e) ambientTransaction.TransactionCompleted -= HandleTransactionCompleted; } - _ambientTransactions.TryPop(out var _); + _ambientTransactions.TryPop(out _); } /// diff --git a/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs b/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs index 7ba78522385..2f4d4ff5d20 100644 --- a/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs +++ b/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs @@ -116,7 +116,8 @@ public virtual Task DeleteAsync(CancellationToken cancellationToken = default) /// to incrementally update the schema. It is assumed that none of the tables exist in the database. /// public virtual void CreateTables() - => Dependencies.MigrationCommandExecutor.ExecuteNonQuery(GetCreateTablesCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true); + => Dependencies.MigrationCommandExecutor.ExecuteNonQuery( + GetCreateTablesCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true); /// /// Asynchronously creates all tables for the current model in the database. No attempt is made @@ -129,7 +130,8 @@ public virtual void CreateTables() /// If the is canceled. public virtual Task CreateTablesAsync(CancellationToken cancellationToken = default) => Dependencies.MigrationCommandExecutor.ExecuteNonQueryAsync( - GetCreateTablesCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true, cancellationToken: cancellationToken); + GetCreateTablesCommands(), Dependencies.Connection, new MigrationExecutionState(), commitTransaction: true, + cancellationToken: cancellationToken); /// /// Gets the commands that will create all tables from the model. diff --git a/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs b/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs index 46966b3538b..0ada3276fec 100644 --- a/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs +++ b/src/EFCore.Relational/Storage/RelationalDatabaseCreatorDependencies.cs @@ -115,7 +115,7 @@ public RelationalDatabaseCreatorDependencies( public ICurrentDbContext CurrentContext { get; init; } /// - /// Gets the exception detector. + /// Gets the exception detector. /// public IExceptionDetector ExceptionDetector { get; init; } } diff --git a/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs b/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs index 27785402a9d..0f0ef1cf7b0 100644 --- a/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs +++ b/src/EFCore.Relational/Storage/RelationalTypeMappingSource.cs @@ -374,7 +374,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo) /// public override RelationalTypeMapping? FindMapping(MemberInfo member) { - if (member.GetCustomAttribute(true) is ColumnAttribute attribute) + if (member.GetCustomAttribute(true) is { } attribute) { var storeTypeName = attribute.TypeName; bool? unicode = null; @@ -395,7 +395,7 @@ protected override CoreTypeMapping FindMapping(in TypeMappingInfo mappingInfo) public override RelationalTypeMapping? FindMapping(MemberInfo member, IModel model, bool useAttributes) { if (useAttributes - && member.GetCustomAttribute(true) is ColumnAttribute attribute) + && member.GetCustomAttribute(true) is { } attribute) { var storeTypeName = attribute.TypeName; bool? unicode = null; diff --git a/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs b/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs index 6af71bdeb89..fd91d7433e1 100644 --- a/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs +++ b/src/EFCore.Relational/Update/AffectedCountModificationCommandBatch.cs @@ -303,8 +303,7 @@ protected virtual int ConsumeResultSet(int startCommandIndex, RelationalDataRead : commandIndex]; Check.DebugAssert( - !resultSetMapping.HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly), - "!resultSetMapping.HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly)"); + !resultSetMapping.HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly)); command.PropagateResults(reader); @@ -374,8 +373,7 @@ await ThrowAggregateUpdateConcurrencyExceptionAsync( : commandIndex]; Check.DebugAssert( - !resultSetMapping.HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly), - "!resultSetMapping.HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly)"); + !resultSetMapping.HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly)); command.PropagateResults(reader); @@ -412,8 +410,7 @@ protected virtual int ConsumeResultSetWithRowsAffectedOnly(int commandIndex, Rel && ResultSetMappings[commandIndex - 1].HasFlag(ResultSetMapping.NotLastInResultSet)) { Check.DebugAssert( - ResultSetMappings[commandIndex].HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly), - "ResultSetMappings[commandIndex].HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly)"); + ResultSetMappings[commandIndex].HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly)); expectedRowsAffected++; } @@ -456,8 +453,7 @@ protected virtual async Task ConsumeResultSetWithRowsAffectedOnlyAsync( && ResultSetMappings[commandIndex - 1].HasFlag(ResultSetMapping.NotLastInResultSet)) { Check.DebugAssert( - ResultSetMappings[commandIndex].HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly), - "ResultSetMappings[commandIndex].HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly)"); + ResultSetMappings[commandIndex].HasFlag(ResultSetMapping.ResultSetWithRowsAffectedOnly)); expectedRowsAffected++; } diff --git a/src/EFCore.Relational/Update/ColumnModification.cs b/src/EFCore.Relational/Update/ColumnModification.cs index a38ee3e6f4f..12b160614f5 100644 --- a/src/EFCore.Relational/Update/ColumnModification.cs +++ b/src/EFCore.Relational/Update/ColumnModification.cs @@ -207,14 +207,15 @@ private void SetOriginalValue(object? value) public static object? GetCurrentValue(IUpdateEntry entry, IProperty property) => property.DeclaringType is IComplexType { ComplexProperty: var complexProperty } && IsNull(complexProperty, entry) - ? null - : entry.GetCurrentValue(property); + ? null + : entry.GetCurrentValue(property); private static bool IsNull(IComplexProperty complexProperty, IUpdateEntry entry) => (complexProperty.DeclaringType is IComplexType { ComplexProperty: var parentComplexProperty } - && IsNull(parentComplexProperty, entry)) - || (complexProperty.IsNullable && !complexProperty.IsCollection - && entry.GetCurrentValue(complexProperty) == null); + && IsNull(parentComplexProperty, entry)) + || (complexProperty.IsNullable + && !complexProperty.IsCollection + && entry.GetCurrentValue(complexProperty) == null); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -258,10 +259,10 @@ public static bool IsStoreGenerated(IUpdateEntry entry, IProperty property) /// public virtual void AddSharedColumnModification(IColumnModification modification) { - Check.DebugAssert(Entry is not null, "Entry is not null"); - Check.DebugAssert(Property is not null, "Property is not null"); - Check.DebugAssert(modification.Entry is not null, "modification.Entry is not null"); - Check.DebugAssert(modification.Property is not null, "modification.Property is not null"); + Check.DebugAssert(Entry is not null); + Check.DebugAssert(Property is not null); + Check.DebugAssert(modification.Entry is not null); + Check.DebugAssert(modification.Property is not null); _sharedColumnModifications ??= []; @@ -280,8 +281,8 @@ public virtual void AddSharedColumnModification(IColumnModification modification existingEntry.EntityType.DisplayName(), newEntry.EntityType.DisplayName(), Entry.BuildCurrentValuesString(Entry.EntityType.FindPrimaryKey()!.Properties), - Entry.BuildCurrentValuesString(new[] { Property }), - newEntry.BuildCurrentValuesString(new[] { modification.Property }), + Entry.BuildCurrentValuesString([Property]), + newEntry.BuildCurrentValuesString([modification.Property]), ColumnName)); } @@ -333,8 +334,8 @@ public virtual void AddSharedColumnModification(IColumnModification modification existingEntry.EntityType.DisplayName(), newEntry.EntityType.DisplayName(), Entry.BuildCurrentValuesString(Entry.EntityType.FindPrimaryKey()!.Properties), - existingEntry.BuildOriginalValuesString(new[] { Property }), - newEntry.BuildOriginalValuesString(new[] { modification.Property }), + existingEntry.BuildOriginalValuesString([Property]), + newEntry.BuildOriginalValuesString([modification.Property]), ColumnName)); } diff --git a/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs b/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs index bf9b3416f7b..6590593a40e 100644 --- a/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs +++ b/src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs @@ -145,14 +145,14 @@ private IEnumerable CreateCommandBatches( foreach (var command in batch.ModificationCommands) { - batch = StartNewBatch(parameterNameGenerator, command); + batch = StartNewBatch(parameterNameGenerator, command, Dependencies); batch.Complete(moreBatchesExpected: true); yield return batch; } } - batch = StartNewBatch(parameterNameGenerator, modificationCommand); + batch = StartNewBatch(parameterNameGenerator, modificationCommand, Dependencies); } } @@ -176,7 +176,8 @@ private IEnumerable CreateCommandBatches( for (var commandIndex = 0; commandIndex < batch.ModificationCommands.Count; commandIndex++) { - var singleCommandBatch = StartNewBatch(parameterNameGenerator, batch.ModificationCommands[commandIndex]); + var singleCommandBatch = StartNewBatch( + parameterNameGenerator, batch.ModificationCommands[commandIndex], Dependencies); singleCommandBatch.Complete( moreBatchesExpected: moreCommandSets || commandIndex < batch.ModificationCommands.Count - 1); @@ -184,12 +185,15 @@ private IEnumerable CreateCommandBatches( } } - ModificationCommandBatch StartNewBatch( + yield break; + + static ModificationCommandBatch StartNewBatch( ParameterNameGenerator? parameterNameGenerator, - IReadOnlyModificationCommand modificationCommand) + IReadOnlyModificationCommand modificationCommand, + CommandBatchPreparerDependencies dependencies) { parameterNameGenerator?.Reset(); - var batch = Dependencies.ModificationCommandBatchFactory.Create(); + var batch = dependencies.ModificationCommandBatchFactory.Create(); batch.TryAddCommand(modificationCommand); return batch; } @@ -510,7 +514,7 @@ private void Format( var rowForeignKeyValueFactory = ((ForeignKeyConstraint)foreignKey).GetRowForeignKeyValueFactory(); var dependentCommand = reverseDependency ? target : source; - var values = rowForeignKeyValueFactory.CreateDependentKeyValue(dependentCommand, fromOriginalValues: !reverseDependency)!; + var values = rowForeignKeyValueFactory.CreateDependentKeyValue(dependentCommand, fromOriginalValues: !reverseDependency); FormatValues(values, foreignKey.Columns, dependentCommand, builder); builder.Append(" } "); @@ -568,7 +572,7 @@ private void Format( builder.Append("UniqueConstraint { "); var rowForeignKeyValueFactory = ((UniqueConstraint)constraint).GetRowKeyValueFactory(); var dependentCommand = reverseDependency ? target : source; - var values = rowForeignKeyValueFactory.CreateKeyValue(dependentCommand, fromOriginalValues: !reverseDependency)!; + var values = rowForeignKeyValueFactory.CreateKeyValue(dependentCommand, fromOriginalValues: !reverseDependency); FormatValues(values, constraint.Columns, dependentCommand, builder); builder.Append(" } "); @@ -595,8 +599,8 @@ private void Format(ITableIndex index, IReadOnlyModificationCommand source, IRea var rowForeignKeyValueFactory = ((TableIndex)index).GetRowIndexValueFactory(); var dependentCommand = reverseDependency ? target : source; - var indexValue = rowForeignKeyValueFactory.CreateIndexValue(dependentCommand, fromOriginalValues: !reverseDependency)!; - FormatValues(indexValue.Value!, index.Columns, dependentCommand, builder); + var indexValue = rowForeignKeyValueFactory.CreateIndexValue(dependentCommand, fromOriginalValues: !reverseDependency); + FormatValues(indexValue.Value, index.Columns, dependentCommand, builder); builder.Append(" } "); @@ -607,7 +611,7 @@ private void Format(ITableIndex index, IReadOnlyModificationCommand source, IRea } private void FormatValues( - object?[] values, + object?[]? values, IReadOnlyList columns, IReadOnlyModificationCommand dependentCommand, StringBuilder builder) @@ -621,17 +625,9 @@ private void FormatValues( if (_sensitiveLoggingEnabled) { builder.Append(": "); - if (values != null) + if (values?[i] is { } value) { - var value = values[i]; - if (value != null) - { - builder.Append(values[i]); - } - else - { - builder.Append("NULL"); - } + builder.Append(value); } else { diff --git a/src/EFCore.Relational/Update/ModificationCommand.cs b/src/EFCore.Relational/Update/ModificationCommand.cs index 6b08744f549..ccc4d1091ec 100644 --- a/src/EFCore.Relational/Update/ModificationCommand.cs +++ b/src/EFCore.Relational/Update/ModificationCommand.cs @@ -107,8 +107,7 @@ public virtual IReadOnlyList ColumnModifications /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - [Conditional("DEBUG")] - [EntityFrameworkInternal] + [Conditional("DEBUG"), EntityFrameworkInternal] public virtual void AssertColumnsNotInitialized() { if (_columnModifications != null @@ -289,10 +288,10 @@ private List GenerateColumnModifications() } } - if (_entries.Any(e => e.EntityType is IEntityType entityType - && (entityType.IsMappedToJson() - || entityType.GetFlattenedComplexProperties().Any(cp => cp.ComplexType.IsMappedToJson()) - || entityType.GetNavigations().Any(e => e.IsCollection && e.TargetEntityType.IsMappedToJson())))) + if (_entries.Any(e => e.EntityType is { } entityType + && (entityType.IsMappedToJson() + || entityType.GetFlattenedComplexProperties().Any(cp => cp.ComplexType.IsMappedToJson()) + || entityType.GetNavigations().Any(e => e.IsCollection && e.TargetEntityType.IsMappedToJson())))) { HandleJson(columnModifications); } @@ -343,7 +342,11 @@ entry.EntityState is EntityState.Modified or EntityState.Added return columnModifications; void HandleNonJson( - IUpdateEntry entry, ITypeBase structuralType, ITableMapping tableMapping, bool nonMainEntry, ref bool optionalDependentWithAllNull) + IUpdateEntry entry, + ITypeBase structuralType, + ITableMapping tableMapping, + bool nonMainEntry, + ref bool optionalDependentWithAllNull) { foreach (var columnMapping in tableMapping.ColumnMappings) { @@ -361,7 +364,10 @@ void HandleNonJson( } void HandleColumn( - IUpdateEntry entry, IColumnMappingBase columnMapping, bool nonMainEntry, ref bool optionalDependentWithAllNull) + IUpdateEntry entry, + IColumnMappingBase columnMapping, + bool nonMainEntry, + ref bool optionalDependentWithAllNull) { var property = columnMapping.Property; var column = columnMapping.Column; @@ -614,11 +620,12 @@ void HandleSharedColumns( var modifiedMembers = entry.EntityType.GetFlattenedProperties().Where(entry.IsModified).ToList(); if (modifiedMembers.Count == 1) { - result.Add(new JsonPartialUpdatePathEntry( - modifiedMembers[0].GetJsonPropertyName()!, - null, - entry, - modifiedMembers[0])); + result.Add( + new JsonPartialUpdatePathEntry( + modifiedMembers[0].GetJsonPropertyName()!, + null, + entry, + modifiedMembers[0])); } else { @@ -706,10 +713,9 @@ void HandleJson(List columnModifications) } foreach (var jsonCollectionNavigation in entry.EntityType.GetNavigations() - .Where( - n => n.IsCollection - && n.TargetEntityType.IsMappedToJson() - && (entry.GetCurrentValue(n) as IEnumerable)?.Any() == false)) + .Where(n => n.IsCollection + && n.TargetEntityType.IsMappedToJson() + && (entry.GetCurrentValue(n) as IEnumerable)?.Any() == false)) { var jsonCollectionEntityType = jsonCollectionNavigation.TargetEntityType; var jsonCollectionColumn = @@ -740,10 +746,7 @@ void HandleJson(List columnModifications) var jsonColumn = GetTableMapping(entry.EntityType)!.Table.FindColumn(complexType.GetContainerColumnName()!)!; if (!jsonColumnsUpdateMap.ContainsKey(jsonColumn)) { - var jsonPartialUpdateInfo = new List - { - new("$", null, entry, complexProperty) - }; + var jsonPartialUpdateInfo = new List { new("$", null, entry, complexProperty) }; jsonColumnsUpdateMap[jsonColumn] = jsonPartialUpdateInfo; } } @@ -936,7 +939,12 @@ private void WriteJson( } #pragma warning disable EF1001 // Internal EF Core API usage. - private void WriteJsonObject(Utf8JsonWriter writer, IInternalEntry parentEntry, IInternalEntry entry, ITypeBase structuralType, int? ordinal) + private void WriteJsonObject( + Utf8JsonWriter writer, + IInternalEntry parentEntry, + IInternalEntry entry, + ITypeBase structuralType, + int? ordinal) #pragma warning restore EF1001 // Internal EF Core API usage. { foreach (var property in structuralType.GetProperties()) diff --git a/src/EFCore.Relational/Update/ReaderModificationCommandBatch.cs b/src/EFCore.Relational/Update/ReaderModificationCommandBatch.cs index 0e0611667be..c3691158c24 100644 --- a/src/EFCore.Relational/Update/ReaderModificationCommandBatch.cs +++ b/src/EFCore.Relational/Update/ReaderModificationCommandBatch.cs @@ -121,8 +121,7 @@ public override bool TryAddCommand(IReadOnlyModificationCommand modificationComm } Check.DebugAssert( - ReferenceEquals(modificationCommand, _modificationCommands[^1]), - "ReferenceEquals(modificationCommand, _modificationCommands[^1])"); + ReferenceEquals(modificationCommand, _modificationCommands[^1])); RollbackLastCommand(modificationCommand); @@ -273,8 +272,8 @@ protected virtual void AddParameters(IReadOnlyModificationCommand modificationCo var modifications = modificationCommand.StoreStoredProcedure is null ? modificationCommand.ColumnModifications - : modificationCommand.ColumnModifications.Where( - c => c.Column is IStoreStoredProcedureParameter or IStoreStoredProcedureReturnValue); + : modificationCommand.ColumnModifications.Where(c + => c.Column is IStoreStoredProcedureParameter or IStoreStoredProcedureReturnValue); foreach (var columnModification in modifications) { @@ -310,7 +309,7 @@ protected virtual void AddParameter(IColumnModification columnModification) if (columnModification.UseOriginalValueParameter) { - Check.DebugAssert(direction.HasFlag(ParameterDirection.Input), "direction.HasFlag(ParameterDirection.Input)"); + Check.DebugAssert(direction.HasFlag(ParameterDirection.Input)); AddParameterCore(columnModification.OriginalParameterName, columnModification.OriginalValue); } diff --git a/src/EFCore.SqlServer.HierarchyId/Extensions/SqlServerHierarchyIdServiceCollectionExtensions.cs b/src/EFCore.SqlServer.HierarchyId/Extensions/SqlServerHierarchyIdServiceCollectionExtensions.cs index c9a715c876d..f4286de6c93 100644 --- a/src/EFCore.SqlServer.HierarchyId/Extensions/SqlServerHierarchyIdServiceCollectionExtensions.cs +++ b/src/EFCore.SqlServer.HierarchyId/Extensions/SqlServerHierarchyIdServiceCollectionExtensions.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; diff --git a/src/EFCore.SqlServer.HierarchyId/Infrastructure/Internal/SqlServerHierarchyIdOptionsExtension.cs b/src/EFCore.SqlServer.HierarchyId/Infrastructure/Internal/SqlServerHierarchyIdOptionsExtension.cs index dc83a909c5b..68c65d1cdc4 100644 --- a/src/EFCore.SqlServer.HierarchyId/Infrastructure/Internal/SqlServerHierarchyIdOptionsExtension.cs +++ b/src/EFCore.SqlServer.HierarchyId/Infrastructure/Internal/SqlServerHierarchyIdOptionsExtension.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.SqlServer.Internal; using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; diff --git a/src/EFCore.SqlServer.HierarchyId/Query/Internal/SqlServerHierarchyIdMethodCallTranslatorPlugin.cs b/src/EFCore.SqlServer.HierarchyId/Query/Internal/SqlServerHierarchyIdMethodCallTranslatorPlugin.cs index c60b5ee8b22..3b71aa476b2 100644 --- a/src/EFCore.SqlServer.HierarchyId/Query/Internal/SqlServerHierarchyIdMethodCallTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.HierarchyId/Query/Internal/SqlServerHierarchyIdMethodCallTranslatorPlugin.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.EntityFrameworkCore.Query; - namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; /// @@ -22,7 +20,7 @@ public class SqlServerHierarchyIdMethodCallTranslatorPlugin : IMethodCallTransla public SqlServerHierarchyIdMethodCallTranslatorPlugin( IRelationalTypeMappingSource typeMappingSource, ISqlExpressionFactory sqlExpressionFactory) - => Translators = new IMethodCallTranslator[] { new SqlServerHierarchyIdMethodTranslator(typeMappingSource, sqlExpressionFactory) }; + => Translators = [new SqlServerHierarchyIdMethodTranslator(typeMappingSource, sqlExpressionFactory)]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.SqlServer.HierarchyId/Query/Internal/SqlServerHierarchyIdMethodTranslator.cs b/src/EFCore.SqlServer.HierarchyId/Query/Internal/SqlServerHierarchyIdMethodTranslator.cs index 5e12bf80c8c..ae69caf64ae 100644 --- a/src/EFCore.SqlServer.HierarchyId/Query/Internal/SqlServerHierarchyIdMethodTranslator.cs +++ b/src/EFCore.SqlServer.HierarchyId/Query/Internal/SqlServerHierarchyIdMethodTranslator.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using ExpressionExtensions = Microsoft.EntityFrameworkCore.Query.ExpressionExtensions; diff --git a/src/EFCore.SqlServer.HierarchyId/build/net10.0/Microsoft.EntityFrameworkCore.SqlServer.HierarchyId.targets b/src/EFCore.SqlServer.HierarchyId/build/net10.0/Microsoft.EntityFrameworkCore.SqlServer.HierarchyId.targets index b445f6e4b57..bf8417baacf 100644 --- a/src/EFCore.SqlServer.HierarchyId/build/net10.0/Microsoft.EntityFrameworkCore.SqlServer.HierarchyId.targets +++ b/src/EFCore.SqlServer.HierarchyId/build/net10.0/Microsoft.EntityFrameworkCore.SqlServer.HierarchyId.targets @@ -32,7 +32,10 @@ Outputs="$(EFCoreSqlServerHierarchyIdFile)"> - <_Parameter1>Microsoft.EntityFrameworkCore.SqlServer.Design.Internal.SqlServerHierarchyIdDesignTimeServices, Microsoft.EntityFrameworkCore.SqlServer.HierarchyId + <_Parameter1> + Microsoft.EntityFrameworkCore.SqlServer.Design.Internal.SqlServerHierarchyIdDesignTimeServices, + Microsoft.EntityFrameworkCore.SqlServer.HierarchyId + <_Parameter2>Microsoft.EntityFrameworkCore.SqlServer diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs index 1ecdeb03db4..72924b55db9 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMemberTranslator.cs @@ -45,10 +45,10 @@ public SqlServerGeometryCollectionMemberTranslator(ISqlExpressionFactory sqlExpr return _sqlExpressionFactory.Function( instance!, "STNumGeometries", - Enumerable.Empty(), + [], nullable: true, instancePropagatesNullability: true, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], returnType); } diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs index 3e3629586a2..c11fabd44d2 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryCollectionMethodTranslator.cs @@ -47,7 +47,7 @@ public SqlServerGeometryCollectionMethodTranslator( && method.GetGenericMethodDefinition() == EnumerableMethods.ElementAt && method.ReturnType == typeof(Geometry) && arguments is [var collection, var index] - && _typeMappingSource.FindMapping(typeof(Geometry), collection.TypeMapping!.StoreType) is RelationalTypeMapping geometryTypeMapping) + && _typeMappingSource.FindMapping(typeof(Geometry), collection.TypeMapping!.StoreType) is { } geometryTypeMapping) { return _sqlExpressionFactory.Function( collection, diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs index ab5f8c35bbe..441c55ee860 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMemberTranslator.cs @@ -87,10 +87,10 @@ public SqlServerGeometryMemberTranslator( return _sqlExpressionFactory.Function( instance, functionName, - Enumerable.Empty(), + [], nullable: true, instancePropagatesNullability: true, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], returnType, resultTypeMapping); } @@ -142,10 +142,10 @@ public SqlServerGeometryMemberTranslator( _sqlExpressionFactory.Function( instance, "STGeometryType", - Enumerable.Empty(), + [], nullable: true, instancePropagatesNullability: true, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], typeof(string)), whenClauses, null); diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs index 63410e68113..ef43cea02c5 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerGeometryMethodTranslator.cs @@ -139,12 +139,11 @@ public SqlServerGeometryMethodTranslator( return _sqlExpressionFactory.Function( instance, "STGeometryN", - new[] - { + [ _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) - }, + ], nullable: true, instancePropagatesNullability: true, argumentsPropagateNullability: Statics.FalseArrays[1], @@ -168,7 +167,7 @@ public SqlServerGeometryMethodTranslator( : _typeMappingSource.FindMapping(argument.Type))); } - var finalArguments = Simplify(new[] { typeMappedArguments[0] }, isGeography); + var finalArguments = Simplify([typeMappedArguments[0]], isGeography); return _sqlExpressionFactory.LessThanOrEqual( _sqlExpressionFactory.Function( diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs index 8615e1cc6e3..3750c4a1b8a 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMemberTranslator.cs @@ -70,10 +70,10 @@ public SqlServerLineStringMemberTranslator( return _sqlExpressionFactory.Function( instance, functionName, - Enumerable.Empty(), + [], nullable: true, instancePropagatesNullability: true, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], returnType, resultTypeMapping); } diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs index 174d1dd4c19..a9fc06e162b 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerLineStringMethodTranslator.cs @@ -52,12 +52,11 @@ public SqlServerLineStringMethodTranslator( return _sqlExpressionFactory.Function( instance, "STPointN", - new[] - { + [ _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) - }, + ], nullable: true, instancePropagatesNullability: true, argumentsPropagateNullability: Statics.TrueArrays[1], diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs index 046f5d53258..8feee41a6fd 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerMultiLineStringMemberTranslator.cs @@ -45,10 +45,10 @@ public SqlServerMultiLineStringMemberTranslator(ISqlExpressionFactory sqlExpress return _sqlExpressionFactory.Function( instance!, "STIsClosed", - Enumerable.Empty(), + [], nullable: true, instancePropagatesNullability: true, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], returnType); } diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteAggregateMethodCallTranslatorPlugin.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteAggregateMethodCallTranslatorPlugin.cs index 99866bd6eef..81645f6ef98 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteAggregateMethodCallTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteAggregateMethodCallTranslatorPlugin.cs @@ -20,10 +20,10 @@ public class SqlServerNetTopologySuiteAggregateMethodCallTranslatorPlugin : IAgg public SqlServerNetTopologySuiteAggregateMethodCallTranslatorPlugin( IRelationalTypeMappingSource typeMappingSource, ISqlExpressionFactory sqlExpressionFactory) - => Translators = new IAggregateMethodCallTranslator[] - { + => Translators = + [ new SqlServerNetTopologySuiteAggregateMethodTranslator(sqlExpressionFactory, typeMappingSource) - }; + ]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteAggregateMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteAggregateMethodTranslator.cs index 662d81750c4..d72593d2d40 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteAggregateMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteAggregateMethodTranslator.cs @@ -99,7 +99,7 @@ public SqlServerNetTopologySuiteAggregateMethodTranslator( return _sqlExpressionFactory.Function( $"{typeMapping.StoreType}::{functionName}", - new[] { sqlExpression }, + [sqlExpression], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[1], method.ReturnType, diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteDbFunctionsMethodCallTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteDbFunctionsMethodCallTranslator.cs index d9fd19c22be..45ead268003 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteDbFunctionsMethodCallTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteDbFunctionsMethodCallTranslator.cs @@ -51,10 +51,10 @@ public SqlServerNetTopologySuiteDbFunctionsMethodCallTranslator( return _sqlExpressionFactory.Function( arguments[1], "STCurveToLine", - Enumerable.Empty(), + [], nullable: true, instancePropagatesNullability: true, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], typeof(Geometry), arguments[1].TypeMapping); } diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs index 2b1d8e388f4..1ae238cfe37 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMemberTranslatorPlugin.cs @@ -20,15 +20,15 @@ public class SqlServerNetTopologySuiteMemberTranslatorPlugin : IMemberTranslator public SqlServerNetTopologySuiteMemberTranslatorPlugin( IRelationalTypeMappingSource typeMappingSource, ISqlExpressionFactory sqlExpressionFactory) - => Translators = new IMemberTranslator[] - { + => Translators = + [ new SqlServerGeometryMemberTranslator(typeMappingSource, sqlExpressionFactory), new SqlServerGeometryCollectionMemberTranslator(sqlExpressionFactory), new SqlServerLineStringMemberTranslator(typeMappingSource, sqlExpressionFactory), new SqlServerMultiLineStringMemberTranslator(sqlExpressionFactory), new SqlServerPointMemberTranslator(sqlExpressionFactory), new SqlServerPolygonMemberTranslator(typeMappingSource, sqlExpressionFactory) - }; + ]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs index 57701851fac..352edc1f30c 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerNetTopologySuiteMethodCallTranslatorPlugin.cs @@ -20,14 +20,14 @@ public class SqlServerNetTopologySuiteMethodCallTranslatorPlugin : IMethodCallTr public SqlServerNetTopologySuiteMethodCallTranslatorPlugin( IRelationalTypeMappingSource typeMappingSource, ISqlExpressionFactory sqlExpressionFactory) - => Translators = new IMethodCallTranslator[] - { + => Translators = + [ new SqlServerGeometryMethodTranslator(typeMappingSource, sqlExpressionFactory), new SqlServerGeometryCollectionMethodTranslator(typeMappingSource, sqlExpressionFactory), new SqlServerLineStringMethodTranslator(typeMappingSource, sqlExpressionFactory), new SqlServerNetTopologySuiteDbFunctionsMethodCallTranslator(typeMappingSource, sqlExpressionFactory), new SqlServerPolygonMethodTranslator(typeMappingSource, sqlExpressionFactory) - }; + ]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs index 269e6541ccb..035261d5a0e 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMemberTranslator.cs @@ -67,7 +67,7 @@ public SqlServerPolygonMemberTranslator( return _sqlExpressionFactory.Function( instance, "RingN", - new[] { _sqlExpressionFactory.Constant(1) }, + [_sqlExpressionFactory.Constant(1)], nullable: true, instancePropagatesNullability: true, argumentsPropagateNullability: Statics.FalseArrays[1], @@ -81,10 +81,10 @@ public SqlServerPolygonMemberTranslator( _sqlExpressionFactory.Function( instance, "NumRings", - Enumerable.Empty(), + [], nullable: true, instancePropagatesNullability: true, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], returnType), _sqlExpressionFactory.Constant(1)); } @@ -99,10 +99,10 @@ public SqlServerPolygonMemberTranslator( return _sqlExpressionFactory.Function( instance, functionName, - Enumerable.Empty(), + [], nullable: true, instancePropagatesNullability: true, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], returnType, resultTypeMapping); } diff --git a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs index 661eeb0e5f5..f7179f5db3b 100644 --- a/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs +++ b/src/EFCore.SqlServer.NTS/Query/Internal/SqlServerPolygonMethodTranslator.cs @@ -57,12 +57,11 @@ public SqlServerPolygonMethodTranslator( return _sqlExpressionFactory.Function( instance, "RingN", - new[] - { + [ _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(2)) - }, + ], nullable: true, instancePropagatesNullability: true, argumentsPropagateNullability: Statics.TrueArrays[1], @@ -73,12 +72,11 @@ public SqlServerPolygonMethodTranslator( return _sqlExpressionFactory.Function( instance, "STInteriorRingN", - new[] - { + [ _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) - }, + ], nullable: true, instancePropagatesNullability: true, argumentsPropagateNullability: Statics.TrueArrays[1], diff --git a/src/EFCore.SqlServer.NTS/build/net10.0/Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite.targets b/src/EFCore.SqlServer.NTS/build/net10.0/Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite.targets index d4029a430f5..d35c2471099 100644 --- a/src/EFCore.SqlServer.NTS/build/net10.0/Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite.targets +++ b/src/EFCore.SqlServer.NTS/build/net10.0/Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite.targets @@ -32,7 +32,10 @@ Outputs="$(EFCoreSqlServerNetTopologySuiteFile)"> - <_Parameter1>Microsoft.EntityFrameworkCore.SqlServer.Design.Internal.SqlServerNetTopologySuiteDesignTimeServices, Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite + <_Parameter1> + Microsoft.EntityFrameworkCore.SqlServer.Design.Internal.SqlServerNetTopologySuiteDesignTimeServices, + Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite + <_Parameter2>Microsoft.EntityFrameworkCore.SqlServer diff --git a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs index eb29b0c3b03..f7a5067f129 100644 --- a/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs +++ b/src/EFCore.SqlServer/Design/Internal/SqlServerAnnotationCodeGenerator.cs @@ -65,7 +65,8 @@ private static readonly MethodInfo ComplexTypePropertyIsSparseMethodInfo private static readonly MethodInfo ComplexTypePrimitiveCollectionIsSparseMethodInfo = typeof(SqlServerComplexTypePrimitiveCollectionBuilderExtensions).GetRuntimeMethod( - nameof(SqlServerComplexTypePrimitiveCollectionBuilderExtensions.IsSparse), [typeof(ComplexTypePrimitiveCollectionBuilder), typeof(bool)])!; + nameof(SqlServerComplexTypePrimitiveCollectionBuilderExtensions.IsSparse), + [typeof(ComplexTypePrimitiveCollectionBuilder), typeof(bool)])!; private static readonly MethodInfo PropertyUseIdentityColumnsMethodInfo = typeof(SqlServerPropertyBuilderExtensions).GetRuntimeMethod( @@ -73,7 +74,8 @@ private static readonly MethodInfo PropertyUseIdentityColumnsMethodInfo private static readonly MethodInfo ComplexTypePropertyUseIdentityColumnsMethodInfo = typeof(SqlServerComplexTypePropertyBuilderExtensions).GetRuntimeMethod( - nameof(SqlServerComplexTypePropertyBuilderExtensions.UseIdentityColumn), [typeof(ComplexTypePropertyBuilder), typeof(long), typeof(int)])!; + nameof(SqlServerComplexTypePropertyBuilderExtensions.UseIdentityColumn), + [typeof(ComplexTypePropertyBuilder), typeof(long), typeof(int)])!; private static readonly MethodInfo PropertyUseHiLoMethodInfo = typeof(SqlServerPropertyBuilderExtensions).GetRuntimeMethod( @@ -81,7 +83,8 @@ private static readonly MethodInfo PropertyUseHiLoMethodInfo private static readonly MethodInfo ComplexTypePropertyUseHiLoMethodInfo = typeof(SqlServerComplexTypePropertyBuilderExtensions).GetRuntimeMethod( - nameof(SqlServerComplexTypePropertyBuilderExtensions.UseHiLo), [typeof(ComplexTypePropertyBuilder), typeof(string), typeof(string)])!; + nameof(SqlServerComplexTypePropertyBuilderExtensions.UseHiLo), + [typeof(ComplexTypePropertyBuilder), typeof(string), typeof(string)])!; private static readonly MethodInfo PropertyUseSequenceMethodInfo = typeof(SqlServerPropertyBuilderExtensions).GetRuntimeMethod( @@ -89,7 +92,8 @@ private static readonly MethodInfo PropertyUseSequenceMethodInfo private static readonly MethodInfo ComplexTypePropertyUseSequenceMethodInfo = typeof(SqlServerComplexTypePropertyBuilderExtensions).GetRuntimeMethod( - nameof(SqlServerComplexTypePropertyBuilderExtensions.UseSequence), [typeof(ComplexTypePropertyBuilder), typeof(string), typeof(string)])!; + nameof(SqlServerComplexTypePropertyBuilderExtensions.UseSequence), + [typeof(ComplexTypePropertyBuilder), typeof(string), typeof(string)])!; private static readonly MethodInfo IndexIsClusteredMethodInfo = typeof(SqlServerIndexBuilderExtensions).GetRuntimeMethod( @@ -168,7 +172,7 @@ public override IReadOnlyList GenerateFluentApiCalls( { var fragments = new List(base.GenerateFluentApiCalls(model, annotations)); - if (GenerateValueGenerationStrategy(annotations, model, onModel: true, complexType: false) is MethodCallCodeFragment valueGenerationStrategy) + if (GenerateValueGenerationStrategy(annotations, model, onModel: true, complexType: false) is { } valueGenerationStrategy) { fragments.Add(valueGenerationStrategy); } @@ -201,25 +205,17 @@ public override IReadOnlyList GenerateFluentApiCalls( IProperty property, IDictionary annotations) { - var defaultConstraintNameAnnotation = default(IAnnotation); var defaultValueAnnotation = default(IAnnotation); var defaultValueSqlAnnotation = default(IAnnotation); // named default constraint must be handled on the provider level - model builder methods live on provider rather than relational // so removing the annotations before calling base - if (annotations.TryGetValue(RelationalAnnotationNames.DefaultConstraintName, out defaultConstraintNameAnnotation)) + if (annotations.TryGetValue(RelationalAnnotationNames.DefaultConstraintName, out var defaultConstraintNameAnnotation)) { if (defaultConstraintNameAnnotation.Value as string != string.Empty) { - if (annotations.TryGetValue(RelationalAnnotationNames.DefaultValue, out defaultValueAnnotation)) - { - annotations.Remove(RelationalAnnotationNames.DefaultValue); - } - else - { - var defaultValueSqlAnnotationExists = annotations.TryGetValue(RelationalAnnotationNames.DefaultValueSql, out defaultValueSqlAnnotation); - annotations.Remove(RelationalAnnotationNames.DefaultValueSql); - } + annotations.Remove(RelationalAnnotationNames.DefaultValue, out defaultValueAnnotation); + annotations.Remove(RelationalAnnotationNames.DefaultValueSql, out defaultValueSqlAnnotation); } annotations.Remove(RelationalAnnotationNames.DefaultConstraintName); @@ -239,7 +235,9 @@ public override IReadOnlyList GenerateFluentApiCalls( } else { - Check.DebugAssert(defaultValueSqlAnnotation != null, $"Default constraint name was set for {property.Name}, but DefaultValue and DefaultValueSql are both null."); + Check.DebugAssert( + defaultValueSqlAnnotation != null, + $"Default constraint name was set for {property.Name}, but DefaultValue and DefaultValueSql are both null."); fragments.Add( new MethodCallCodeFragment( nameof(SqlServerPropertyBuilderExtensions.HasDefaultValueSql), @@ -250,13 +248,14 @@ public override IReadOnlyList GenerateFluentApiCalls( var isPrimitiveCollection = property.IsPrimitiveCollection; - if (GenerateValueGenerationStrategy(annotations, property.DeclaringType.Model, onModel: false, complexType: property.DeclaringType is IComplexType) is MethodCallCodeFragment - valueGenerationStrategy) + if (GenerateValueGenerationStrategy( + annotations, property.DeclaringType.Model, onModel: false, + complexType: property.DeclaringType is IComplexType) is { } valueGenerationStrategy) { fragments.Add(valueGenerationStrategy); } - if (GetAndRemove(annotations, SqlServerAnnotationNames.Sparse) is bool isSparse) + if (GetAndRemove(annotations, SqlServerAnnotationNames.Sparse) is { } isSparse) { var methodInfo = isPrimitiveCollection ? property.DeclaringType is IComplexType @@ -286,7 +285,7 @@ public override IReadOnlyList GenerateFluentApiCalls( { var fragments = new List(base.GenerateFluentApiCalls(entityType, annotations)); - if (GetAndRemove(annotations, SqlServerAnnotationNames.MemoryOptimized) is bool isMemoryOptimized) + if (GetAndRemove(annotations, SqlServerAnnotationNames.MemoryOptimized) is { } isMemoryOptimized) { fragments.Add( isMemoryOptimized @@ -566,7 +565,7 @@ private static void GenerateSimpleFluentApiCall( { if (annotations.Remove(annotationName, out var annotation)) { - if (annotation.Value is object annotationValue) + if (annotation.Value is { } annotationValue) { methodCallCodeFragments.Add( new MethodCallCodeFragment(methodInfo, annotationValue)); diff --git a/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePropertyBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePropertyBuilderExtensions.cs index 6018502489a..b50adf17b85 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePropertyBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerComplexTypePropertyBuilderExtensions.cs @@ -295,7 +295,8 @@ public static ComplexTypePropertyBuilder HasDefaultValue( this ComplexTypePropertyBuilder propertyBuilder, object? value, string defaultConstraintName) - => (ComplexTypePropertyBuilder)HasDefaultValue((ComplexTypePropertyBuilder)propertyBuilder, value, defaultConstraintName); + => (ComplexTypePropertyBuilder)HasDefaultValue( + (ComplexTypePropertyBuilder)propertyBuilder, value, defaultConstraintName); /// /// Configures the default value expression for the column that the property maps to when targeting a relational database. @@ -335,5 +336,6 @@ public static ComplexTypePropertyBuilder HasDefaultValueSql propertyBuilder, string? sql, string defaultConstraintName) - => (ComplexTypePropertyBuilder)HasDefaultValueSql((ComplexTypePropertyBuilder)propertyBuilder, sql, defaultConstraintName); + => (ComplexTypePropertyBuilder)HasDefaultValueSql( + (ComplexTypePropertyBuilder)propertyBuilder, sql, defaultConstraintName); } diff --git a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs index baa97ffb632..355aeba7845 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs @@ -2462,14 +2462,18 @@ public static long PatIndex( /// /// The instance. /// - /// A string with the name of the distance metric to use to calculate the distance between the two given vectors. The following distance metrics are supported: cosine, euclidean or dot. + /// A string with the name of the distance metric to use to calculate the distance between the two given vectors. The following distance + /// metrics are supported: cosine, euclidean or dot. /// /// The first vector. /// The second vector. /// /// Vector distance is always exact and doesn't use any vector index, even if available. /// - /// SQL Server documentation for VECTOR_DISTANCE. + /// + /// SQL Server documentation for + /// VECTOR_DISTANCE. + /// /// Vectors in the SQL Database Engine. public static double VectorDistance( this DbFunctions _, diff --git a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs index 9d55811eb3e..c9417eb9e04 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerEntityTypeExtensions.cs @@ -199,7 +199,7 @@ public static void SetPeriodEndPropertyName(this IMutableEntityType entityType, : entityType[SqlServerAnnotationNames.TemporalHistoryTableName] is string historyTableName ? historyTableName : entityType[SqlServerAnnotationNames.IsTemporal] as bool? == true - ? entityType.GetTableName() is string tableName + ? entityType.GetTableName() is { } tableName ? tableName + DefaultHistoryTableNameSuffix : null : null; diff --git a/src/EFCore.SqlServer/Extensions/SqlServerPrimitiveCollectionBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerPrimitiveCollectionBuilderExtensions.cs index 7aeaad211a7..5d8857c8603 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerPrimitiveCollectionBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerPrimitiveCollectionBuilderExtensions.cs @@ -89,7 +89,8 @@ public static PrimitiveCollectionBuilder HasDefaultValue( this PrimitiveCollectionBuilder primitiveCollectionBuilder, object? value, string defaultConstraintName) - => (PrimitiveCollectionBuilder)HasDefaultValue((PrimitiveCollectionBuilder)primitiveCollectionBuilder, value, defaultConstraintName); + => (PrimitiveCollectionBuilder)HasDefaultValue( + (PrimitiveCollectionBuilder)primitiveCollectionBuilder, value, defaultConstraintName); /// /// Configures the default value expression for the column that the property maps to when targeting a relational database. @@ -129,5 +130,6 @@ public static PrimitiveCollectionBuilder HasDefaultValueSql primitiveCollectionBuilder, string? sql, string defaultConstraintName) - => (PrimitiveCollectionBuilder)HasDefaultValueSql((PrimitiveCollectionBuilder)primitiveCollectionBuilder, sql, defaultConstraintName); + => (PrimitiveCollectionBuilder)HasDefaultValueSql( + (PrimitiveCollectionBuilder)primitiveCollectionBuilder, sql, defaultConstraintName); } diff --git a/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs index f1aba330da3..fe5ae01d00b 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerPropertyBuilderExtensions.cs @@ -907,13 +907,13 @@ public static bool CanSetDefaultValue( string defaultConstraintName, bool fromDataAnnotation = false) => propertyBuilder.CanSetAnnotation( - RelationalAnnotationNames.DefaultValue, - value, - fromDataAnnotation) - && propertyBuilder.CanSetAnnotation( - RelationalAnnotationNames.DefaultConstraintName, - defaultConstraintName, - fromDataAnnotation); + RelationalAnnotationNames.DefaultValue, + value, + fromDataAnnotation) + && propertyBuilder.CanSetAnnotation( + RelationalAnnotationNames.DefaultConstraintName, + defaultConstraintName, + fromDataAnnotation); /// /// Configures the default value expression for the column that the property maps to when targeting SQL Server. @@ -1008,11 +1008,11 @@ public static bool CanSetDefaultValueSql( string defaultConstraintName, bool fromDataAnnotation = false) => propertyBuilder.CanSetAnnotation( - RelationalAnnotationNames.DefaultValueSql, - sql, - fromDataAnnotation) - && propertyBuilder.CanSetAnnotation( - RelationalAnnotationNames.DefaultConstraintName, - defaultConstraintName, - fromDataAnnotation); + RelationalAnnotationNames.DefaultValueSql, + sql, + fromDataAnnotation) + && propertyBuilder.CanSetAnnotation( + RelationalAnnotationNames.DefaultConstraintName, + defaultConstraintName, + fromDataAnnotation); } diff --git a/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs index 0a31a789ab9..90254052f1a 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerPropertyExtensions.cs @@ -755,12 +755,11 @@ internal static SqlServerValueGenerationStrategy GetValueGenerationStrategy( return sharedTableRootProperty.GetValueGenerationStrategy(storeObject, typeMappingSource) == SqlServerValueGenerationStrategy.IdentityColumn && table.StoreObjectType == StoreObjectType.Table - && !property.GetContainingForeignKeys().Any( - fk => - !fk.IsBaseLinking() - || (StoreObjectIdentifier.Create(fk.PrincipalEntityType, StoreObjectType.Table) - is StoreObjectIdentifier principal - && fk.GetConstraintName(table, principal) != null)) + && !property.GetContainingForeignKeys().Any(fk => + !fk.IsBaseLinking() + || (StoreObjectIdentifier.Create(fk.PrincipalEntityType, StoreObjectType.Table) + is { } principal + && fk.GetConstraintName(table, principal) != null)) ? SqlServerValueGenerationStrategy.IdentityColumn : SqlServerValueGenerationStrategy.None; } @@ -771,12 +770,11 @@ is StoreObjectIdentifier principal || property.GetDefaultValueSql(storeObject) != null || property.GetComputedColumnSql(storeObject) != null || property.GetContainingForeignKeys() - .Any( - fk => - !fk.IsBaseLinking() - || (StoreObjectIdentifier.Create(fk.PrincipalEntityType, StoreObjectType.Table) - is StoreObjectIdentifier principal - && fk.GetConstraintName(table, principal) != null))) + .Any(fk => + !fk.IsBaseLinking() + || (StoreObjectIdentifier.Create(fk.PrincipalEntityType, StoreObjectType.Table) + is { } principal + && fk.GetConstraintName(table, principal) != null))) { return SqlServerValueGenerationStrategy.None; } diff --git a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs index 7e8c0696546..7100f36ee51 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerServiceCollectionExtensions.cs @@ -61,12 +61,11 @@ public static IServiceCollection AddSqlServer( Action? sqlServerOptionsAction = null, Action? optionsAction = null) where TContext : DbContext - => serviceCollection.AddDbContext( - (_, options) => - { - optionsAction?.Invoke(options); - options.UseSqlServer(connectionString, sqlServerOptionsAction); - }); + => serviceCollection.AddDbContext((_, options) => + { + optionsAction?.Invoke(options); + options.UseSqlServer(connectionString, sqlServerOptionsAction); + }); /// /// @@ -135,12 +134,11 @@ public static IServiceCollection AddAzureSql( Action? azureSqlOptionsAction = null, Action? optionsAction = null) where TContext : DbContext - => serviceCollection.AddDbContext( - (_, options) => - { - optionsAction?.Invoke(options); - options.UseAzureSql(connectionString, azureSqlOptionsAction); - }); + => serviceCollection.AddDbContext((_, options) => + { + optionsAction?.Invoke(options); + options.UseAzureSql(connectionString, azureSqlOptionsAction); + }); /// /// @@ -209,12 +207,11 @@ public static IServiceCollection AddAzureSynapse( Action? azureSynapseOptionsAction = null, Action? optionsAction = null) where TContext : DbContext - => serviceCollection.AddDbContext( - (_, options) => - { - optionsAction?.Invoke(options); - options.UseAzureSynapse(connectionString, azureSynapseOptionsAction); - }); + => serviceCollection.AddDbContext((_, options) => + { + optionsAction?.Invoke(options); + options.UseAzureSynapse(connectionString, azureSynapseOptionsAction); + }); /// /// @@ -279,13 +276,12 @@ private static IServiceCollection AddEntityFrameworkSqlEngine(IServiceCollection .TryAdd() .TryAdd() .TryAdd(p => p.GetRequiredService()) - .TryAddProviderSpecificServices( - b => b - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddSingleton() - .TryAddScoped()) + .TryAddProviderSpecificServices(b => b + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddSingleton() + .TryAddScoped()) .TryAddCoreServices(); return serviceCollection; diff --git a/src/EFCore.SqlServer/Extensions/SqlServerTableExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerTableExtensions.cs index 15f542e6949..62d7de7cba7 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerTableExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerTableExtensions.cs @@ -24,8 +24,8 @@ public static bool IsSqlOutputClauseUsed(this ITable table) return isSqlOutputClauseUsed; } - isSqlOutputClauseUsed = table.EntityTypeMappings.All( - e => ((IEntityType)e.TypeBase).IsSqlOutputClauseUsed(StoreObjectIdentifier.Table(table.Name, table.Schema))); + isSqlOutputClauseUsed = table.EntityTypeMappings.All(e + => ((IEntityType)e.TypeBase).IsSqlOutputClauseUsed(StoreObjectIdentifier.Table(table.Name, table.Schema))); table.SetRuntimeAnnotation(SqlServerAnnotationNames.UseSqlOutputClause, isSqlOutputClauseUsed); diff --git a/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerModelValidator.cs b/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerModelValidator.cs index b38966b9f7d..9dc3f76bf27 100644 --- a/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerModelValidator.cs +++ b/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerModelValidator.cs @@ -62,9 +62,8 @@ protected virtual void ValidateDecimalColumns( { foreach (IConventionProperty property in model.GetEntityTypes() .SelectMany(t => t.GetDeclaredProperties()) - .Where( - p => p.ClrType.UnwrapNullableType() == typeof(decimal) - && !p.IsForeignKey())) + .Where(p => p.ClrType.UnwrapNullableType() == typeof(decimal) + && !p.IsForeignKey())) { var valueConverterConfigurationSource = property.GetValueConverterConfigurationSource(); var valueConverterProviderType = property.GetValueConverter()?.ProviderClrType; @@ -103,17 +102,19 @@ protected virtual void ValidateVectorColumns( IDiagnosticsLogger logger) { foreach (IConventionProperty property in model.GetEntityTypes() - .SelectMany(t => t.GetDeclaredProperties()) - .Where(p => p.ClrType.UnwrapNullableType() == typeof(SqlVector))) + .SelectMany(t => t.GetDeclaredProperties()) + .Where(p => p.ClrType.UnwrapNullableType() == typeof(SqlVector))) { if (property.GetTypeMapping() is not SqlServerVectorTypeMapping { Size: not null } vectorTypeMapping) { - throw new InvalidOperationException(SqlServerStrings.VectorDimensionsMissing(property.DeclaringType.DisplayName(), property.Name)); + throw new InvalidOperationException( + SqlServerStrings.VectorDimensionsMissing(property.DeclaringType.DisplayName(), property.Name)); } if (property.DeclaringType.IsMappedToJson()) { - throw new InvalidOperationException(SqlServerStrings.VectorPropertiesNotSupportedInJson(property.DeclaringType.DisplayName(), property.Name)); + throw new InvalidOperationException( + SqlServerStrings.VectorPropertiesNotSupportedInJson(property.DeclaringType.DisplayName(), property.Name)); } } } @@ -132,9 +133,8 @@ protected virtual void ValidateByteIdentityMapping( { // TODO: Validate this per table foreach (var property in entityType.GetDeclaredProperties() - .Where( - p => p.ClrType.UnwrapNullableType() == typeof(byte) - && p.GetValueGenerationStrategy() == SqlServerValueGenerationStrategy.IdentityColumn)) + .Where(p => p.ClrType.UnwrapNullableType() == typeof(byte) + && p.GetValueGenerationStrategy() == SqlServerValueGenerationStrategy.IdentityColumn)) { logger.ByteIdentityColumnWarning(property); } @@ -155,9 +155,8 @@ protected override void ValidateValueGeneration( if (entityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy && entityType.BaseType == null) { - foreach (var storeGeneratedProperty in key.Properties.Where( - p => (p.ValueGenerated & ValueGenerated.OnAdd) != 0 - && p.GetValueGenerationStrategy() == SqlServerValueGenerationStrategy.IdentityColumn)) + foreach (var storeGeneratedProperty in key.Properties.Where(p => (p.ValueGenerated & ValueGenerated.OnAdd) != 0 + && p.GetValueGenerationStrategy() == SqlServerValueGenerationStrategy.IdentityColumn)) { logger.TpcStoreGeneratedIdentityWarning(storeGeneratedProperty); } @@ -335,7 +334,7 @@ private static void ValidateTemporalPeriodProperty(IEntityType temporalEntityTyp temporalEntityType.DisplayName(), periodProperty.Name, expectedPeriodColumnName)); } - if (periodProperty.TryGetDefaultValue(out var _)) + if (periodProperty.TryGetDefaultValue(out _)) { throw new InvalidOperationException( SqlServerStrings.TemporalPeriodPropertyCantHaveDefaultValue( diff --git a/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerOptionsExtension.cs b/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerOptionsExtension.cs index 2b2b5679d33..4f1d0d358c3 100644 --- a/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerOptionsExtension.cs +++ b/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerOptionsExtension.cs @@ -369,17 +369,17 @@ public override void PopulateDebugInfo(IDictionary debugInfo) debugInfo["EngineType"] = Extension.EngineType.ToString(); debugInfo["UseRetryingStrategyByDefault"] = Extension.UseRetryingStrategyByDefault.ToString(); - if (Extension.SqlServerCompatibilityLevel is int sqlServerCompatibilityLevel) + if (Extension.SqlServerCompatibilityLevel is var sqlServerCompatibilityLevel) { debugInfo["SqlServerCompatibilityLevel"] = sqlServerCompatibilityLevel.ToString(); } - if (Extension.AzureSqlCompatibilityLevel is int azureSqlCompatibilityLevel) + if (Extension.AzureSqlCompatibilityLevel is var azureSqlCompatibilityLevel) { debugInfo["AzureSqlCompatibilityLevel"] = azureSqlCompatibilityLevel.ToString(); } - if (Extension.AzureSynapseCompatibilityLevel is int azureSynapseCompatibilityLevel) + if (Extension.AzureSynapseCompatibilityLevel is var azureSynapseCompatibilityLevel) { debugInfo["AzureSynapseCompatibilityLevel"] = azureSynapseCompatibilityLevel.ToString(); } diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs index c259704a30a..7cc34385776 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs @@ -108,10 +108,9 @@ private static IServiceScope CreateServiceScope() { var serviceProvider = new ServiceCollection() .AddEntityFrameworkSqlServer() - .AddDbContext( - (p, o) => - o.UseSqlServer("Server=.") - .UseInternalServiceProvider(p)) + .AddDbContext((p, o) => + o.UseSqlServer("Server=.") + .UseInternalServiceProvider(p)) .BuildServiceProvider(); return serviceProvider.GetRequiredService().CreateScope(); diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs index d4d7f076c31..3737ef8d63a 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs @@ -62,9 +62,8 @@ protected override DeleteBehavior GetTargetDeleteBehavior(IConventionForeignKey private DeleteBehavior? ProcessSkipNavigations(IEnumerable skipNavigations) { var skipNavigation = skipNavigations - .FirstOrDefault( - s => s.Inverse != null - && IsMappedToSameTable(s.DeclaringEntityType, s.TargetEntityType)); + .FirstOrDefault(s => s.Inverse != null + && IsMappedToSameTable(s.DeclaringEntityType, s.TargetEntityType)); if (skipNavigation != null && skipNavigation.ForeignKey != null) diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOutputClauseConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOutputClauseConvention.cs index e980031e343..abfd6c39f55 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOutputClauseConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerOutputClauseConvention.cs @@ -57,8 +57,8 @@ public virtual void ProcessTriggerRemoved( var entityType = entityTypeBuilder.Metadata; var triggerTableIdentifier = StoreObjectIdentifier.Table(trigger.GetTableName(), trigger.GetTableSchema()); - if (!entityType.GetDeclaredTriggers().Any( - t => t.GetTableName() == trigger.GetTableName() && t.GetTableSchema() == trigger.GetTableSchema())) + if (!entityType.GetDeclaredTriggers() + .Any(t => t.GetTableName() == trigger.GetTableName() && t.GetTableSchema() == trigger.GetTableSchema())) { entityType.UseSqlOutputClause(null, triggerTableIdentifier); } diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs index 32bc4f23ca1..d42f38694c6 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerTemporalConvention.cs @@ -68,7 +68,7 @@ public virtual void ProcessEntityTypeAnnotationChanged( foreach (var skipLevelNavigation in entityTypeBuilder.Metadata.GetSkipNavigations()) { if (skipLevelNavigation.DeclaringEntityType.IsTemporal() - && skipLevelNavigation.Inverse is IConventionSkipNavigation inverse + && skipLevelNavigation.Inverse is { } inverse && inverse.DeclaringEntityType.IsTemporal() && skipLevelNavigation.JoinEntityType is { HasSharedClrType: true } joinEntityType && !joinEntityType.IsTemporal() @@ -90,7 +90,7 @@ public virtual void ProcessEntityTypeAnnotationChanged( if (oldAnnotation?.Value is string oldPeriodPropertyName) { var oldPeriodProperty = entityTypeBuilder.Metadata.GetProperty(oldPeriodPropertyName); - entityTypeBuilder.RemoveUnusedImplicitProperties(new[] { oldPeriodProperty }); + entityTypeBuilder.RemoveUnusedImplicitProperties([oldPeriodProperty]); if (oldPeriodProperty.GetTypeConfigurationSource() == ConfigurationSource.Explicit) { @@ -130,7 +130,7 @@ public virtual void ProcessSkipNavigationForeignKeyChanged( && !joinEntityType.IsTemporal() && joinEntityType.GetConfigurationSource() == ConfigurationSource.Convention && skipNavigationBuilder.Metadata.DeclaringEntityType.IsTemporal() - && skipNavigationBuilder.Metadata.Inverse is IConventionSkipNavigation inverse + && skipNavigationBuilder.Metadata.Inverse is { } inverse && inverse.DeclaringEntityType.IsTemporal()) { joinEntityType.SetIsTemporal(true); diff --git a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs index 05e17e4a1b0..0d57955a65e 100644 --- a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs +++ b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationProvider.cs @@ -154,12 +154,12 @@ public override IEnumerable For(IUniqueConstraint constraint, bool var table = constraint.Table; - if (key.IsClustered(StoreObjectIdentifier.Table(table.Name, table.Schema)) is bool isClustered) + if (key.IsClustered(StoreObjectIdentifier.Table(table.Name, table.Schema)) is { } isClustered) { yield return new Annotation(SqlServerAnnotationNames.Clustered, isClustered); } - if (key.GetFillFactor() is int fillFactor) + if (key.GetFillFactor() is { } fillFactor) { yield return new Annotation(SqlServerAnnotationNames.FillFactor, fillFactor); } @@ -181,17 +181,16 @@ public override IEnumerable For(ITableIndex index, bool designTime) // Model validation ensures that these facets are the same on all mapped indexes var modelIndex = index.MappedIndexes.First(); var table = StoreObjectIdentifier.Table(index.Table.Name, index.Table.Schema); - if (modelIndex.IsClustered(table) is bool isClustered) + if (modelIndex.IsClustered(table) is { } isClustered) { yield return new Annotation(SqlServerAnnotationNames.Clustered, isClustered); } - if (modelIndex.GetIncludeProperties(table) is IReadOnlyList includeProperties) + if (modelIndex.GetIncludeProperties(table) is { } includeProperties) { var includeColumns = includeProperties - .Select( - p => modelIndex.DeclaringEntityType.FindProperty(p)! - .GetColumnName(StoreObjectIdentifier.Table(table.Name, table.Schema))) + .Select(p => modelIndex.DeclaringEntityType.FindProperty(p)! + .GetColumnName(StoreObjectIdentifier.Table(table.Name, table.Schema))) .ToArray(); yield return new Annotation( @@ -199,22 +198,22 @@ public override IEnumerable For(ITableIndex index, bool designTime) includeColumns); } - if (modelIndex.IsCreatedOnline(table) is bool isOnline) + if (modelIndex.IsCreatedOnline(table) is { } isOnline) { yield return new Annotation(SqlServerAnnotationNames.CreatedOnline, isOnline); } - if (modelIndex.GetFillFactor(table) is int fillFactor) + if (modelIndex.GetFillFactor(table) is { } fillFactor) { yield return new Annotation(SqlServerAnnotationNames.FillFactor, fillFactor); } - if (modelIndex.GetSortInTempDb(table) is bool sortInTempDb) + if (modelIndex.GetSortInTempDb(table) is { } sortInTempDb) { yield return new Annotation(SqlServerAnnotationNames.SortInTempDb, sortInTempDb); } - if (modelIndex.GetDataCompression(table) is DataCompressionType dataCompressionType) + if (modelIndex.GetDataCompression(table) is { } dataCompressionType) { yield return new Annotation(SqlServerAnnotationNames.DataCompression, dataCompressionType); } @@ -236,9 +235,8 @@ public override IEnumerable For(IColumn column, bool designTime) var table = StoreObjectIdentifier.Table(column.Table.Name, column.Table.Schema); var identityProperty = column.PropertyMappings .Select(m => m.Property) - .FirstOrDefault( - p => p.GetValueGenerationStrategy(table) - == SqlServerValueGenerationStrategy.IdentityColumn); + .FirstOrDefault(p => p.GetValueGenerationStrategy(table) + == SqlServerValueGenerationStrategy.IdentityColumn); if (identityProperty != null) { var seed = identityProperty.GetIdentitySeed(table); @@ -252,7 +250,7 @@ public override IEnumerable For(IColumn column, bool designTime) // JSON columns have no property mappings so all annotations that rely on property mappings should be skipped for them if (column is not JsonColumn) { - if (column.PropertyMappings.FirstOrDefault()?.Property.IsSparse() is bool isSparse) + if (column.PropertyMappings.FirstOrDefault()?.Property.IsSparse() is { } isSparse) { // Model validation ensures that these facets are the same on all mapped properties yield return new Annotation(SqlServerAnnotationNames.Sparse, isSparse); @@ -261,15 +259,15 @@ public override IEnumerable For(IColumn column, bool designTime) var mappedProperty = column.PropertyMappings.FirstOrDefault()?.Property; if (mappedProperty != null) { - if (mappedProperty.GetDefaultConstraintName(table) is string defaultConstraintName) + if (mappedProperty.GetDefaultConstraintName(table) is { } defaultConstraintName) { // named constraint stored as annotation are either explicitly configured by user // or generated by EF because of naming duplicates (SqlServerDefaultValueConvention) yield return new Annotation(RelationalAnnotationNames.DefaultConstraintName, defaultConstraintName); } - else if (mappedProperty.DeclaringType.Model.AreNamedDefaultConstraintsUsed() == true - && (mappedProperty.FindAnnotation(RelationalAnnotationNames.DefaultValue) != null - || mappedProperty.FindAnnotation(RelationalAnnotationNames.DefaultValueSql) != null)) + else if (mappedProperty.DeclaringType.Model.AreNamedDefaultConstraintsUsed() + && (mappedProperty.FindAnnotation(RelationalAnnotationNames.DefaultValue) != null + || mappedProperty.FindAnnotation(RelationalAnnotationNames.DefaultValueSql) != null)) { // named default constraints opt-in + default value (sql) was specified // generate the default constraint name (based on table and column name) diff --git a/src/EFCore.SqlServer/Metadata/Internal/SqlServerIndexExtensions.cs b/src/EFCore.SqlServer/Metadata/Internal/SqlServerIndexExtensions.cs index 416f1064329..06d055c1323 100644 --- a/src/EFCore.SqlServer/Metadata/Internal/SqlServerIndexExtensions.cs +++ b/src/EFCore.SqlServer/Metadata/Internal/SqlServerIndexExtensions.cs @@ -137,11 +137,10 @@ public static bool AreCompatibleForSqlServer( return true; static bool SameColumnNames(IReadOnlyIndex index, IReadOnlyIndex duplicateIndex, StoreObjectIdentifier storeObject) - => index.GetIncludeProperties()!.Select( - p => index.DeclaringEntityType.FindProperty(p)!.GetColumnName(storeObject)) + => index.GetIncludeProperties()!.Select(p => index.DeclaringEntityType.FindProperty(p)!.GetColumnName(storeObject)) .SequenceEqual( - duplicateIndex.GetIncludeProperties()!.Select( - p => duplicateIndex.DeclaringEntityType.FindProperty(p)!.GetColumnName(storeObject))); + duplicateIndex.GetIncludeProperties()!.Select(p + => duplicateIndex.DeclaringEntityType.FindProperty(p)!.GetColumnName(storeObject))); } private static string FormatInclude(IReadOnlyIndex index, StoreObjectIdentifier storeObject) @@ -150,8 +149,7 @@ private static string FormatInclude(IReadOnlyIndex index, StoreObjectIdentifier : "{'" + string.Join( "', '", - index.GetIncludeProperties()!.Select( - p => index.DeclaringEntityType.FindProperty(p) - ?.GetColumnName(storeObject))) + index.GetIncludeProperties()!.Select(p => index.DeclaringEntityType.FindProperty(p) + ?.GetColumnName(storeObject))) + "'}"; } diff --git a/src/EFCore.SqlServer/Migrations/Internal/SqlServerHistoryRepository.cs b/src/EFCore.SqlServer/Migrations/Internal/SqlServerHistoryRepository.cs index 202c7a2c131..e8128cd0ef5 100644 --- a/src/EFCore.SqlServer/Migrations/Internal/SqlServerHistoryRepository.cs +++ b/src/EFCore.SqlServer/Migrations/Internal/SqlServerHistoryRepository.cs @@ -59,7 +59,8 @@ protected override bool InterpretExistsResult(object? value) /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override LockReleaseBehavior LockReleaseBehavior => LockReleaseBehavior.Connection; + public override LockReleaseBehavior LockReleaseBehavior + => LockReleaseBehavior.Connection; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.SqlServer/Migrations/Internal/SqlServerMigrationDatabaseLock.cs b/src/EFCore.SqlServer/Migrations/Internal/SqlServerMigrationDatabaseLock.cs index b31ff900625..cafa0b32b71 100644 --- a/src/EFCore.SqlServer/Migrations/Internal/SqlServerMigrationDatabaseLock.cs +++ b/src/EFCore.SqlServer/Migrations/Internal/SqlServerMigrationDatabaseLock.cs @@ -28,7 +28,8 @@ public class SqlServerMigrationDatabaseLock( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual IHistoryRepository HistoryRepository => historyRepository; + public virtual IHistoryRepository HistoryRepository + => historyRepository; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs index bcd1e47eadc..d57bfa6b187 100644 --- a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs +++ b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs @@ -381,7 +381,7 @@ protected override void Generate( } else { - Check.DebugAssert(operation.DefaultValue is not null, "operation.DefaultValue is not null"); + Check.DebugAssert(operation.DefaultValue is not null); var typeMapping = (columnType != null ? Dependencies.TypeMappingSource.FindMapping(operation.DefaultValue.GetType(), columnType) @@ -444,9 +444,8 @@ protected override void Generate( OldColumn = operation.OldColumn }; definitionOperation.AddAnnotations( - operation.GetAnnotations().Where( - a => a.Name != SqlServerAnnotationNames.ValueGenerationStrategy - && a.Name != SqlServerAnnotationNames.Identity)); + operation.GetAnnotations().Where(a => a.Name != SqlServerAnnotationNames.ValueGenerationStrategy + && a.Name != SqlServerAnnotationNames.Identity)); ColumnDefinition( operation.Schema, @@ -1446,8 +1445,10 @@ protected override void Generate(SqlOperation operation, IModel? model, Migratio { goto LineEnd; } + commentStart = true; } + break; default: commentStart = false; diff --git a/src/EFCore.SqlServer/Query/Internal/SqlExpressions/SqlServerOpenJsonExpression.cs b/src/EFCore.SqlServer/Query/Internal/SqlExpressions/SqlServerOpenJsonExpression.cs index cc213ae489c..fd7e282797c 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlExpressions/SqlServerOpenJsonExpression.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlExpressions/SqlServerOpenJsonExpression.cs @@ -61,7 +61,7 @@ public SqlServerOpenJsonExpression( SqlExpression jsonExpression, IReadOnlyList? path = null, IReadOnlyList? columnInfos = null) - : base(alias, "OPENJSON", schema: null, builtIn: true, new[] { jsonExpression }) + : base(alias, "OPENJSON", schema: null, builtIn: true, [jsonExpression]) { if (columnInfos?.Count == 0) { @@ -202,21 +202,20 @@ Path is null ColumnInfos is null ? Constant(null, typeof(IReadOnlyList)) : NewArrayInit( - typeof(ColumnInfo), ColumnInfos.Select( - ci => New( - _columnInfoQuotingConstructor ??= typeof(ColumnInfo).GetConstructor( - [ - typeof(string), - typeof(RelationalTypeMapping), - typeof(IReadOnlyList), - typeof(bool) - ])!, - Constant(ci.Name), - RelationalExpressionQuotingUtilities.QuoteTypeMapping(ci.TypeMapping), - ci.Path is null - ? Constant(null, typeof(IReadOnlyList)) - : NewArrayInit(typeof(PathSegment), ci.Path.Select(s => s.Quote())), - Constant(ci.AsJson))))); + typeof(ColumnInfo), ColumnInfos.Select(ci => New( + _columnInfoQuotingConstructor ??= typeof(ColumnInfo).GetConstructor( + [ + typeof(string), + typeof(RelationalTypeMapping), + typeof(IReadOnlyList), + typeof(bool) + ])!, + Constant(ci.Name), + RelationalExpressionQuotingUtilities.QuoteTypeMapping(ci.TypeMapping), + ci.Path is null + ? Constant(null, typeof(IReadOnlyList)) + : NewArrayInit(typeof(PathSegment), ci.Path.Select(s => s.Quote())), + Constant(ci.AsJson))))); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerAggregateOverSubqueryPostprocessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerAggregateOverSubqueryPostprocessor.cs index 5c361339604..2731af894b3 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerAggregateOverSubqueryPostprocessor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerAggregateOverSubqueryPostprocessor.cs @@ -84,7 +84,7 @@ when function.Name.ToLower(CultureInfo.InvariantCulture) is "sum" or "avg" or "m var parentAggregateArgumentContainsSubquery = _aggregateArgumentContainsSubquery; _inAggregateInvocation = true; _isCorrelatedSubquery = false; - _tableAliasesInScope = new HashSet(); + _tableAliasesInScope = []; _aggregateArgumentContainsSubquery = false; var result = base.VisitExtension(function); @@ -139,20 +139,20 @@ when function.Name.ToLower(CultureInfo.InvariantCulture) is "sum" or "avg" or "m #pragma warning disable EF1001 // SelectExpression constructor is internal liftedSubquery = new SelectExpression( subqueryAlias, - tables: Array.Empty(), + tables: [], predicate: null, - groupBy: Array.Empty(), + groupBy: [], having: null, - projections: new[] { new ProjectionExpression(argument, "value") }, + projections: [new ProjectionExpression(argument, "value")], distinct: false, - orderings: Array.Empty(), + orderings: [], offset: null, limit: null, sqlAliasManager: sqlAliasManager); #pragma warning restore EF1001 } - _joinsToAdd ??= new List(); + _joinsToAdd ??= []; _joinsToAdd.Add( _isCorrelatedSubquery ? new OuterApplyExpression(liftedSubquery) : new CrossJoinExpression(liftedSubquery)); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerJsonPostprocessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerJsonPostprocessor.cs index 3c155b62131..bfcf349b5ee 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerJsonPostprocessor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerJsonPostprocessor.cs @@ -31,7 +31,7 @@ public sealed class SqlServerJsonPostprocessor( SqlAliasManager? sqlAliasManager) : ExpressionVisitor { - private readonly List _openjsonOuterAppliesToAdd = new(); + private readonly List _openjsonOuterAppliesToAdd = []; private readonly Dictionary<(string, string), ColumnInfo> _columnsToRewrite = new(); private RelationalTypeMapping? _nvarcharMaxTypeMapping; @@ -261,13 +261,14 @@ when _columnsToRewrite.TryGetValue((columnExpression.TableAlias, columnExpressio // IS NULL operator"). So we find comparisons that involve the json type, and apply a conversion to string (nvarchar(max)) // to both sides. We exempt this when one of the sides is a constant null (not required). case SqlBinaryExpression - { - OperatorType: ExpressionType.Equal or ExpressionType.NotEqual, - Left: var left, - Right: var right - } comparison + { + OperatorType: ExpressionType.Equal or ExpressionType.NotEqual, + Left: var left, + Right: var right + } comparison when (left.TypeMapping?.StoreType is "json" || right.TypeMapping?.StoreType is "json") - && left is not SqlConstantExpression { Value: null } && right is not SqlConstantExpression { Value: null }: + && left is not SqlConstantExpression { Value: null } + && right is not SqlConstantExpression { Value: null }: { return comparison.Update( sqlExpressionFactory.Convert( @@ -289,7 +290,7 @@ static bool IsKeyColumn(SqlExpression sqlExpression, string openJsonTableAlias) || (sqlExpression is SqlUnaryExpression { OperatorType: ExpressionType.Convert, - Operand: SqlExpression operand + Operand: var operand } && IsKeyColumn(operand, openJsonTableAlias)); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerNavigationExpansionExtensibilityHelper.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerNavigationExpansionExtensibilityHelper.cs index 58d46e1e71b..d8399f76891 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerNavigationExpansionExtensibilityHelper.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerNavigationExpansionExtensibilityHelper.cs @@ -73,8 +73,8 @@ public override void ValidateQueryRootCreation(IEntityType entityType, EntityQue private bool OwnedEntityMappedToSameTableAsOwner(IEntityType entityType) => entityType.IsOwned() - && entityType.FindOwnership()!.PrincipalEntityType.GetTableMappings().FirstOrDefault()?.Table is ITable ownerTable - && entityType.GetTableMappings().FirstOrDefault()?.Table is ITable entityTable + && entityType.FindOwnership()!.PrincipalEntityType.GetTableMappings().FirstOrDefault()?.Table is { } ownerTable + && entityType.GetTableMappings().FirstOrDefault()?.Table is { } entityTable && ownerTable == entityTable; /// diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs index 15dae0ff738..34c88df3c14 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs @@ -229,20 +229,21 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction // with the two above, this implies that all of the expressions // are using the default type mapping of the type) if (defaultTypeMapping == typeMapping - && sqlFunctionExpression.Arguments.All(a => a.Type == type && a.TypeMapping == typeMapping)) { - + && sqlFunctionExpression.Arguments.All(a => a.Type == type && a.TypeMapping == typeMapping)) + { var head = sqlFunctionExpression.Arguments[0]; sqlFunctionExpression = (SqlFunctionExpression)sqlFunctionExpression .Arguments .Skip(1) - .Aggregate(head, (l, r) => new SqlFunctionExpression( - "ISNULL", - arguments: [l, r], - nullable: true, - argumentsPropagateNullability: [false, false], - sqlFunctionExpression.Type, - sqlFunctionExpression.TypeMapping - )); + .Aggregate( + head, (l, r) => new SqlFunctionExpression( + "ISNULL", + arguments: [l, r], + nullable: true, + argumentsPropagateNullability: [false, false], + sqlFunctionExpression.Type, + sqlFunctionExpression.TypeMapping + )); } } @@ -536,7 +537,8 @@ protected override Expression VisitJsonScalar(JsonScalarExpression jsonScalarExp // 3. Can do JSON-specific decoding (e.g. base64 for varbinary) // Note that RETURNING is only (currently) supported over the json type (not nvarchar(max)). // Note that we don't need to check the compatibility level - if the json type is being used, then RETURNING is supported. - var useJsonValueReturningClause = !jsonQuery && jsonScalarExpression.Json.TypeMapping?.StoreType is "json" + var useJsonValueReturningClause = !jsonQuery + && jsonScalarExpression.Json.TypeMapping?.StoreType is "json" // Temporarily disabling for Azure SQL, which doesn't yet support RETURNING; this should get removed for 10 (see #36460). && _sqlServerSingletonOptions.EngineType is not SqlServerEngineType.AzureSql; @@ -591,11 +593,11 @@ private void GenerateJsonPath(IReadOnlyList path) { switch (pathSegment) { - case { PropertyName: string propertyName }: + case { PropertyName: { } propertyName }: Sql.Append(".").Append(Dependencies.SqlGenerationHelper.DelimitJsonPathElement(propertyName)); break; - case { ArrayIndex: SqlExpression arrayIndex }: + case { ArrayIndex: { } arrayIndex }: Sql.Append("["); // JSON functions such as JSON_VALUE only support arbitrary expressions for the path parameter in SQL Server 2017 and diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs index a044008ceaa..9930786970e 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs @@ -159,15 +159,15 @@ protected override Expression VisitExtension(Expression extensionExpression) ? new SqlServerOpenJsonExpression(tableAlias, sqlExpression) : new SqlServerOpenJsonExpression( tableAlias, sqlExpression, - columnInfos: new[] - { + columnInfos: + [ new SqlServerOpenJsonExpression.ColumnInfo { Name = "value", TypeMapping = elementTypeMapping, Path = [] } - }); + ]); var elementClrType = sqlExpression.Type.GetSequenceType(); @@ -253,14 +253,14 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr // We're only interested in properties which actually exist in the JSON, filter out uninteresting shadow keys foreach (var property in jsonQueryExpression.StructuralType.GetPropertiesInHierarchy()) { - if (property.GetJsonPropertyName() is string jsonPropertyName) + if (property.GetJsonPropertyName() is { } jsonPropertyName) { columnInfos.Add( new SqlServerOpenJsonExpression.ColumnInfo { Name = jsonPropertyName, TypeMapping = property.GetRelationalTypeMapping(), - Path = [new(jsonPropertyName)], + Path = [new PathSegment(jsonPropertyName)], AsJson = property.GetRelationalTypeMapping().ElementTypeMapping is not null }); } @@ -271,16 +271,16 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr case IEntityType entityType: // Navigations represent nested JSON owned entities, which we also add to the OPENJSON WITH clause, but with AS JSON. foreach (var navigation in entityType.GetNavigationsInHierarchy() - .Where( - n => n.ForeignKey.IsOwnership - && n.TargetEntityType.IsMappedToJson() - && n.ForeignKey.PrincipalToDependent == n)) + .Where(n => n.ForeignKey.IsOwnership + && n.TargetEntityType.IsMappedToJson() + && n.ForeignKey.PrincipalToDependent == n)) { var jsonPropertyName = navigation.TargetEntityType.GetJsonPropertyName(); Check.DebugAssert(jsonPropertyName is not null, $"No JSON property name for navigation {navigation.Name}"); AddStructuralColumnInfo(jsonPropertyName); } + break; case IComplexType complexType: @@ -291,6 +291,7 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr AddStructuralColumnInfo(jsonPropertyName); } + break; default: @@ -302,7 +303,7 @@ void AddStructuralColumnInfo(string jsonPropertyName) { Name = jsonPropertyName, TypeMapping = _nvarcharMaxTypeMapping ??= _typeMappingSource.FindMapping("nvarchar(max)")!, - Path = [new(jsonPropertyName)], + Path = [new PathSegment(jsonPropertyName)], AsJson = true }); } @@ -362,48 +363,48 @@ void AddStructuralColumnInfo(string jsonPropertyName) // index on parameter using a column // translate via JSON because it is a better translation case SelectExpression - { - Tables: [ValuesExpression { ValuesParameter: { } valuesParameter }], - Predicate: null, - GroupBy: [], - Having: null, - IsDistinct: false, + { + Tables: [ValuesExpression { ValuesParameter: { } valuesParameter }], + Predicate: null, + GroupBy: [], + Having: null, + IsDistinct: false, #pragma warning disable EF1001 - Orderings: [{ Expression: ColumnExpression { Name: ValuesOrderingColumnName }, IsAscending: true }], + Orderings: [{ Expression: ColumnExpression { Name: ValuesOrderingColumnName }, IsAscending: true }], #pragma warning restore EF1001 - Limit: null, - Offset: null - } selectExpression - when TranslateExpression(index) is { } translatedIndex + Limit: null, + Offset: null + } selectExpression + when TranslateExpression(index) is { } translatedIndex && _sqlServerSingletonOptions.SupportsJsonFunctions && TryTranslate(selectExpression, valuesParameter, translatedIndex, out var result): return result; // Index on JSON array case SelectExpression - { - Tables: [SqlServerOpenJsonExpression { Arguments: [var jsonArrayColumn] } openJsonExpression], - Predicate: null, - GroupBy: [], - Having: null, - IsDistinct: false, - Limit: null, - Offset: null, - // We can only apply the indexing if the JSON array is ordered by its natural ordered, i.e. by the "key" column that - // we created in TranslateCollection. For example, if another ordering has been applied (e.g. by the JSON elements - // themselves), we can no longer simply index into the original array. - Orderings: - [ - { - Expression: SqlUnaryExpression + { + Tables: [SqlServerOpenJsonExpression { Arguments: [var jsonArrayColumn] } openJsonExpression], + Predicate: null, + GroupBy: [], + Having: null, + IsDistinct: false, + Limit: null, + Offset: null, + // We can only apply the indexing if the JSON array is ordered by its natural ordered, i.e. by the "key" column that + // we created in TranslateCollection. For example, if another ordering has been applied (e.g. by the JSON elements + // themselves), we can no longer simply index into the original array. + Orderings: + [ { - OperatorType: ExpressionType.Convert, - Operand: ColumnExpression { Name: "key", TableAlias: var orderingTableAlias } + Expression: SqlUnaryExpression + { + OperatorType: ExpressionType.Convert, + Operand: ColumnExpression { Name: "key", TableAlias: var orderingTableAlias } + } } - } - ] - } selectExpression - when orderingTableAlias == openJsonExpression.Alias + ] + } selectExpression + when orderingTableAlias == openJsonExpression.Alias && TranslateExpression(index) is { } translatedIndex && TryTranslate(selectExpression, jsonArrayColumn, translatedIndex, out var result): return result; @@ -419,51 +420,45 @@ bool TryTranslate( [NotNullWhen(true)] out ShapedQueryExpression? result) { // Extract the column projected out of the source, and simplify the subquery to a simple JsonScalarExpression - var shaperExpression = source.ShaperExpression; - if (shaperExpression is UnaryExpression { NodeType: ExpressionType.Convert } unaryExpression - && unaryExpression.Operand.Type.IsNullableType() - && unaryExpression.Operand.Type.UnwrapNullableType() == unaryExpression.Type) + if (!TryGetProjection(source, selectExpression, out var projection)) { - shaperExpression = unaryExpression.Operand; + result = null; + return false; } - if (shaperExpression is ProjectionBindingExpression projectionBindingExpression - && selectExpression.GetProjection(projectionBindingExpression) is SqlExpression projection) + // OPENJSON's value column is an nvarchar(max); if this is a collection column whose type mapping is know, the projection + // contains a CAST node which we unwrap + var projectionColumn = projection switch { - // OPENJSON's value column is an nvarchar(max); if this is a collection column whose type mapping is know, the projection - // contains a CAST node which we unwrap - var projectionColumn = projection switch - { - ColumnExpression c => c, - SqlUnaryExpression { OperatorType: ExpressionType.Convert, Operand: ColumnExpression c } => c, - _ => null - }; + ColumnExpression c => c, + SqlUnaryExpression { OperatorType: ExpressionType.Convert, Operand: ColumnExpression c } => c, + _ => null + }; - if (projectionColumn is not null) - { - // If the inner expression happens to itself be a JsonScalarExpression, simply append the two paths to avoid creating - // JSON_VALUE within JSON_VALUE. - var (json, path) = jsonArrayColumn is JsonScalarExpression innerJsonScalarExpression - ? (innerJsonScalarExpression.Json, - innerJsonScalarExpression.Path.Append(new PathSegment(translatedIndex)).ToArray()) - : (jsonArrayColumn, new PathSegment[] { new(translatedIndex) }); - - var translation = new JsonScalarExpression( - json, - path, - projection.Type, - projection.TypeMapping, - projectionColumn.IsNullable); + if (projectionColumn is null) + { + result = null; + return false; + } + + // If the inner expression happens to itself be a JsonScalarExpression, simply append the two paths to avoid creating + // JSON_VALUE within JSON_VALUE. + var (json, path) = jsonArrayColumn is JsonScalarExpression innerJsonScalarExpression + ? (innerJsonScalarExpression.Json, + innerJsonScalarExpression.Path.Append(new PathSegment(translatedIndex)).ToArray()) + : (jsonArrayColumn, new PathSegment[] { new(translatedIndex) }); + + var translation = new JsonScalarExpression( + json, + path, + projection.Type, + projection.TypeMapping, + projectionColumn.IsNullable); #pragma warning disable EF1001 - result = source.UpdateQueryExpression(new SelectExpression(translation, _queryCompilationContext.SqlAliasManager)); + result = source.UpdateQueryExpression(new SelectExpression(translation, _queryCompilationContext.SqlAliasManager)); #pragma warning restore EF1001 - return true; - } - } - - result = default; - return false; + return true; } } @@ -499,9 +494,9 @@ protected override bool IsNaturallyOrdered(SelectExpression selectExpression) /// protected override bool IsValidSelectExpressionForExecuteDelete(SelectExpression selectExpression) => selectExpression.Offset == null - && selectExpression.GroupBy.Count == 0 - && selectExpression.Having == null - && selectExpression.Orderings.Count == 0; + && selectExpression.GroupBy.Count == 0 + && selectExpression.Having == null + && selectExpression.Orderings.Count == 0; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -539,7 +534,10 @@ protected override bool IsValidSelectExpressionForExecuteUpdate( return false; } - private bool TryGetProjection(ShapedQueryExpression shapedQueryExpression, [NotNullWhen(true)] out SqlExpression? projection) + private bool TryGetProjection( + ShapedQueryExpression shapedQueryExpression, + SelectExpression selectExpression, + [NotNullWhen(true)] out SqlExpression? projection) { var shaperExpression = shapedQueryExpression.ShaperExpression; // No need to check ConvertChecked since this is convert node which we may have added during projection @@ -550,8 +548,7 @@ private bool TryGetProjection(ShapedQueryExpression shapedQueryExpression, [NotN shaperExpression = unaryExpression.Operand; } - if (shapedQueryExpression.QueryExpression is SelectExpression selectExpression - && shaperExpression is ProjectionBindingExpression projectionBindingExpression + if (shaperExpression is ProjectionBindingExpression projectionBindingExpression && selectExpression.GetProjection(projectionBindingExpression) is SqlExpression sqlExpression) { projection = sqlExpression; diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs index ce7cbbd75fc..57ec6e8d1a7 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs @@ -42,9 +42,7 @@ public SqlServerSqlNullabilityProcessor( RelationalParameterBasedSqlProcessorParameters parameters, ISqlServerSingletonOptions sqlServerSingletonOptions) : base(dependencies, parameters) - { - _sqlServerSingletonOptions = sqlServerSingletonOptions; - } + => _sqlServerSingletonOptions = sqlServerSingletonOptions; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -188,7 +186,7 @@ protected override Expression VisitExtension(Expression node) { switch (node) { - case ValuesExpression { ValuesParameter: SqlParameterExpression valuesParameter } valuesExpression + case ValuesExpression { ValuesParameter: { } valuesParameter } valuesExpression when (valuesParameter.TranslationMode ?? CollectionParameterTranslationMode) is ParameterTranslationMode.MultipleParameters: { Check.DebugAssert(valuesParameter.TypeMapping is not null); @@ -196,12 +194,12 @@ protected override Expression VisitExtension(Expression node) var elementTypeMapping = (RelationalTypeMapping)valuesParameter.TypeMapping.ElementTypeMapping; if (TryHandleOverLimitParameters( - valuesParameter, - elementTypeMapping, - valuesExpression, - out var openJson, - out var constants, - out _)) + valuesParameter, + elementTypeMapping, + valuesExpression, + out var openJson, + out var constants, + out _)) { switch (openJson, constants) { @@ -216,6 +214,7 @@ protected override Expression VisitExtension(Expression node) throw new UnreachableException(); } } + return base.VisitExtension(node); } @@ -234,7 +233,7 @@ protected override SqlExpression VisitIn(InExpression inExpression, bool allowOp { switch (inExpression.ValuesParameter) { - case SqlParameterExpression valuesParameter + case { } valuesParameter when (valuesParameter.TranslationMode ?? CollectionParameterTranslationMode) is ParameterTranslationMode.MultipleParameters: { Check.DebugAssert(valuesParameter.TypeMapping is not null); @@ -242,12 +241,12 @@ protected override SqlExpression VisitIn(InExpression inExpression, bool allowOp var elementTypeMapping = (RelationalTypeMapping)valuesParameter.TypeMapping.ElementTypeMapping; if (TryHandleOverLimitParameters( - valuesParameter, - elementTypeMapping, - valuesExpression: null, - out var openJson, - out var constants, - out var containsNulls)) + valuesParameter, + elementTypeMapping, + valuesExpression: null, + out var openJson, + out var constants, + out var containsNulls)) { inExpression = (openJson, constants) switch { @@ -274,6 +273,7 @@ protected override SqlExpression VisitIn(InExpression inExpression, bool allowOp _ => throw new UnreachableException(), }; } + return base.VisitIn(inExpression, allowOptimizedExpansion, out nullable); } @@ -284,16 +284,16 @@ protected override SqlExpression VisitIn(InExpression inExpression, bool allowOp /// protected override int CalculateParameterBucketSize(int count, RelationalTypeMapping elementTypeMapping) - => count switch - { - <= 5 => 1, - <= 150 => 10, - <= 750 => 50, - <= 2000 => 100, - <= 2070 => 10, // try not to over-pad as we approach that limit - <= MaxParameterCount => 0, // just don't pad between 2070 and 2100, to minimize the crazy - _ => 200, - }; + => count switch + { + <= 5 => 1, + <= 150 => 10, + <= 750 => 50, + <= 2000 => 100, + <= 2070 => 10, // try not to over-pad as we approach that limit + <= MaxParameterCount => 0, // just don't pad between 2070 and 2100, to minimize the crazy + _ => 200, + }; private bool TryHandleOverLimitParameters( SqlParameterExpression valuesParameter, @@ -334,30 +334,33 @@ private bool TryHandleOverLimitParameters( containsNulls = values.Any(static x => x is null); return true; } - else - { - var intTypeMapping = (IntTypeMapping)Dependencies.TypeMappingSource.FindMapping(typeof(int))!; - var counter = 1; - constantsResult = new List(); - foreach (var value in values) - { - constantsResult.Add( - valuesExpression is not null - ? new RowValueExpression( - ProcessValuesOrderingColumn( - valuesExpression, - [Dependencies.SqlExpressionFactory.Constant(value, value?.GetType() ?? typeof(object), sensitive: true, typeMapping)], - intTypeMapping, - ref counter)) - : Dependencies.SqlExpressionFactory.Constant(value, value?.GetType() ?? typeof(object), sensitive: true, typeMapping)); - } + var intTypeMapping = (IntTypeMapping)Dependencies.TypeMappingSource.FindMapping(typeof(int))!; + var counter = 1; - openJsonResult = default; - containsNulls = default; - return true; + constantsResult = []; + foreach (var value in values) + { + constantsResult.Add( + valuesExpression is not null + ? new RowValueExpression( + ProcessValuesOrderingColumn( + valuesExpression, + [ + Dependencies.SqlExpressionFactory.Constant( + value, value?.GetType() ?? typeof(object), sensitive: true, typeMapping) + ], + intTypeMapping, + ref counter)) + : Dependencies.SqlExpressionFactory.Constant( + value, value?.GetType() ?? typeof(object), sensitive: true, typeMapping)); } + + openJsonResult = default; + containsNulls = default; + return true; } + openJsonResult = default; constantsResult = default; containsNulls = default; diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs index 8b1abfc068d..42a25a43186 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs @@ -163,7 +163,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) var isBinaryMaxDataType = GetProviderType(sqlExpression) == "varbinary(max)" || sqlExpression is SqlParameterExpression; var dataLengthSqlFunction = Dependencies.SqlExpressionFactory.Function( "DATALENGTH", - new[] { sqlExpression }, + [sqlExpression], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], isBinaryMaxDataType ? typeof(long) : typeof(int)); @@ -420,16 +420,15 @@ StartsEndsWithContains.StartsWith or StartsEndsWithContains.EndsWith _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( methodType is StartsEndsWithContains.StartsWith ? "LEFT" : "RIGHT", - new[] - { - translatedInstance, - _sqlExpressionFactory.Function( - "LEN", - new[] { translatedPattern }, - nullable: true, - argumentsPropagateNullability: Statics.TrueArrays[1], - typeof(int)) - }, + [ + translatedInstance, + _sqlExpressionFactory.Function( + "LEN", + [translatedPattern], + nullable: true, + argumentsPropagateNullability: Statics.TrueArrays[1], + typeof(int)) + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], typeof(string), @@ -462,7 +461,7 @@ SqlExpression CharIndexGreaterThanZero() => _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "CHARINDEX", - new[] { translatedPattern, translatedInstance }, + [translatedPattern, translatedInstance], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], typeof(int)), @@ -668,14 +667,13 @@ private Expression TranslateByteArrayElementAccess(Expression array, Expression ? Dependencies.SqlExpressionFactory.Convert( Dependencies.SqlExpressionFactory.Function( "SUBSTRING", - new[] - { + [ sqlArray, Dependencies.SqlExpressionFactory.Add( Dependencies.SqlExpressionFactory.ApplyDefaultTypeMapping(sqlIndex), Dependencies.SqlExpressionFactory.Constant(1)), Dependencies.SqlExpressionFactory.Constant(1) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], typeof(byte[])), diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTreePruner.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTreePruner.cs index 48af433f3b9..d53dddc442a 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTreePruner.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTreePruner.cs @@ -24,7 +24,7 @@ protected override Expression VisitExtension(Expression node) { switch (node) { - case SqlServerOpenJsonExpression { ColumnInfos: IReadOnlyList columnInfos } openJson: + case SqlServerOpenJsonExpression { ColumnInfos: { } columnInfos } openJson: var visitedJson = (SqlExpression)Visit(openJson.JsonExpression); if (ReferencedColumnMap.TryGetValue(openJson.Alias, out var referencedAliases)) diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerTypeMappingPostprocessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerTypeMappingPostprocessor.cs index 1aa6607bd87..9316ed18b72 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerTypeMappingPostprocessor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerTypeMappingPostprocessor.cs @@ -44,7 +44,7 @@ protected override Expression VisitExtension(Expression expression) { SqlServerOpenJsonExpression openJsonExpression when TryGetInferredTypeMapping(openJsonExpression.Alias, "value", out var typeMapping) - => ApplyTypeMappingsOnOpenJsonExpression(openJsonExpression, new[] { typeMapping }), + => ApplyTypeMappingsOnOpenJsonExpression(openJsonExpression, [typeMapping]), _ => base.VisitExtension(expression) }; @@ -59,7 +59,7 @@ protected virtual SqlServerOpenJsonExpression ApplyTypeMappingsOnOpenJsonExpress SqlServerOpenJsonExpression openJsonExpression, IReadOnlyList typeMappings) { - Check.DebugAssert(typeMappings.Count == 1, "typeMappings.Count == 1"); + Check.DebugAssert(typeMappings.Count == 1); var elementTypeMapping = typeMappings[0]; // Constant queryables are translated to VALUES, no need for JSON. @@ -93,6 +93,6 @@ protected virtual SqlServerOpenJsonExpression ApplyTypeMappingsOnOpenJsonExpress return openJsonExpression.Update( parameterExpression.ApplyTypeMapping(parameterTypeMapping), path: null, - new[] { new SqlServerOpenJsonExpression.ColumnInfo("value", elementTypeMapping, []) }); + [new SqlServerOpenJsonExpression.ColumnInfo("value", elementTypeMapping, [])]); } } diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerConvertTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerConvertTranslator.cs index f0c3643d9f0..185f5d397df 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerConvertTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerConvertTranslator.cs @@ -58,15 +58,13 @@ static SqlServerConvertTranslator() { var convertInfo = typeof(Convert).GetTypeInfo(); SupportedMethods = TypeMapping.Keys - .SelectMany( - name => convertInfo.GetDeclaredMethods(name) - .Where( - method => - { - var parameters = method.GetParameters(); - return parameters.Length == 1 - && SupportedTypes.Contains(parameters[0].ParameterType); - })) + .SelectMany(name => convertInfo.GetDeclaredMethods(name) + .Where(method => + { + var parameters = method.GetParameters(); + return parameters.Length == 1 + && SupportedTypes.Contains(parameters[0].ParameterType); + })) .ToArray(); } diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerDateDiffFunctionsTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerDateDiffFunctionsTranslator.cs index e0bc46dd906..6be965994f8 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerDateDiffFunctionsTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerDateDiffFunctionsTranslator.cs @@ -558,9 +558,9 @@ public SqlServerDateDiffFunctionsTranslator( return _sqlExpressionFactory.Function( "DATEDIFF", - new[] { _sqlExpressionFactory.Fragment(datePart), startDate, endDate }, + [_sqlExpressionFactory.Fragment(datePart), startDate, endDate], nullable: true, - argumentsPropagateNullability: new[] { false, true, true }, + argumentsPropagateNullability: [false, true, true], typeof(int)); } diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerDateTimeMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerDateTimeMemberTranslator.cs index 6a307857c0b..96cccd74180 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerDateTimeMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerDateTimeMemberTranslator.cs @@ -52,7 +52,7 @@ public class SqlServerDateTimeMemberTranslator( nameof(DateTime.Date) => sqlExpressionFactory.Function( "CONVERT", - new[] { sqlExpressionFactory.Fragment("date"), instance! }, + [sqlExpressionFactory.Fragment("date"), instance!], nullable: true, argumentsPropagateNullability: Statics.FalseTrue, returnType, @@ -63,7 +63,7 @@ public class SqlServerDateTimeMemberTranslator( nameof(DateTime.TimeOfDay) => sqlExpressionFactory.Function( "CONVERT", - new[] { sqlExpressionFactory.Fragment("time"), instance! }, + [sqlExpressionFactory.Fragment("time"), instance!], nullable: true, argumentsPropagateNullability: Statics.FalseTrue, returnType), @@ -98,8 +98,7 @@ public class SqlServerDateTimeMemberTranslator( nameof(DateTime.Today) => sqlExpressionFactory.Function( "CONVERT", - new[] - { + [ sqlExpressionFactory.Fragment("date"), sqlExpressionFactory.Function( "GETDATE", @@ -107,7 +106,7 @@ public class SqlServerDateTimeMemberTranslator( nullable: false, argumentsPropagateNullability: [], typeof(DateTime)) - }, + ], nullable: true, argumentsPropagateNullability: Statics.FalseTrue, returnType), diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerIsDateFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerIsDateFunctionTranslator.cs index a16e7f77560..8e7d545daf6 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerIsDateFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerIsDateFunctionTranslator.cs @@ -43,7 +43,7 @@ public SqlServerIsDateFunctionTranslator(ISqlExpressionFactory sqlExpressionFact ? _sqlExpressionFactory.Convert( _sqlExpressionFactory.Function( "ISDATE", - new[] { arguments[1] }, + [arguments[1]], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], MethodInfo.ReturnType), diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerIsNumericFunctionTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerIsNumericFunctionTranslator.cs index 5fa14b21f65..f9a24c9f7e3 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerIsNumericFunctionTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerIsNumericFunctionTranslator.cs @@ -43,7 +43,7 @@ public SqlServerIsNumericFunctionTranslator(ISqlExpressionFactory sqlExpressionF ? _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "ISNUMERIC", - new[] { arguments[1] }, + [arguments[1]], nullable: false, argumentsPropagateNullability: Statics.FalseArrays[1], typeof(int)), diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerLongCountMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerLongCountMethodTranslator.cs index e1081904814..2a3e9152dc8 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerLongCountMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerLongCountMethodTranslator.cs @@ -39,7 +39,7 @@ public SqlServerLongCountMethodTranslator(ISqlExpressionFactory sqlExpressionFac { if (method.DeclaringType == typeof(Queryable) && method.IsGenericMethod - && method.GetGenericMethodDefinition() is MethodInfo genericMethod + && method.GetGenericMethodDefinition() is { } genericMethod && (genericMethod == QueryableMethods.LongCountWithoutPredicate || genericMethod == QueryableMethods.LongCountWithPredicate)) { @@ -64,7 +64,7 @@ public SqlServerLongCountMethodTranslator(ISqlExpressionFactory sqlExpressionFac return _sqlExpressionFactory.ApplyDefaultTypeMapping( _sqlExpressionFactory.Function( "COUNT_BIG", - new[] { sqlExpression }, + [sqlExpression], nullable: false, argumentsPropagateNullability: Statics.FalseArrays[1], typeof(long))); diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerMathTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerMathTranslator.cs index 1c6b775929e..de4242b2a29 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerMathTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerMathTranslator.cs @@ -71,22 +71,22 @@ public class SqlServerMathTranslator : IMethodCallTranslator // Note: Math.Max/Min are handled in RelationalSqlTranslatingExpressionVisitor - private static readonly IEnumerable TruncateMethodInfos = new[] - { + private static readonly IEnumerable TruncateMethodInfos = + [ typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), [typeof(decimal)])!, typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), [typeof(double)])!, typeof(MathF).GetRuntimeMethod(nameof(MathF.Truncate), [typeof(float)])! - }; + ]; - private static readonly IEnumerable RoundMethodInfos = new[] - { + private static readonly IEnumerable RoundMethodInfos = + [ typeof(Math).GetRuntimeMethod(nameof(Math.Round), [typeof(decimal)])!, typeof(Math).GetRuntimeMethod(nameof(Math.Round), [typeof(double)])!, typeof(Math).GetRuntimeMethod(nameof(Math.Round), [typeof(decimal), typeof(int)])!, typeof(Math).GetRuntimeMethod(nameof(Math.Round), [typeof(double), typeof(int)])!, typeof(MathF).GetRuntimeMethod(nameof(MathF.Round), [typeof(float)])!, typeof(MathF).GetRuntimeMethod(nameof(MathF.Round), [typeof(float), typeof(int)])! - }; + ]; private readonly ISqlExpressionFactory _sqlExpressionFactory; @@ -147,7 +147,7 @@ public SqlServerMathTranslator(ISqlExpressionFactory sqlExpressionFactory) var result = _sqlExpressionFactory.Function( "ROUND", - new[] { argument, _sqlExpressionFactory.Constant(0), _sqlExpressionFactory.Constant(1) }, + [argument, _sqlExpressionFactory.Constant(0), _sqlExpressionFactory.Constant(1)], nullable: true, argumentsPropagateNullability: [true, false, false], resultType); @@ -174,7 +174,7 @@ public SqlServerMathTranslator(ISqlExpressionFactory sqlExpressionFactory) var result = _sqlExpressionFactory.Function( "ROUND", - new[] { argument, digits }, + [argument, digits], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], resultType); diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerNewGuidTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerNewGuidTranslator.cs index ecead0e611c..95b412800bc 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerNewGuidTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerNewGuidTranslator.cs @@ -40,9 +40,9 @@ public SqlServerNewGuidTranslator(ISqlExpressionFactory sqlExpressionFactory) => MethodInfo.Equals(method) ? _sqlExpressionFactory.Function( "NEWID", - Enumerable.Empty(), + [], nullable: false, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], method.ReturnType) : null; } diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerObjectToStringTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerObjectToStringTranslator.cs index b733eeb950a..6d3959a0439 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerObjectToStringTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerObjectToStringTranslator.cs @@ -83,25 +83,23 @@ public SqlServerObjectToStringTranslator(ISqlExpressionFactory sqlExpressionFact { return _sqlExpressionFactory.Case( instance, - new[] - { + [ new CaseWhenClause( _sqlExpressionFactory.Constant(false), _sqlExpressionFactory.Constant(false.ToString())), new CaseWhenClause( _sqlExpressionFactory.Constant(true), _sqlExpressionFactory.Constant(true.ToString())) - }, + ], _sqlExpressionFactory.Constant(string.Empty)); } return _sqlExpressionFactory.Case( - new[] - { + [ new CaseWhenClause( instance, _sqlExpressionFactory.Constant(true.ToString())) - }, + ], _sqlExpressionFactory.Constant(false.ToString())); } @@ -111,7 +109,7 @@ public SqlServerObjectToStringTranslator(ISqlExpressionFactory sqlExpressionFact ? _sqlExpressionFactory.Coalesce( _sqlExpressionFactory.Function( "CONVERT", - new[] { _sqlExpressionFactory.Fragment(storeType), instance }, + [_sqlExpressionFactory.Fragment(storeType), instance], nullable: true, argumentsPropagateNullability: Statics.FalseTrue, typeof(string), diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStatisticsAggregateMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStatisticsAggregateMethodTranslator.cs index 7ece77765bb..38a34fa3a9d 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStatisticsAggregateMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStatisticsAggregateMethodTranslator.cs @@ -68,7 +68,7 @@ public SqlServerStatisticsAggregateMethodTranslator( return SqlServerExpression.AggregateFunction( _sqlExpressionFactory, functionName, - new[] { sqlExpression }, + [sqlExpression], source, enumerableArgumentIndex: 0, nullable: true, diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringAggregateMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringAggregateMethodTranslator.cs index de0864f072a..8e7b01eae87 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringAggregateMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringAggregateMethodTranslator.cs @@ -91,13 +91,12 @@ public SqlServerStringAggregateMethodTranslator( SqlServerExpression.AggregateFunctionWithOrdering( _sqlExpressionFactory, "STRING_AGG", - new[] - { + [ sqlExpression, _sqlExpressionFactory.ApplyTypeMapping( method == StringJoinMethod ? arguments[0] : _sqlExpressionFactory.Constant(string.Empty, typeof(string)), sqlExpression.TypeMapping) - }, + ], source, enumerableArgumentIndex: 0, nullable: true, diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringMemberTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringMemberTranslator.cs index e62d2785391..e50d6bfc397 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringMemberTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringMemberTranslator.cs @@ -43,7 +43,7 @@ public SqlServerStringMemberTranslator(ISqlExpressionFactory sqlExpressionFactor return _sqlExpressionFactory.Convert( _sqlExpressionFactory.Function( "LEN", - new[] { instance! }, + [instance!], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(long)), diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringMethodTranslator.cs index db7c88a1e02..9fbd664bcc4 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringMethodTranslator.cs @@ -80,14 +80,12 @@ private static readonly MethodInfo TrimEndMethodInfoWithCharArg = typeof(string).GetRuntimeMethod(nameof(string.TrimEnd), [typeof(char)])!; private static readonly MethodInfo FirstOrDefaultMethodInfoWithoutArgs - = typeof(Enumerable).GetRuntimeMethods().Single( - m => m.Name == nameof(Enumerable.FirstOrDefault) - && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); + = typeof(Enumerable).GetRuntimeMethods().Single(m => m.Name == nameof(Enumerable.FirstOrDefault) + && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); private static readonly MethodInfo LastOrDefaultMethodInfoWithoutArgs - = typeof(Enumerable).GetRuntimeMethods().Single( - m => m.Name == nameof(Enumerable.LastOrDefault) - && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); + = typeof(Enumerable).GetRuntimeMethods().Single(m => m.Name == nameof(Enumerable.LastOrDefault) + && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); private static readonly MethodInfo PatIndexMethodInfo = typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( @@ -142,12 +140,14 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); - firstArgument = _sqlExpressionFactory.ApplyTypeMapping(firstArgument, firstArgument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping); - secondArgument = _sqlExpressionFactory.ApplyTypeMapping(secondArgument, secondArgument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping); + firstArgument = _sqlExpressionFactory.ApplyTypeMapping( + firstArgument, firstArgument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping); + secondArgument = _sqlExpressionFactory.ApplyTypeMapping( + secondArgument, secondArgument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping); return _sqlExpressionFactory.Function( "REPLACE", - new[] { instance, firstArgument, secondArgument }, + [instance, firstArgument, secondArgument], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], method.ReturnType, @@ -159,7 +159,7 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor { return _sqlExpressionFactory.Function( ToLowerMethodInfo.Equals(method) ? "LOWER" : "UPPER", - new[] { instance }, + [instance], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], method.ReturnType, @@ -170,19 +170,18 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor { return _sqlExpressionFactory.Function( "SUBSTRING", - new[] - { + [ instance, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)), _sqlExpressionFactory.Function( "LEN", - new[] { instance }, + [instance], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(int)) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], method.ReturnType, @@ -193,14 +192,13 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor { return _sqlExpressionFactory.Function( "SUBSTRING", - new[] - { + [ instance, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)), arguments[1] - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], method.ReturnType, @@ -238,16 +236,15 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor { return _sqlExpressionFactory.Function( "LTRIM", - new[] - { + [ _sqlExpressionFactory.Function( "RTRIM", - new[] { instance }, + [instance], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], instance.Type, instance.TypeMapping) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], instance.Type, @@ -282,7 +279,7 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor var argument = arguments[0]; return _sqlExpressionFactory.Function( "SUBSTRING", - new[] { argument, _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1) }, + [argument, _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1)], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], method.ReturnType); @@ -293,17 +290,16 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor var argument = arguments[0]; return _sqlExpressionFactory.Function( "SUBSTRING", - new[] - { + [ argument, _sqlExpressionFactory.Function( "LEN", - new[] { argument }, + [argument], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(int)), _sqlExpressionFactory.Constant(1) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], method.ReturnType); @@ -316,7 +312,7 @@ public SqlServerStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactor return _sqlExpressionFactory.Function( "PATINDEX", - new[] { pattern, expression }, + [pattern, expression], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], method.ReturnType @@ -333,7 +329,8 @@ private SqlExpression TranslateIndexOf( SqlExpression? startIndex) { var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, searchExpression)!; - searchExpression = _sqlExpressionFactory.ApplyTypeMapping(searchExpression, searchExpression.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping); + searchExpression = _sqlExpressionFactory.ApplyTypeMapping( + searchExpression, searchExpression.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); @@ -386,14 +383,13 @@ [new CaseWhenClause(_sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFac var offsetExpression = searchExpression is SqlConstantExpression ? _sqlExpressionFactory.Constant(1) : _sqlExpressionFactory.Case( - new[] - { + [ new CaseWhenClause( _sqlExpressionFactory.Equal( searchExpression, _sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)), _sqlExpressionFactory.Constant(0)) - }, + ], _sqlExpressionFactory.Constant(1)); return _sqlExpressionFactory.Subtract(charIndexExpression, offsetExpression); diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerTimeOnlyMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerTimeOnlyMethodTranslator.cs index 013e9d8e77b..4189be6a7d9 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerTimeOnlyMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerTimeOnlyMethodTranslator.cs @@ -84,7 +84,7 @@ public SqlServerTimeOnlyMethodTranslator(ISqlExpressionFactory sqlExpressionFact return _sqlExpressionFactory.Function( "DATEADD", - new[] { _sqlExpressionFactory.Fragment(datePart), _sqlExpressionFactory.Convert(arguments[0], typeof(int)), instance }, + [_sqlExpressionFactory.Fragment(datePart), _sqlExpressionFactory.Convert(arguments[0], typeof(int)), instance], nullable: true, argumentsPropagateNullability: [false, true, true], instance.Type, diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerVectorTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerVectorTranslator.cs index 3e53d8baacf..d3bcab2ebd1 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerVectorTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerVectorTranslator.cs @@ -37,7 +37,8 @@ public class SqlServerVectorTranslator( case nameof(SqlServerDbFunctionsExtensions.VectorDistance) when arguments is [_, var distanceMetric, var vector1, var vector2]: { - var vectorTypeMapping = vector1.TypeMapping ?? vector2.TypeMapping + var vectorTypeMapping = vector1.TypeMapping + ?? vector2.TypeMapping ?? throw new InvalidOperationException( "One of the arguments to EF.Functions.VectorDistance must be a vector column."); @@ -94,4 +95,3 @@ public class SqlServerVectorTranslator( return null; } } - diff --git a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs index 78de96ff183..58400365349 100644 --- a/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs +++ b/src/EFCore.SqlServer/Scaffolding/Internal/SqlServerDatabaseModelFactory.cs @@ -163,10 +163,9 @@ public override DatabaseModel Create(DbConnection connection, DatabaseModelFacto foreach (var table in tableList) { var (parsedSchema, parsedTableName) = Parse(table); - if (!databaseModel.Tables.Any( - t => !string.IsNullOrEmpty(parsedSchema) - && t.Schema == parsedSchema - || t.Name == parsedTableName)) + if (!databaseModel.Tables.Any(t => !string.IsNullOrEmpty(parsedSchema) + && t.Schema == parsedSchema + || t.Name == parsedTableName)) { _logger.MissingTableWarning(table); } @@ -750,7 +749,7 @@ FROM [sys].[tables] t if (SupportsViews()) { - Check.DebugAssert(viewFilter is not null, "viewFilter is not null"); + Check.DebugAssert(viewFilter is not null); builder.AppendLine().Append( $""" @@ -782,9 +781,8 @@ FROM [sys].[views] v using var reader = command.ExecuteReader(); var tableColumnGroups = reader.Cast() - .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("table_schema"), - tableName: ddr.GetFieldValue("table_name"))); + .GroupBy(ddr => (tableSchema: ddr.GetValueOrDefault("table_schema"), + tableName: ddr.GetFieldValue("table_name"))); foreach (var tableColumnGroup in tableColumnGroups) { @@ -1089,9 +1087,8 @@ FROM [sys].[indexes] i using var reader = command.ExecuteReader(); var tableIndexGroups = reader.Cast() - .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("table_schema"), - tableName: ddr.GetFieldValue("table_name"))); + .GroupBy(ddr => (tableSchema: ddr.GetValueOrDefault("table_schema"), + tableName: ddr.GetFieldValue("table_name"))); foreach (var tableIndexGroup in tableIndexGroups) { @@ -1102,11 +1099,10 @@ FROM [sys].[indexes] i var primaryKeyGroups = tableIndexGroup .Where(ddr => ddr.GetValueOrDefault("is_primary_key")) - .GroupBy( - ddr => - (Name: ddr.GetFieldValue("index_name"), - TypeDesc: ddr.GetValueOrDefault("type_desc"), - FillFactor: ddr.GetValueOrDefault("fill_factor"))) + .GroupBy(ddr => + (Name: ddr.GetFieldValue("index_name"), + TypeDesc: ddr.GetValueOrDefault("type_desc"), + FillFactor: ddr.GetValueOrDefault("fill_factor"))) .ToArray(); Check.DebugAssert(primaryKeyGroups.Length is 0 or 1, "Multiple primary keys found"); @@ -1122,11 +1118,10 @@ FROM [sys].[indexes] i var uniqueConstraintGroups = tableIndexGroup .Where(ddr => ddr.GetValueOrDefault("is_unique_constraint")) - .GroupBy( - ddr => - (Name: ddr.GetValueOrDefault("index_name"), - TypeDesc: ddr.GetValueOrDefault("type_desc"), - FillFactor: ddr.GetValueOrDefault("fill_factor"))) + .GroupBy(ddr => + (Name: ddr.GetValueOrDefault("index_name"), + TypeDesc: ddr.GetValueOrDefault("type_desc"), + FillFactor: ddr.GetValueOrDefault("fill_factor"))) .ToArray(); foreach (var uniqueConstraintGroup in uniqueConstraintGroups) @@ -1139,17 +1134,15 @@ FROM [sys].[indexes] i } var indexGroups = tableIndexGroup - .Where( - ddr => !ddr.GetValueOrDefault("is_primary_key") - && !ddr.GetValueOrDefault("is_unique_constraint")) - .GroupBy( - ddr => - (Name: ddr.GetValueOrDefault("index_name"), - TypeDesc: ddr.GetValueOrDefault("type_desc"), - IsUnique: ddr.GetValueOrDefault("is_unique"), - HasFilter: ddr.GetValueOrDefault("has_filter"), - FilterDefinition: ddr.GetValueOrDefault("filter_definition"), - FillFactor: ddr.GetValueOrDefault("fill_factor"))) + .Where(ddr => !ddr.GetValueOrDefault("is_primary_key") + && !ddr.GetValueOrDefault("is_unique_constraint")) + .GroupBy(ddr => + (Name: ddr.GetValueOrDefault("index_name"), + TypeDesc: ddr.GetValueOrDefault("type_desc"), + IsUnique: ddr.GetValueOrDefault("is_unique"), + HasFilter: ddr.GetValueOrDefault("has_filter"), + FilterDefinition: ddr.GetValueOrDefault("filter_definition"), + FillFactor: ddr.GetValueOrDefault("fill_factor"))) .ToArray(); foreach (var indexGroup in indexGroups) @@ -1181,8 +1174,7 @@ bool TryGetPrimaryKey( { var columnName = dataRecord.GetValueOrDefault("column_name"); var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault( - c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); if (column is null) { @@ -1215,8 +1207,7 @@ bool TryGetUniqueConstraint( { var columnName = dataRecord.GetValueOrDefault("column_name"); var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault( - c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); if (column is null) { @@ -1263,8 +1254,7 @@ bool TryGetIndex( } var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault( - c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); if (column is null) { @@ -1307,9 +1297,8 @@ FROM [sys].[foreign_keys] AS [f] using var reader = command.ExecuteReader(); var tableForeignKeyGroups = reader.Cast() - .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("table_schema"), - tableName: ddr.GetFieldValue("table_name"))); + .GroupBy(ddr => (tableSchema: ddr.GetValueOrDefault("table_schema"), + tableName: ddr.GetFieldValue("table_name"))); foreach (var tableForeignKeyGroup in tableForeignKeyGroups) { @@ -1319,11 +1308,10 @@ FROM [sys].[foreign_keys] AS [f] var table = tables.Single(t => t.Schema == tableSchema && t.Name == tableName); var foreignKeyGroups = tableForeignKeyGroup - .GroupBy( - c => (Name: c.GetValueOrDefault("name"), - PrincipalTableSchema: c.GetValueOrDefault("principal_table_schema"), - PrincipalTableName: c.GetValueOrDefault("principal_table_name"), - OnDeleteAction: c.GetValueOrDefault("delete_referential_action_desc"))); + .GroupBy(c => (Name: c.GetValueOrDefault("name"), + PrincipalTableSchema: c.GetValueOrDefault("principal_table_schema"), + PrincipalTableName: c.GetValueOrDefault("principal_table_name"), + OnDeleteAction: c.GetValueOrDefault("delete_referential_action_desc"))); foreach (var foreignKeyGroup in foreignKeyGroups) { @@ -1347,12 +1335,10 @@ FROM [sys].[foreign_keys] AS [f] DisplayName(principalTableSchema, principalTableName), onDeleteAction!); - var principalTable = tables.FirstOrDefault( - t => t.Schema == principalTableSchema - && t.Name == principalTableName) - ?? tables.FirstOrDefault( - t => t.Schema?.Equals(principalTableSchema, StringComparison.OrdinalIgnoreCase) == true - && t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); + var principalTable = tables.FirstOrDefault(t => t.Schema == principalTableSchema + && t.Name == principalTableName) + ?? tables.FirstOrDefault(t => t.Schema?.Equals(principalTableSchema, StringComparison.OrdinalIgnoreCase) == true + && t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); if (principalTable == null) { @@ -1378,14 +1364,13 @@ FROM [sys].[foreign_keys] AS [f] { var columnName = dataRecord.GetValueOrDefault("column_name"); var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault( - c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); Check.DebugAssert(column != null, "column is null."); var principalColumnName = dataRecord.GetValueOrDefault("referenced_column_name"); var principalColumn = foreignKey.PrincipalTable.Columns.FirstOrDefault(c => c.Name == principalColumnName) - ?? foreignKey.PrincipalTable.Columns.FirstOrDefault( - c => c.Name.Equals(principalColumnName, StringComparison.OrdinalIgnoreCase)); + ?? foreignKey.PrincipalTable.Columns.FirstOrDefault(c => c.Name.Equals( + principalColumnName, StringComparison.OrdinalIgnoreCase)); if (principalColumn == null) { invalid = true; @@ -1412,10 +1397,9 @@ FROM [sys].[foreign_keys] AS [f] else { var duplicated = table.ForeignKeys - .FirstOrDefault( - k => k.Columns.SequenceEqual(foreignKey.Columns) - && k.PrincipalColumns.SequenceEqual(foreignKey.PrincipalColumns) - && k.PrincipalTable.Equals(foreignKey.PrincipalTable)); + .FirstOrDefault(k => k.Columns.SequenceEqual(foreignKey.Columns) + && k.PrincipalColumns.SequenceEqual(foreignKey.PrincipalColumns) + && k.PrincipalTable.Equals(foreignKey.PrincipalTable)); if (duplicated != null) { _logger.DuplicateForeignKeyConstraintIgnored( @@ -1449,9 +1433,8 @@ FROM [sys].[triggers] AS [tr] using var reader = command.ExecuteReader(); var tableGroups = reader.Cast() - .GroupBy( - ddr => (tableSchema: ddr.GetValueOrDefault("table_schema"), - tableName: ddr.GetFieldValue("table_name"))); + .GroupBy(ddr => (tableSchema: ddr.GetValueOrDefault("table_schema"), + tableName: ddr.GetFieldValue("table_name"))); foreach (var tableGroup in tableGroups) { @@ -1490,7 +1473,8 @@ private bool SupportsTriggers() => IsFullFeaturedEngineEdition(); private bool IsFullFeaturedEngineEdition() - => _engineEdition is not EngineEdition.SqlDataWarehouse and not EngineEdition.SqlOnDemand and not EngineEdition.DynamicsTdsEndpoint && _version != "Microsoft SQL Kusto"; + => _engineEdition is not EngineEdition.SqlDataWarehouse and not EngineEdition.SqlOnDemand and not EngineEdition.DynamicsTdsEndpoint + && _version != "Microsoft SQL Kusto"; private static string DisplayName(string? schema, string name) => (!string.IsNullOrEmpty(schema) ? schema + "." : "") + name; diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerConnection.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerConnection.cs index d4c5693d01f..f4e313aeefe 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerConnection.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerConnection.cs @@ -62,10 +62,8 @@ protected override Task OpenDbConnectionAsync(bool errorsExpected, CancellationT { return sqlConnection.OpenAsync(SqlConnectionOverrides.OpenWithoutRetry, cancellationToken); } - else - { - return DbConnection.OpenAsync(cancellationToken); - } + + return DbConnection.OpenAsync(cancellationToken); } /// diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerDatabaseCreator.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerDatabaseCreator.cs index e97f68487e8..93e386787ba 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerDatabaseCreator.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerDatabaseCreator.cs @@ -75,7 +75,9 @@ public override async Task CreateAsync(CancellationToken cancellationToken = def await using (masterConnection.ConfigureAwait(false)) { await Dependencies.MigrationCommandExecutor - .ExecuteNonQueryAsync(CreateCreateOperations(), masterConnection, new MigrationExecutionState(), commitTransaction: true, cancellationToken: cancellationToken) + .ExecuteNonQueryAsync( + CreateCreateOperations(), masterConnection, new MigrationExecutionState(), commitTransaction: true, + cancellationToken: cancellationToken) .ConfigureAwait(false); ClearPool(); @@ -149,15 +151,15 @@ private IReadOnlyList CreateCreateOperations() { var builder = new SqlConnectionStringBuilder(_connection.DbConnection.ConnectionString); return Dependencies.MigrationsSqlGenerator.Generate( - [ - new SqlServerCreateDatabaseOperation - { - Name = builder.InitialCatalog, - FileName = builder.AttachDBFilename, - Collation = Dependencies.CurrentContext.Context.GetService() - .Model.GetRelationalModel().Collation - } - ]); + [ + new SqlServerCreateDatabaseOperation + { + Name = builder.InitialCatalog, + FileName = builder.AttachDBFilename, + Collation = Dependencies.CurrentContext.Context.GetService() + .Model.GetRelationalModel().Collation + } + ]); } /// @@ -352,7 +354,9 @@ public override async Task DeleteAsync(CancellationToken cancellationToken = def var masterConnection = _connection.CreateMasterConnection(); await using var _ = masterConnection.ConfigureAwait(false); await Dependencies.MigrationCommandExecutor - .ExecuteNonQueryAsync(CreateDropCommands(), masterConnection, new MigrationExecutionState(), commitTransaction: true, cancellationToken: cancellationToken) + .ExecuteNonQueryAsync( + CreateDropCommands(), masterConnection, new MigrationExecutionState(), commitTransaction: true, + cancellationToken: cancellationToken) .ConfigureAwait(false); } diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerStructuralJsonTypeMapping.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerStructuralJsonTypeMapping.cs index d01411c695a..42fae29b1cc 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerStructuralJsonTypeMapping.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerStructuralJsonTypeMapping.cs @@ -3,7 +3,6 @@ using System.Data; using System.Text; -using System.Text.Json; using Microsoft.Data.SqlClient; namespace Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; @@ -28,7 +27,8 @@ private static readonly MethodInfo GetStringMethod /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public static SqlServerStructuralJsonTypeMapping Default => JsonTypeDefault; + public static SqlServerStructuralJsonTypeMapping Default + => JsonTypeDefault; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs index 2449906081a..845c0b9b61b 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs @@ -310,19 +310,19 @@ static SqlServerTypeMappingSource() switch (clrType) { - case Type t when t == typeof(ulong) && mappingInfo.IsRowVersion is true: + case { } t when t == typeof(ulong) && mappingInfo.IsRowVersion is true: return UlongRowversion; - case Type t when t == typeof(long) && mappingInfo.IsRowVersion is true: + case { } t when t == typeof(long) && mappingInfo.IsRowVersion is true: return LongRowversion; - case Type t when t == typeof(byte[]) && mappingInfo.IsRowVersion is true: + case { } t when t == typeof(byte[]) && mappingInfo.IsRowVersion is true: return Rowversion; - case Type t when t == typeof(string) && storeTypeName == "json": + case { } t when t == typeof(string) && storeTypeName == "json": return SqlServerStringTypeMapping.JsonTypeDefault; - case Type t when t == typeof(string): + case { } t when t == typeof(string): { var isAnsi = mappingInfo.IsUnicode == false; var isFixedLength = mappingInfo.IsFixedLength == true; @@ -355,7 +355,7 @@ static SqlServerTypeMappingSource() useKeyComparison: mappingInfo.IsKey); } - case Type t when t == typeof(byte[]) && mappingInfo.ElementTypeMapping is null: + case { } t when t == typeof(byte[]) && mappingInfo.ElementTypeMapping is null: { var isFixedLength = mappingInfo.IsFixedLength == true; @@ -373,7 +373,7 @@ static SqlServerTypeMappingSource() storeTypePostfix: storeTypeName == null ? StoreTypePostfix.Size : StoreTypePostfix.None); } - case Type t when t == typeof(SqlVector): + case { } t when t == typeof(SqlVector): return new SqlServerVectorTypeMapping(mappingInfo.Size); } } @@ -401,10 +401,10 @@ static SqlServerTypeMappingSource() info.CoreTypeMappingInfo, modelType, providerType, ref elementMapping, out var comparer, out var collectionReaderWriter)) { var jsonTypeMappingInfo = new RelationalTypeMappingInfo( - info.CoreTypeMappingInfo.ClrType, - (RelationalTypeMapping?)info.CoreTypeMappingInfo.ElementTypeMapping, - storeTypeName: "json", - storeTypeNameBase: "json") + info.CoreTypeMappingInfo.ClrType, + (RelationalTypeMapping?)info.CoreTypeMappingInfo.ElementTypeMapping, + storeTypeName: "json", + storeTypeNameBase: "json") // Note that the converter info is only used temporarily here and never creates an instance. .WithConverter(new ValueConverterInfo(modelType, typeof(string), _ => null!)); diff --git a/src/EFCore.SqlServer/Storage/Internal/SqlServerVectorTypeMapping.cs b/src/EFCore.SqlServer/Storage/Internal/SqlServerVectorTypeMapping.cs index 03d199197be..0f068bd1f34 100644 --- a/src/EFCore.SqlServer/Storage/Internal/SqlServerVectorTypeMapping.cs +++ b/src/EFCore.SqlServer/Storage/Internal/SqlServerVectorTypeMapping.cs @@ -125,7 +125,7 @@ private sealed class VectorComparer() : ValueComparer>( // This is because vectors are basically immutable, and it's better to have more efficient change tracking // equality checks. private static bool CalculateEquality(SqlVector? x, SqlVector? y) - => x is SqlVector v1 && y is SqlVector v2 + => x is { } v1 && y is { } v2 ? v1.IsNull ? v2.IsNull : !v2.IsNull && v1.Memory.Span == v2.Memory.Span diff --git a/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs b/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs index 9cef4d8619d..6c5d369bb6f 100644 --- a/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs +++ b/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs @@ -59,11 +59,10 @@ public override ResultSetMapping AppendInsertOperation( // Otherwise fall back to INSERT ... OUTPUT INTO @inserted; SELECT ... FROM @inserted. var table = StoreObjectIdentifier.Table(command.TableName, command.Schema); - return command.ColumnModifications.All( - o => - !o.IsKey - || !o.IsRead - || o.Property?.GetValueGenerationStrategy(table) == SqlServerValueGenerationStrategy.IdentityColumn) + return command.ColumnModifications.All(o => + !o.IsKey + || !o.IsRead + || o.Property?.GetValueGenerationStrategy(table) == SqlServerValueGenerationStrategy.IdentityColumn) ? AppendInsertAndSelectOperation(commandStringBuilder, command, commandPosition, out requiresTransaction) : AppendInsertSingleRowWithOutputInto( commandStringBuilder, @@ -235,11 +234,10 @@ public virtual ResultSetMapping AppendBulkInsertOperation( var keyOperations = firstCommand.ColumnModifications.Where(o => o.IsKey).ToList(); var writableOperations = modificationCommands[0].ColumnModifications - .Where( - o => - o.Property?.GetValueGenerationStrategy(table) != SqlServerValueGenerationStrategy.IdentityColumn - && o.Property?.GetComputedColumnSql() is null - && o.Property?.GetColumnType() is not "rowversion" and not "timestamp") + .Where(o => + o.Property?.GetValueGenerationStrategy(table) != SqlServerValueGenerationStrategy.IdentityColumn + && o.Property?.GetComputedColumnSql() is null + && o.Property?.GetColumnType() is not "rowversion" and not "timestamp") .ToList(); if (writeOperations.Count == 0) @@ -324,11 +322,10 @@ public virtual ResultSetMapping AppendBulkInsertOperation( // If we have an IDENTITY column, then multiple batched SELECT+INSERTs are faster up to a certain threshold (4), and then // MERGE ... OUTPUT INTO is faster. if (modificationCommands.Count < MergeIntoMinimumThreshold - && firstCommand.ColumnModifications.All( - o => - !o.IsKey - || !o.IsRead - || o.Property?.GetValueGenerationStrategy(table) == SqlServerValueGenerationStrategy.IdentityColumn)) + && firstCommand.ColumnModifications.All(o => + !o.IsKey + || !o.IsRead + || o.Property?.GetValueGenerationStrategy(table) == SqlServerValueGenerationStrategy.IdentityColumn)) { requiresTransaction = true; @@ -620,8 +617,8 @@ public override ResultSetMapping AppendStoredProcedureCall( { var returnValueModification = command.ColumnModifications.First(c => c.Column is IStoreStoredProcedureReturnValue); - Check.DebugAssert(returnValueModification.UseCurrentValueParameter, "returnValueModification.UseCurrentValueParameter"); - Check.DebugAssert(!returnValueModification.UseOriginalValueParameter, "!returnValueModification.UseOriginalValueParameter"); + Check.DebugAssert(returnValueModification.UseCurrentValueParameter); + Check.DebugAssert(!returnValueModification.UseOriginalValueParameter); SqlGenerationHelper.GenerateParameterNamePlaceholder(commandStringBuilder, returnValueModification.ParameterName!); diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs index 20190cc57aa..c4c6f1680ce 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqliteServiceCollectionExtensions.cs @@ -59,12 +59,11 @@ public static IServiceCollection AddSqlite( Action? sqliteOptionsAction = null, Action? optionsAction = null) where TContext : DbContext - => serviceCollection.AddDbContext( - (_, options) => - { - optionsAction?.Invoke(options); - options.UseSqlite(connectionString, sqliteOptionsAction); - }); + => serviceCollection.AddDbContext((_, options) => + { + optionsAction?.Invoke(options); + options.UseSqlite(connectionString, sqliteOptionsAction); + }); /// /// @@ -116,8 +115,7 @@ public static IServiceCollection AddEntityFrameworkSqlite(this IServiceCollectio .TryAdd() .TryAdd() .TryAdd() - .TryAddProviderSpecificServices( - b => b.TryAddScoped()) + .TryAddProviderSpecificServices(b => b.TryAddScoped()) .TryAddCoreServices(); return serviceCollection; diff --git a/src/EFCore.Sqlite.Core/Extensions/SqliteTableExtensions.cs b/src/EFCore.Sqlite.Core/Extensions/SqliteTableExtensions.cs index a6d13f65962..e2d9d5b3993 100644 --- a/src/EFCore.Sqlite.Core/Extensions/SqliteTableExtensions.cs +++ b/src/EFCore.Sqlite.Core/Extensions/SqliteTableExtensions.cs @@ -24,8 +24,8 @@ public static bool IsSqlReturningClauseUsed(this ITable table) return isSqlOutputClauseUsed; } - isSqlOutputClauseUsed = table.EntityTypeMappings.All( - e => ((IEntityType)e.TypeBase).IsSqlReturningClauseUsed(StoreObjectIdentifier.Table(table.Name, table.Schema))); + isSqlOutputClauseUsed = table.EntityTypeMappings.All(e + => ((IEntityType)e.TypeBase).IsSqlReturningClauseUsed(StoreObjectIdentifier.Table(table.Name, table.Schema))); table.SetRuntimeAnnotation(SqliteAnnotationNames.UseSqlReturningClause, isSqlOutputClauseUsed); diff --git a/src/EFCore.Sqlite.Core/Infrastructure/Internal/SqliteModelValidator.cs b/src/EFCore.Sqlite.Core/Infrastructure/Internal/SqliteModelValidator.cs index d601b461a1f..08fe9f7a074 100644 --- a/src/EFCore.Sqlite.Core/Infrastructure/Internal/SqliteModelValidator.cs +++ b/src/EFCore.Sqlite.Core/Infrastructure/Internal/SqliteModelValidator.cs @@ -141,12 +141,11 @@ protected override void ValidateValueGeneration( if (!entityType.IsMappedToJson() && key.IsPrimaryKey() && keyProperties.Count(p => p.ClrType.UnwrapNullableType().IsInteger()) > 1 - && keyProperties.Any( - p => p.ValueGenerated == ValueGenerated.OnAdd - && p.ClrType.UnwrapNullableType().IsInteger() - && !p.TryGetDefaultValue(out _) - && p.GetDefaultValueSql() == null - && !p.IsForeignKey())) + && keyProperties.Any(p => p.ValueGenerated == ValueGenerated.OnAdd + && p.ClrType.UnwrapNullableType().IsInteger() + && !p.TryGetDefaultValue(out _) + && p.GetDefaultValueSql() == null + && !p.IsForeignKey())) { logger.CompositeKeyWithValueGeneration(key); } diff --git a/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs b/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs index 59b2b0cc065..ce3b774f77d 100644 --- a/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs +++ b/src/EFCore.Sqlite.Core/Infrastructure/SpatialiteLoader.cs @@ -193,11 +193,10 @@ private static void FindExtension() } if (currentPath == null - || !currentPath.Split(Path.PathSeparator).Any( - p => string.Equals( - p.TrimEnd(Path.DirectorySeparatorChar), - assetDirectory, - StringComparison.OrdinalIgnoreCase))) + || !currentPath.Split(Path.PathSeparator).Any(p => string.Equals( + p.TrimEnd(Path.DirectorySeparatorChar), + assetDirectory, + StringComparison.OrdinalIgnoreCase))) { Environment.SetEnvironmentVariable( PathVariableName!, diff --git a/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteConventionSetBuilder.cs b/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteConventionSetBuilder.cs index 66046bb1ac5..1cebd484d5b 100644 --- a/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteConventionSetBuilder.cs +++ b/src/EFCore.Sqlite.Core/Metadata/Conventions/SqliteConventionSetBuilder.cs @@ -84,10 +84,9 @@ private static IServiceScope CreateServiceScope() { var serviceProvider = new ServiceCollection() .AddEntityFrameworkSqlite() - .AddDbContext( - (p, o) => - o.UseSqlite("Filename=_.db") - .UseInternalServiceProvider(p)) + .AddDbContext((p, o) => + o.UseSqlite("Filename=_.db") + .UseInternalServiceProvider(p)) .BuildServiceProvider(); return serviceProvider.GetRequiredService().CreateScope(); } diff --git a/src/EFCore.Sqlite.Core/Metadata/Internal/SqliteAnnotationProvider.cs b/src/EFCore.Sqlite.Core/Metadata/Internal/SqliteAnnotationProvider.cs index 51aeb3bf830..525780bb16a 100644 --- a/src/EFCore.Sqlite.Core/Metadata/Internal/SqliteAnnotationProvider.cs +++ b/src/EFCore.Sqlite.Core/Metadata/Internal/SqliteAnnotationProvider.cs @@ -38,8 +38,7 @@ public override IEnumerable For(IRelationalModel model, bool design yield break; } - if (model.Tables.SelectMany(t => t.Columns).Any( - c => SqliteTypeMappingSource.IsSpatialiteType(c.StoreType))) + if (model.Tables.SelectMany(t => t.Columns).Any(c => SqliteTypeMappingSource.IsSpatialiteType(c.StoreType))) { yield return new Annotation(SqliteAnnotationNames.InitSpatialMetaData, true); } diff --git a/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteHistoryRepository.cs b/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteHistoryRepository.cs index 89d8fefc0c8..7b34d46e434 100644 --- a/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteHistoryRepository.cs +++ b/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteHistoryRepository.cs @@ -103,7 +103,8 @@ public override string GetEndIfScript() /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public override LockReleaseBehavior LockReleaseBehavior => LockReleaseBehavior.Explicit; + public override LockReleaseBehavior LockReleaseBehavior + => LockReleaseBehavior.Explicit; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -116,8 +117,8 @@ public override IMigrationsDatabaseLock AcquireDatabaseLock() Dependencies.MigrationsLogger.AcquiringMigrationLock(); if (!InterpretExistsResult( - Dependencies.RawSqlCommandBuilder.Build(CreateExistsSql(LockTableName)) - .ExecuteScalar(CreateRelationalCommandParameters()))) + Dependencies.RawSqlCommandBuilder.Build(CreateExistsSql(LockTableName)) + .ExecuteScalar(CreateRelationalCommandParameters()))) { CreateLockTableCommand().ExecuteNonQuery(CreateRelationalCommandParameters()); } @@ -153,8 +154,8 @@ public override async Task AcquireDatabaseLockAsync( Dependencies.MigrationsLogger.AcquiringMigrationLock(); if (!InterpretExistsResult( - await Dependencies.RawSqlCommandBuilder.Build(CreateExistsSql(LockTableName)) - .ExecuteScalarAsync(CreateRelationalCommandParameters(), cancellationToken).ConfigureAwait(false))) + await Dependencies.RawSqlCommandBuilder.Build(CreateExistsSql(LockTableName)) + .ExecuteScalarAsync(CreateRelationalCommandParameters(), cancellationToken).ConfigureAwait(false))) { await CreateLockTableCommand().ExecuteNonQueryAsync(CreateRelationalCommandParameters(), cancellationToken) .ConfigureAwait(false); diff --git a/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteMigrationDatabaseLock.cs b/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteMigrationDatabaseLock.cs index 668d2107eaf..a565b70b4e5 100644 --- a/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteMigrationDatabaseLock.cs +++ b/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteMigrationDatabaseLock.cs @@ -22,7 +22,8 @@ public class SqliteMigrationDatabaseLock( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual IHistoryRepository HistoryRepository => historyRepository; + public virtual IHistoryRepository HistoryRepository + => historyRepository; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqlExpressions/JsonEachExpression.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqlExpressions/JsonEachExpression.cs index 3a2eef74f86..ea4ee5ee388 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqlExpressions/JsonEachExpression.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqlExpressions/JsonEachExpression.cs @@ -51,7 +51,7 @@ public JsonEachExpression( string alias, SqlExpression jsonExpression, IReadOnlyList? path = null) - : base(alias, "json_each", schema: null, builtIn: true, new[] { jsonExpression }) + : base(alias, "json_each", schema: null, builtIn: true, [jsonExpression]) => Path = path; /// diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteParameterBasedSqlProcessor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteParameterBasedSqlProcessor.cs index 042e6ed41af..09b0bfb67e9 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteParameterBasedSqlProcessor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteParameterBasedSqlProcessor.cs @@ -14,7 +14,6 @@ public class SqliteParameterBasedSqlProcessor( RelationalParameterBasedSqlProcessorParameters parameters) : RelationalParameterBasedSqlProcessor(dependencies, parameters) { - /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs index 952c270cecd..33f7a06a8cd 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs @@ -145,10 +145,9 @@ static bool TryUnwrapBareSetOperation(SelectExpression selectExpression, [NotNul GroupBy: [] } && selectExpression.Projection.Count == s.Source1.Projection.Count - && selectExpression.Projection.Select( - (pe, index) => pe.Expression is ColumnExpression column - && column.TableAlias == s.Alias - && column.Name == s.Source1.Projection[index].Alias) + && selectExpression.Projection.Select((pe, index) => pe.Expression is ColumnExpression column + && column.TableAlias == s.Alias + && column.Name == s.Source1.Projection[index].Alias) .All(e => e)) { setOperation = s; @@ -219,11 +218,11 @@ protected virtual void GenerateJsonEach(JsonEachExpression jsonEachExpression) { switch (path[i]) { - case { PropertyName: string propertyName }: + case { PropertyName: { } propertyName }: Sql.Append(".").Append(propertyName); break; - case { ArrayIndex: SqlExpression arrayIndex }: + case { ArrayIndex: { } arrayIndex }: Sql.Append("["); if (arrayIndex is SqlConstantExpression) @@ -282,7 +281,7 @@ protected override Expression VisitJsonScalar(JsonScalarExpression jsonScalarExp switch (pathSegment) { - case { PropertyName: string propertyName }: + case { PropertyName: { } propertyName }: if (inJsonpathString) { Sql.Append(".").Append(Dependencies.SqlGenerationHelper.DelimitJsonPathElement(propertyName)); @@ -335,7 +334,7 @@ protected override Expression VisitJsonScalar(JsonScalarExpression jsonScalarExp Sql.Append(" ->> "); - Check.DebugAssert(pathSegment.ArrayIndex is not null, "pathSegment.ArrayIndex is not null"); + Check.DebugAssert(pathSegment.ArrayIndex is not null); var requiresParentheses = RequiresParentheses(jsonScalarExpression, pathSegment.ArrayIndex); if (requiresParentheses) diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs index 275452fc583..f150150fce8 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs @@ -109,7 +109,7 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "json_array_length", - new[] { array }, + [array], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(int)), @@ -148,7 +148,8 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis throw new NotSupportedException( SqliteStrings.OrderByNotSupported(orderingExpressionType.ShortDisplayName())); } - else if (orderingExpressionType == typeof(decimal)) + + if (orderingExpressionType == typeof(decimal)) { translation = new CollateExpression(translation, "EF_DECIMAL"); } @@ -183,7 +184,8 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis throw new NotSupportedException( SqliteStrings.OrderByNotSupported(orderingExpressionType.ShortDisplayName())); } - else if (orderingExpressionType == typeof(decimal)) + + if (orderingExpressionType == typeof(decimal)) { translation = new CollateExpression(translation, "EF_DECIMAL"); } @@ -216,7 +218,7 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis { var translation = _sqlExpressionFactory.Function( "json_array_length", - new[] { array }, + [array], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(int)); @@ -381,7 +383,7 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr // We're only interested in properties which actually exist in the JSON, filter out uninteresting synthetic keys foreach (var property in structuralType.GetPropertiesInHierarchy()) { - if (property.GetJsonPropertyName() is string jsonPropertyName) + if (property.GetJsonPropertyName() is { } jsonPropertyName) { // HACK: currently the only way to project multiple values from a SelectExpression is to simulate a Select out to an anonymous // type; this requires the MethodInfos of the anonymous type properties, from which the projection alias gets taken. @@ -400,10 +402,9 @@ [new PathSegment(property.GetJsonPropertyName()!)], if (structuralType is IEntityType entityType) { foreach (var navigation in entityType.GetNavigationsInHierarchy() - .Where( - n => n.ForeignKey.IsOwnership - && n.TargetEntityType.IsMappedToJson() - && n.ForeignKey.PrincipalToDependent == n)) + .Where(n => n.ForeignKey.IsOwnership + && n.TargetEntityType.IsMappedToJson() + && n.ForeignKey.PrincipalToDependent == n)) { var jsonNavigationName = navigation.TargetEntityType.GetJsonPropertyName(); Check.DebugAssert(jsonNavigationName is not null, "Invalid navigation found on JSON-mapped entity"); @@ -492,38 +493,41 @@ [new PathSegment(jsonNavigationName)], // index on parameter using a column // translate via JSON because it is a better translation case SelectExpression - { - Tables: [ValuesExpression { ValuesParameter: { } valuesParameter }], - Predicate: null, - GroupBy: [], - Having: null, - IsDistinct: false, + { + Tables: [ValuesExpression { ValuesParameter: { } valuesParameter }], + Predicate: null, + GroupBy: [], + Having: null, + IsDistinct: false, #pragma warning disable EF1001 - Orderings: [{ Expression: ColumnExpression { Name: ValuesOrderingColumnName }, IsAscending: true }], + Orderings: [{ Expression: ColumnExpression { Name: ValuesOrderingColumnName }, IsAscending: true }], #pragma warning restore EF1001 - Limit: null, - Offset: null - } selectExpression - when TranslateExpression(index) is { } translatedIndex + Limit: null, + Offset: null + } selectExpression + when TranslateExpression(index) is { } translatedIndex && TryTranslate(selectExpression, valuesParameter, translatedIndex, out var result): return result; // Index on JSON array case SelectExpression - { - Tables: [TableValuedFunctionExpression { - Name: "json_each", Schema: null, IsBuiltIn: true, Arguments: [var jsonArrayColumn] - } jsonEachExpression], - Predicate: null, - GroupBy: [], - Having: null, - IsDistinct: false, - Orderings: [{ Expression: ColumnExpression { Name: JsonEachKeyColumnName } orderingColumn, IsAscending: true }], - Limit: null, - Offset: null - } selectExpression - when orderingColumn.TableAlias == jsonEachExpression.Alias + Tables: + [ + TableValuedFunctionExpression + { + Name: "json_each", Schema: null, IsBuiltIn: true, Arguments: [var jsonArrayColumn] + } jsonEachExpression + ], + Predicate: null, + GroupBy: [], + Having: null, + IsDistinct: false, + Orderings: [{ Expression: ColumnExpression { Name: JsonEachKeyColumnName } orderingColumn, IsAscending: true }], + Limit: null, + Offset: null + } selectExpression + when orderingColumn.TableAlias == jsonEachExpression.Alias && TranslateExpression(index) is { } translatedIndex && TryTranslate(selectExpression, jsonArrayColumn, translatedIndex, out var result): return result; @@ -536,7 +540,7 @@ bool TryTranslate( SelectExpression selectExpression, SqlExpression jsonArrayColumn, SqlExpression translatedIndex, - [NotNullWhen(true)]out ShapedQueryExpression? result) + [NotNullWhen(true)] out ShapedQueryExpression? result) { // Extract the column projected out of the source, and simplify the subquery to a simple JsonScalarExpression var shaperExpression = source.ShaperExpression; @@ -552,7 +556,7 @@ bool TryTranslate( { SqlExpression translation = new JsonScalarExpression( jsonArrayColumn, - new[] { new PathSegment(translatedIndex) }, + [new PathSegment(translatedIndex)], projectionColumn.Type, projectionColumn.TypeMapping, projectionColumn.IsNullable); @@ -585,21 +589,21 @@ bool TryTranslate( protected override bool IsNaturallyOrdered(SelectExpression selectExpression) { return selectExpression is - { - Tables: [var mainTable, ..], - Orderings: + { + Tables: [var mainTable, ..], + Orderings: [ - { - Expression: ColumnExpression { Name: JsonEachKeyColumnName } orderingColumn, - IsAscending: true - } + { + Expression: ColumnExpression { Name: JsonEachKeyColumnName } orderingColumn, + IsAscending: true + } ] - } + } && orderingColumn.TableAlias == mainTable.Alias && IsJsonEachKeyColumn(selectExpression, orderingColumn); bool IsJsonEachKeyColumn(SelectExpression selectExpression, ColumnExpression orderingColumn) - => selectExpression.Tables.FirstOrDefault(t => t.Alias == orderingColumn.TableAlias)?.UnwrapJoin() is TableExpressionBase table + => selectExpression.Tables.FirstOrDefault(t => t.Alias == orderingColumn.TableAlias)?.UnwrapJoin() is { } table && (table is JsonEachExpression || (table is SelectExpression subquery && subquery.Projection.FirstOrDefault(p => p.Alias == JsonEachKeyColumnName)?.Expression is ColumnExpression @@ -640,7 +644,7 @@ public static SqlExpression ApplyJsonSqlConversion( ByteArrayTypeMapping => sqlExpressionFactory.Function( "unhex", - new[] { expression }, + [expression], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(byte[]), diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlExpressionFactory.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlExpressionFactory.cs index bd837879247..91ddd2b8793 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlExpressionFactory.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlExpressionFactory.cs @@ -40,7 +40,7 @@ public virtual SqlExpression Strftime( IEnumerable? modifiers = null, RelationalTypeMapping? typeMapping = null) { - modifiers ??= Enumerable.Empty(); + modifiers ??= []; // If the inner call is another strftime then shortcut a double call if (timestring is SqlFunctionExpression { Name: "rtrim" } rtrimFunction @@ -86,7 +86,7 @@ public virtual SqlExpression Date( IEnumerable? modifiers = null, RelationalTypeMapping? typeMapping = null) { - modifiers ??= Enumerable.Empty(); + modifiers ??= []; if (timestring is SqlFunctionExpression { Name: "date" } dateFunction) { diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlNullabilityProcessor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlNullabilityProcessor.cs index d86cb5bcdd3..470dd3af33c 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlNullabilityProcessor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlNullabilityProcessor.cs @@ -136,7 +136,7 @@ protected override TableExpressionBase UpdateParameterCollection( TableExpressionBase table, SqlParameterExpression newCollectionParameter) => table is TableValuedFunctionExpression { Arguments: [SqlParameterExpression] } jsonEachExpression - ? jsonEachExpression.Update(new[] { newCollectionParameter }) + ? jsonEachExpression.Update([newCollectionParameter]) : base.UpdateParameterCollection(table, newCollectionParameter); #pragma warning restore EF1001 } diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs index ea89ab030fe..723657cb2cf 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs @@ -132,7 +132,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) return Visit(unaryExpression.Operand) is SqlExpression sqlExpression ? Dependencies.SqlExpressionFactory.Function( "length", - new[] { sqlExpression }, + [sqlExpression], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(int)) @@ -152,9 +152,9 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) { return Dependencies.SqlExpressionFactory.Function( name: "ef_negate", - new[] { sqlUnary.Operand }, + [sqlUnary.Operand], nullable: true, - new[] { true }, + [true], visitedExpression.Type); } @@ -228,7 +228,7 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) { return Dependencies.SqlExpressionFactory.Function( function, - new[] { sqlBinary.Left, sqlBinary.Right }, + [sqlBinary.Left, sqlBinary.Right], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[2], visitedExpression.Type, @@ -325,7 +325,7 @@ bool TryTranslateStartsEndsWith( char s => IsLikeWildChar(s) ? _sqlExpressionFactory.Like( translatedInstance, - _sqlExpressionFactory.Constant(startsWith ? LikeEscapeString + s + "%" : '%' + LikeEscapeString + s), + _sqlExpressionFactory.Constant(startsWith ? LikeEscapeString + s + "%" : '%' + LikeEscapeString + s), _sqlExpressionFactory.Constant(LikeEscapeString)) : _sqlExpressionFactory.Like( translatedInstance, @@ -379,17 +379,16 @@ bool TryTranslateStartsEndsWith( _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "substr", - new[] - { + [ translatedInstance, _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Function( "length", - new[] { translatedPattern }, + [translatedPattern], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(int)) - }, + ], nullable: true, argumentsPropagateNullability: [true, false, false], typeof(string), @@ -413,17 +412,16 @@ bool TryTranslateStartsEndsWith( _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "substr", - new[] - { + [ translatedInstance, _sqlExpressionFactory.Negate( _sqlExpressionFactory.Function( "length", - new[] { translatedPattern }, + [translatedPattern], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(int))) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], typeof(string), @@ -458,7 +456,7 @@ bool TryTranslateStartsEndsWith( string s => startsWith ? EscapeLikePattern(s) + '%' : '%' + EscapeLikePattern(s), - char s when IsLikeWildChar(s )=> startsWith ? LikeEscapeString + s + '%' : '%' + LikeEscapeString + s, + char s when IsLikeWildChar(s) => startsWith ? LikeEscapeString + s + '%' : '%' + LikeEscapeString + s, char s => startsWith ? s + "%" : "%" + s, @@ -542,9 +540,9 @@ private Expression DoDecimalCompare(SqlExpression visitedExpression, ExpressionT { var actual = Dependencies.SqlExpressionFactory.Function( name: "ef_compare", - new[] { left, right }, + [left, right], nullable: true, - new[] { true, true }, + [true, true], typeof(int)); var oracle = Dependencies.SqlExpressionFactory.Constant(value: 0); @@ -587,26 +585,26 @@ static string ResolveFunctionNameFromExpressionType(ExpressionType expressionTyp Expression DecimalArithmeticExpressionFactoryMethod(string name, SqlExpression left, SqlExpression right) => Dependencies.SqlExpressionFactory.Function( name, - new[] { left, right }, + [left, right], nullable: true, - new[] { true, true }, + [true, true], visitedExpression.Type); Expression DecimalDivisionExpressionFactoryMethod(string name, SqlExpression left, SqlExpression right) => Dependencies.SqlExpressionFactory.Function( name, - new[] { left, right }, + [left, right], nullable: true, - new[] { false, false }, + [false, false], visitedExpression.Type); Expression DecimalSubtractExpressionFactoryMethod(SqlExpression left, SqlExpression right) { var subtrahend = Dependencies.SqlExpressionFactory.Function( "ef_negate", - new[] { right }, + [right], nullable: true, - new[] { true }, + [true], visitedExpression.Type); return DecimalArithmeticExpressionFactoryMethod(ResolveFunctionNameFromExpressionType(op), left, subtrahend); diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteByteArrayMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteByteArrayMethodTranslator.cs index 46cacdc94aa..e5e7af297c6 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteByteArrayMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteByteArrayMethodTranslator.cs @@ -47,7 +47,7 @@ public SqliteByteArrayMethodTranslator(ISqlExpressionFactory sqlExpressionFactor ? (SqlExpression)_sqlExpressionFactory.Constant(new[] { (byte)constantValue.Value! }, source.TypeMapping) : _sqlExpressionFactory.Function( "char", - new[] { arguments[1] }, + [arguments[1]], nullable: false, argumentsPropagateNullability: Statics.FalseArrays[1], typeof(string)); @@ -55,7 +55,7 @@ public SqliteByteArrayMethodTranslator(ISqlExpressionFactory sqlExpressionFactor return _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "instr", - new[] { source, value }, + [source, value], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], typeof(int)), diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteDateTimeMemberTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteDateTimeMemberTranslator.cs index f9080403b41..6f8ca140350 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteDateTimeMemberTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteDateTimeMemberTranslator.cs @@ -58,7 +58,7 @@ public class SqliteDateTimeMemberTranslator(SqliteSqlExpressionFactory sqlExpres sqlExpressionFactory.Subtract( sqlExpressionFactory.Function( "julianday", - new[] { instance! }, + [instance!], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(double)), @@ -122,24 +122,22 @@ public class SqliteDateTimeMemberTranslator(SqliteSqlExpressionFactory sqlExpres return sqlExpressionFactory.Function( "rtrim", - new[] - { + [ sqlExpressionFactory.Function( "rtrim", - new[] - { + [ sqlExpressionFactory.Strftime( returnType, format, timestring, modifiers), sqlExpressionFactory.Constant("0") - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueFalse, returnType), sqlExpressionFactory.Constant(".") - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueFalse, returnType); diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteDateTimeMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteDateTimeMethodTranslator.cs index 86051da9d82..9081423d5bc 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteDateTimeMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteDateTimeMethodTranslator.cs @@ -87,24 +87,22 @@ private static readonly MethodInfo AddTicks { return sqlExpressionFactory.Function( "rtrim", - new[] - { + [ sqlExpressionFactory.Function( "rtrim", - new[] - { + [ sqlExpressionFactory.Strftime( method.ReturnType, "%Y-%m-%d %H:%M:%f", instance!, modifiers: [modifier]), sqlExpressionFactory.Constant("0") - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueFalse, method.ReturnType), sqlExpressionFactory.Constant(".") - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueFalse, method.ReturnType); diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteHexMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteHexMethodTranslator.cs index 4164069f612..bd3a5886e86 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteHexMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteHexMethodTranslator.cs @@ -50,7 +50,7 @@ public SqliteHexMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) { return _sqlExpressionFactory.Function( "hex", - new[] { arguments[1] }, + [arguments[1]], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(string)); diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteMathTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteMathTranslator.cs index fc09683b017..6aecd3f8802 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteMathTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteMathTranslator.cs @@ -152,10 +152,9 @@ public SqliteMathTranslator(ISqlExpressionFactory sqlExpressionFactory) return _sqlExpressionFactory.Function( "log", - new[] - { + [ _sqlExpressionFactory.ApplyTypeMapping(newBase, typeMapping), _sqlExpressionFactory.ApplyTypeMapping(a, typeMapping) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], method.ReturnType, diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteObjectToStringTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteObjectToStringTranslator.cs index 6e4b24b5b0f..61400abc90f 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteObjectToStringTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteObjectToStringTranslator.cs @@ -76,25 +76,23 @@ public SqliteObjectToStringTranslator(ISqlExpressionFactory sqlExpressionFactory { return _sqlExpressionFactory.Case( instance, - new[] - { + [ new CaseWhenClause( _sqlExpressionFactory.Constant(false), _sqlExpressionFactory.Constant(false.ToString())), new CaseWhenClause( _sqlExpressionFactory.Constant(true), _sqlExpressionFactory.Constant(true.ToString())) - }, + ], _sqlExpressionFactory.Constant(string.Empty)); } return _sqlExpressionFactory.Case( - new[] - { + [ new CaseWhenClause( instance, _sqlExpressionFactory.Constant(true.ToString())) - }, + ], _sqlExpressionFactory.Constant(false.ToString())); } diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteQueryableAggregateMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteQueryableAggregateMethodTranslator.cs index b6d412879b5..c9f11e150d2 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteQueryableAggregateMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteQueryableAggregateMethodTranslator.cs @@ -76,7 +76,8 @@ public SqliteQueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpress throw new NotSupportedException( SqliteStrings.AggregateOperationNotSupported(nameof(Queryable.Max), maxArgumentType.ShortDisplayName())); } - else if (maxArgumentType == typeof(decimal)) + + if (maxArgumentType == typeof(decimal)) { maxSqlExpression = CombineTerms(source, maxSqlExpression); return _sqlExpressionFactory.Function( @@ -102,7 +103,8 @@ public SqliteQueryableAggregateMethodTranslator(ISqlExpressionFactory sqlExpress throw new NotSupportedException( SqliteStrings.AggregateOperationNotSupported(nameof(Queryable.Min), minArgumentType.ShortDisplayName())); } - else if (minArgumentType == typeof(decimal)) + + if (minArgumentType == typeof(decimal)) { minSqlExpression = CombineTerms(source, minSqlExpression); return _sqlExpressionFactory.Function( diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteRandomTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteRandomTranslator.cs index 1f3050dbb9b..b111e7de682 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteRandomTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteRandomTranslator.cs @@ -43,17 +43,16 @@ public SqliteRandomTranslator(ISqlExpressionFactory sqlExpressionFactory) => MethodInfo.Equals(method) ? _sqlExpressionFactory.Function( "abs", - new[] - { + [ _sqlExpressionFactory.Divide( _sqlExpressionFactory.Function( "random", - Enumerable.Empty(), + [], nullable: false, - argumentsPropagateNullability: Enumerable.Empty(), + argumentsPropagateNullability: [], method.ReturnType), _sqlExpressionFactory.Constant(9223372036854780000.0)) - }, + ], nullable: false, argumentsPropagateNullability: Statics.TrueArrays[1], method.ReturnType) diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringAggregateMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringAggregateMethodTranslator.cs index c47045348cf..492539f26ed 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringAggregateMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringAggregateMethodTranslator.cs @@ -83,13 +83,12 @@ public SqliteStringAggregateMethodTranslator(ISqlExpressionFactory sqlExpression return _sqlExpressionFactory.Coalesce( _sqlExpressionFactory.Function( "group_concat", - new[] - { + [ sqlExpression, _sqlExpressionFactory.ApplyTypeMapping( method == StringJoinMethod ? arguments[0] : _sqlExpressionFactory.Constant(string.Empty, typeof(string)), sqlExpression.TypeMapping) - }, + ], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[2], typeof(string)), diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringLengthTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringLengthTranslator.cs index 89975bcf7aa..10e8a4416f7 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringLengthTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringLengthTranslator.cs @@ -40,7 +40,7 @@ public SqliteStringLengthTranslator(ISqlExpressionFactory sqlExpressionFactory) && member.Name == nameof(string.Length) ? _sqlExpressionFactory.Function( "length", - new[] { instance! }, + [instance!], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], returnType) diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringMethodTranslator.cs index 7297982a0e6..c806954ee51 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringMethodTranslator.cs @@ -79,18 +79,17 @@ private static readonly MethodInfo TrimMethodInfoWithCharArrayArg private static readonly MethodInfo ContainsMethodInfoString = typeof(string).GetRuntimeMethod(nameof(string.Contains), [typeof(string)])!; + private static readonly MethodInfo ContainsMethodInfoChar = typeof(string).GetRuntimeMethod(nameof(string.Contains), [typeof(char)])!; private static readonly MethodInfo FirstOrDefaultMethodInfoWithoutArgs - = typeof(Enumerable).GetRuntimeMethods().Single( - m => m.Name == nameof(Enumerable.FirstOrDefault) - && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); + = typeof(Enumerable).GetRuntimeMethods().Single(m => m.Name == nameof(Enumerable.FirstOrDefault) + && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); private static readonly MethodInfo LastOrDefaultMethodInfoWithoutArgs - = typeof(Enumerable).GetRuntimeMethods().Single( - m => m.Name == nameof(Enumerable.LastOrDefault) - && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); + = typeof(Enumerable).GetRuntimeMethods().Single(m => m.Name == nameof(Enumerable.LastOrDefault) + && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); private readonly ISqlExpressionFactory _sqlExpressionFactory; @@ -125,11 +124,11 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) return _sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( "instr", - new[] - { + [ _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), - _sqlExpressionFactory.ApplyTypeMapping(argument, argument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping) - }, + _sqlExpressionFactory.ApplyTypeMapping( + argument, argument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping) + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], method.ReturnType), @@ -142,7 +141,7 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument); instance = _sqlExpressionFactory.Function( "substr", - new[] { instance, _sqlExpressionFactory.Add(arguments[1], _sqlExpressionFactory.Constant(1)) }, + [instance, _sqlExpressionFactory.Add(arguments[1], _sqlExpressionFactory.Constant(1))], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], method.ReturnType, @@ -152,11 +151,11 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( "instr", - new[] - { + [ _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), - _sqlExpressionFactory.ApplyTypeMapping(argument, argument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping) - }, + _sqlExpressionFactory.ApplyTypeMapping( + argument, argument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping) + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], method.ReturnType), @@ -172,12 +171,13 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) return _sqlExpressionFactory.Function( "replace", - new[] - { + [ _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), - _sqlExpressionFactory.ApplyTypeMapping(firstArgument, firstArgument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping), - _sqlExpressionFactory.ApplyTypeMapping(secondArgument, secondArgument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping) - }, + _sqlExpressionFactory.ApplyTypeMapping( + firstArgument, firstArgument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping), + _sqlExpressionFactory.ApplyTypeMapping( + secondArgument, secondArgument.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping) + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], method.ReturnType, @@ -189,7 +189,7 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) { return _sqlExpressionFactory.Function( ToLowerMethodInfo.Equals(method) ? "lower" : "upper", - new[] { instance }, + [instance], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], method.ReturnType, @@ -200,7 +200,7 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) { return _sqlExpressionFactory.Function( "substr", - new[] { instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)) }, + [instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1))], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], method.ReturnType, @@ -211,7 +211,7 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) { return _sqlExpressionFactory.Function( "substr", - new[] { instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)), arguments[1] }, + [instance, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)), arguments[1]], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], method.ReturnType, @@ -245,13 +245,14 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern); instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); - pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, pattern.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping); + pattern = _sqlExpressionFactory.ApplyTypeMapping( + pattern, pattern.Type == typeof(char) ? CharTypeMapping.Default : stringTypeMapping); return _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "instr", - new[] { instance, pattern }, + [instance, pattern], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], typeof(int)), @@ -268,9 +269,9 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) _sqlExpressionFactory.Equal( _sqlExpressionFactory.Function( "trim", - new[] { argument }, + [argument], nullable: true, - argumentsPropagateNullability: new[] { true }, + argumentsPropagateNullability: [true], argument.Type, argument.TypeMapping), _sqlExpressionFactory.Constant(string.Empty))); @@ -281,7 +282,7 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) var argument = arguments[0]; return _sqlExpressionFactory.Function( "substr", - new[] { argument, _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1) }, + [argument, _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1)], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], method.ReturnType); @@ -292,17 +293,16 @@ public SqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) var argument = arguments[0]; return _sqlExpressionFactory.Function( "substr", - new[] - { + [ argument, _sqlExpressionFactory.Function( "length", - new[] { argument }, + [argument], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(int)), _sqlExpressionFactory.Constant(1) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[3], method.ReturnType); diff --git a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs index 15289bf3c9c..374563a31dd 100644 --- a/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs +++ b/src/EFCore.Sqlite.Core/Scaffolding/Internal/SqliteDatabaseModelFactory.cs @@ -989,8 +989,7 @@ ORDER BY "seqno" { var columnName = reader2.GetString(0); var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault( - c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); Check.DebugAssert(column != null, "column is null."); uniqueConstraint.Columns.Add(column); @@ -1083,8 +1082,7 @@ ORDER BY "id" var principalTableName = reader1.GetString(1); var onDelete = reader1.GetString(2); var principalTable = tables.FirstOrDefault(t => t.Name == principalTableName) - ?? tables.FirstOrDefault( - t => t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); + ?? tables.FirstOrDefault(t => t.Name.Equals(principalTableName, StringComparison.OrdinalIgnoreCase)); _logger.ForeignKeyFound(table.Name, id, principalTableName, onDelete); @@ -1129,8 +1127,7 @@ ORDER BY "seq" { var columnName = reader2.GetString(1); var column = table.Columns.FirstOrDefault(c => c.Name == columnName) - ?? table.Columns.FirstOrDefault( - c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); + ?? table.Columns.FirstOrDefault(c => c.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)); Check.DebugAssert(column != null, "column is null."); var principalColumnName = reader2.IsDBNull(2) ? null : reader2.GetString(2); @@ -1139,8 +1136,8 @@ ORDER BY "seq" { principalColumn = foreignKey.PrincipalTable.Columns.FirstOrDefault(c => c.Name == principalColumnName) - ?? foreignKey.PrincipalTable.Columns.FirstOrDefault( - c => c.Name.Equals(principalColumnName, StringComparison.OrdinalIgnoreCase)); + ?? foreignKey.PrincipalTable.Columns.FirstOrDefault(c => c.Name.Equals( + principalColumnName, StringComparison.OrdinalIgnoreCase)); } else if (principalTable?.PrimaryKey != null) { diff --git a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteJsonTypeMapping.cs b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteJsonTypeMapping.cs index 32d5931aa1e..c90b5317a3d 100644 --- a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteJsonTypeMapping.cs +++ b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteJsonTypeMapping.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text; -using System.Text.Json; namespace Microsoft.EntityFrameworkCore.Sqlite.Storage.Internal; diff --git a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs index f0c1e8d244b..f63c2fac40e 100644 --- a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs +++ b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs @@ -159,7 +159,9 @@ private void InitializeDbConnection(DbConnection connection) seed: null, (decimal? max, decimal? value) => max is null ? value - : value is null ? max : decimal.Max(max.Value, value.Value), + : value is null + ? max + : decimal.Max(max.Value, value.Value), isDeterministic: true); sqliteConnection.CreateAggregate( @@ -167,7 +169,9 @@ private void InitializeDbConnection(DbConnection connection) seed: null, (decimal? min, decimal? value) => min is null ? value - : value is null ? min : decimal.Min(min.Value, value.Value), + : value is null + ? min + : decimal.Min(min.Value, value.Value), isDeterministic: true); sqliteConnection.CreateAggregate( diff --git a/src/EFCore.Sqlite.Core/Update/Internal/SqliteModificationCommand.cs b/src/EFCore.Sqlite.Core/Update/Internal/SqliteModificationCommand.cs index 0a9299687de..7bba8d00c9d 100644 --- a/src/EFCore.Sqlite.Core/Update/Internal/SqliteModificationCommand.cs +++ b/src/EFCore.Sqlite.Core/Update/Internal/SqliteModificationCommand.cs @@ -51,7 +51,7 @@ protected override void ProcessSinglePropertyJsonUpdate(ref ColumnModificationPa // Here we convert the .NET bool to a "true"/"false" string, and SqliteUpdateSqlGenerator will add the enclosing json(). if (propertyProviderClrType == typeof(bool)) { - var value = property.GetTypeMapping().Converter is ValueConverter converter + var value = property.GetTypeMapping().Converter is { } converter ? converter.ConvertToProvider(parameters.Value) : parameters.Value; diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs index 7e0e31f0ba6..ef0004dba0e 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryCollectionMemberTranslator.cs @@ -42,7 +42,7 @@ public SqliteGeometryCollectionMemberTranslator(ISqlExpressionFactory sqlExpress => Equals(member, Count) ? _sqlExpressionFactory.Function( "NumGeometries", - new[] { instance! }, + [instance!], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], returnType) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs index 5ae533f995b..61161f7415a 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMemberTranslator.cs @@ -67,21 +67,20 @@ public SqliteGeometryMemberTranslator(ISqlExpressionFactory sqlExpressionFactory { return returnType == typeof(bool) ? _sqlExpressionFactory.Case( - new[] - { + [ new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( functionName, - new[] { instance }, + [instance], nullable: false, argumentsPropagateNullability: Statics.FalseArrays[1], returnType)) - }, + ], null) : _sqlExpressionFactory.Function( functionName, - new[] { instance }, + [instance], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], returnType); @@ -92,21 +91,19 @@ public SqliteGeometryMemberTranslator(ISqlExpressionFactory sqlExpressionFactory return _sqlExpressionFactory.Case( _sqlExpressionFactory.Function( "rtrim", - new[] - { + [ _sqlExpressionFactory.Function( "GeometryType", - new[] { instance }, + [instance], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], returnType), _sqlExpressionFactory.Constant(" ZM") - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], returnType), - new[] - { + [ new CaseWhenClause(_sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant("Point")), new CaseWhenClause(_sqlExpressionFactory.Constant("LINESTRING"), _sqlExpressionFactory.Constant("LineString")), new CaseWhenClause(_sqlExpressionFactory.Constant("POLYGON"), _sqlExpressionFactory.Constant("Polygon")), @@ -117,7 +114,7 @@ public SqliteGeometryMemberTranslator(ISqlExpressionFactory sqlExpressionFactory _sqlExpressionFactory.Constant("MULTIPOLYGON"), _sqlExpressionFactory.Constant("MultiPolygon")), new CaseWhenClause( _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant("GeometryCollection")) - }, + ], null); } @@ -126,21 +123,19 @@ public SqliteGeometryMemberTranslator(ISqlExpressionFactory sqlExpressionFactory return _sqlExpressionFactory.Case( _sqlExpressionFactory.Function( "rtrim", - new[] - { + [ _sqlExpressionFactory.Function( "GeometryType", - new[] { instance }, + [instance], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(string)), _sqlExpressionFactory.Constant(" ZM") - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], typeof(string)), - new[] - { + [ new CaseWhenClause( _sqlExpressionFactory.Constant("POINT"), _sqlExpressionFactory.Constant(NetTopologySuite.Geometries.OgcGeometryType.Point)), @@ -162,7 +157,7 @@ public SqliteGeometryMemberTranslator(ISqlExpressionFactory sqlExpressionFactory new CaseWhenClause( _sqlExpressionFactory.Constant("GEOMETRYCOLLECTION"), _sqlExpressionFactory.Constant(NetTopologySuite.Geometries.OgcGeometryType.GeometryCollection)) - }, + ], null); } } diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs index d75d6ddcc74..242a5bdbcba 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteGeometryMethodTranslator.cs @@ -89,8 +89,7 @@ public SqliteGeometryMethodTranslator(ISqlExpressionFactory sqlExpressionFactory } return _sqlExpressionFactory.Case( - new[] - { + [ new CaseWhenClause( nullCheck, _sqlExpressionFactory.Function( @@ -99,7 +98,7 @@ public SqliteGeometryMethodTranslator(ISqlExpressionFactory sqlExpressionFactory nullable: false, finalArguments.Select(a => false), method.ReturnType)) - }, + ], null); } @@ -115,13 +114,12 @@ public SqliteGeometryMethodTranslator(ISqlExpressionFactory sqlExpressionFactory { return _sqlExpressionFactory.Function( "GeometryN", - new[] - { + [ instance, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], method.ReturnType); @@ -132,7 +130,7 @@ public SqliteGeometryMethodTranslator(ISqlExpressionFactory sqlExpressionFactory return _sqlExpressionFactory.LessThanOrEqual( _sqlExpressionFactory.Function( "Distance", - new[] { instance, arguments[0] }, + [instance, arguments[0]], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], typeof(double)), diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs index 0ace0963453..9429c6663ed 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMemberTranslator.cs @@ -52,21 +52,20 @@ public SqliteLineStringMemberTranslator(ISqlExpressionFactory sqlExpressionFacto { return returnType == typeof(bool) ? _sqlExpressionFactory.Case( - new[] - { + [ new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( functionName, - new[] { instance }, + [instance], nullable: false, argumentsPropagateNullability: Statics.FalseArrays[1], returnType)) - }, + ], null) : _sqlExpressionFactory.Function( functionName, - new[] { instance }, + [instance], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], returnType); diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs index 5656ca78d10..18fbad36b1a 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteLineStringMethodTranslator.cs @@ -44,13 +44,12 @@ public SqliteLineStringMethodTranslator(ISqlExpressionFactory sqlExpressionFacto { return _sqlExpressionFactory.Function( "PointN", - new[] - { + [ instance!, _sqlExpressionFactory.Add( arguments[0], _sqlExpressionFactory.Constant(1)) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], method.ReturnType); diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs index b3460716246..12f73c3973f 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteMultiLineStringMemberTranslator.cs @@ -44,17 +44,16 @@ public SqliteMultiLineStringMemberTranslator(ISqlExpressionFactory sqlExpression && instance != null) { return _sqlExpressionFactory.Case( - new[] - { + [ new CaseWhenClause( _sqlExpressionFactory.IsNotNull(instance), _sqlExpressionFactory.Function( "IsClosed", - new[] { instance }, + [instance], nullable: false, argumentsPropagateNullability: Statics.FalseArrays[1], returnType)) - }, + ], null); } diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteAggregateMethodCallTranslatorPlugin.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteAggregateMethodCallTranslatorPlugin.cs index 649deb97f34..7dc850a1e58 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteAggregateMethodCallTranslatorPlugin.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteAggregateMethodCallTranslatorPlugin.cs @@ -18,7 +18,7 @@ public class SqliteNetTopologySuiteAggregateMethodCallTranslatorPlugin : IAggreg /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public SqliteNetTopologySuiteAggregateMethodCallTranslatorPlugin(ISqlExpressionFactory sqlExpressionFactory) - => Translators = new IAggregateMethodCallTranslator[] { new SqliteNetTopologySuiteAggregateMethodTranslator(sqlExpressionFactory) }; + => Translators = [new SqliteNetTopologySuiteAggregateMethodTranslator(sqlExpressionFactory)]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteAggregateMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteAggregateMethodTranslator.cs index 200eb5b9b8d..27e02c5e6a9 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteAggregateMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteAggregateMethodTranslator.cs @@ -64,15 +64,14 @@ public SqliteNetTopologySuiteAggregateMethodTranslator(ISqlExpressionFactory sql // Spatialite has no built-in aggregate convex hull, but we can simply apply Collect beforehand return _sqlExpressionFactory.Function( "ConvexHull", - new[] - { + [ _sqlExpressionFactory.Function( "Collect", - new[] { sqlExpression }, + [sqlExpression], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[1], typeof(Geometry)) - }, + ], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], typeof(Geometry)); @@ -95,7 +94,7 @@ public SqliteNetTopologySuiteAggregateMethodTranslator(ISqlExpressionFactory sql return _sqlExpressionFactory.Function( functionName, - new[] { sqlExpression }, + [sqlExpression], nullable: true, argumentsPropagateNullability: Statics.FalseArrays[1], typeof(Geometry)); diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs index 1fd35c70226..93f35e9a497 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMemberTranslatorPlugin.cs @@ -19,15 +19,15 @@ public class SqliteNetTopologySuiteMemberTranslatorPlugin : IMemberTranslatorPlu /// public SqliteNetTopologySuiteMemberTranslatorPlugin( ISqlExpressionFactory sqlExpressionFactory) - => Translators = new IMemberTranslator[] - { + => Translators = + [ new SqliteGeometryMemberTranslator(sqlExpressionFactory), new SqliteGeometryCollectionMemberTranslator(sqlExpressionFactory), new SqliteLineStringMemberTranslator(sqlExpressionFactory), new SqliteMultiLineStringMemberTranslator(sqlExpressionFactory), new SqlitePointMemberTranslator(sqlExpressionFactory), new SqlitePolygonMemberTranslator(sqlExpressionFactory) - }; + ]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs index e763a582ddd..36d3d17f153 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqliteNetTopologySuiteMethodCallTranslatorPlugin.cs @@ -18,13 +18,13 @@ public class SqliteNetTopologySuiteMethodCallTranslatorPlugin : IMethodCallTrans /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public SqliteNetTopologySuiteMethodCallTranslatorPlugin(ISqlExpressionFactory sqlExpressionFactory) - => Translators = new IMethodCallTranslator[] - { + => Translators = + [ new SqliteGeometryMethodTranslator(sqlExpressionFactory), new SqliteGeometryCollectionMethodTranslator(sqlExpressionFactory), new SqliteLineStringMethodTranslator(sqlExpressionFactory), new SqlitePolygonMethodTranslator(sqlExpressionFactory) - }; + ]; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs index fcafbf9f608..b338d8f9b75 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePointMemberTranslator.cs @@ -47,7 +47,7 @@ public SqlitePointMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) => MemberToFunctionName.TryGetValue(member, out var functionName) ? _sqlExpressionFactory.Function( functionName, - new[] { instance! }, + [instance!], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], returnType) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs index 83d0abb0053..17a16ec2b06 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMemberTranslator.cs @@ -46,7 +46,7 @@ public SqlitePolygonMemberTranslator(ISqlExpressionFactory sqlExpressionFactory) => MemberToFunctionName.TryGetValue(member, out var functionName) ? _sqlExpressionFactory.Function( functionName, - new[] { instance! }, + [instance!], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[1], returnType) diff --git a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs index 2104f752b7c..abe96c0697a 100644 --- a/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs +++ b/src/EFCore.Sqlite.NTS/Query/Internal/SqlitePolygonMethodTranslator.cs @@ -44,7 +44,7 @@ public SqlitePolygonMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) { return _sqlExpressionFactory.Function( "InteriorRingN", - new[] { instance!, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1)) }, + [instance!, _sqlExpressionFactory.Add(arguments[0], _sqlExpressionFactory.Constant(1))], nullable: true, argumentsPropagateNullability: Statics.TrueArrays[2], method.ReturnType); diff --git a/src/EFCore.Sqlite.NTS/build/net10.0/Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite.targets b/src/EFCore.Sqlite.NTS/build/net10.0/Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite.targets index 37f11ead01c..9be2ce67b00 100644 --- a/src/EFCore.Sqlite.NTS/build/net10.0/Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite.targets +++ b/src/EFCore.Sqlite.NTS/build/net10.0/Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite.targets @@ -32,7 +32,10 @@ Outputs="$(EFCoreSqliteNetTopologySuiteFile)"> - <_Parameter1>Microsoft.EntityFrameworkCore.Sqlite.Design.Internal.SqliteNetTopologySuiteDesignTimeServices, Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite + <_Parameter1> + Microsoft.EntityFrameworkCore.Sqlite.Design.Internal.SqliteNetTopologySuiteDesignTimeServices, + Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite + <_Parameter2>Microsoft.EntityFrameworkCore.Sqlite diff --git a/src/EFCore.Tasks/EFCore.Tasks.nuspec b/src/EFCore.Tasks/EFCore.Tasks.nuspec index bd751d9589b..9bc52c09450 100644 --- a/src/EFCore.Tasks/EFCore.Tasks.nuspec +++ b/src/EFCore.Tasks/EFCore.Tasks.nuspec @@ -20,4 +20,4 @@ - + \ No newline at end of file diff --git a/src/EFCore.Tasks/Tasks/OptimizeDbContext.cs b/src/EFCore.Tasks/Tasks/OptimizeDbContext.cs index dbcafa6ad10..05ffa8615c8 100644 --- a/src/EFCore.Tasks/Tasks/OptimizeDbContext.cs +++ b/src/EFCore.Tasks/Tasks/OptimizeDbContext.cs @@ -96,7 +96,7 @@ public override bool Execute() return false; } - GeneratedFiles = Output.Split(new[] { Environment.NewLine }, StringSplitOptions.None) + GeneratedFiles = Output.Split([Environment.NewLine], StringSplitOptions.None) .Select(f => new TaskItem(f)).ToArray(); } catch (Exception e) diff --git a/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.props b/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.props index 23bf020eb75..2d467ddd27f 100644 --- a/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.props +++ b/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.props @@ -1,13 +1,17 @@ - + + <_TaskTargetFramework Condition="'$(MSBuildRuntimeType)' == 'core'">net10.0 <_TaskTargetFramework Condition="'$(MSBuildRuntimeType)' != 'core'">net472 - <_EFCustomTasksAssembly>$([MSBuild]::NormalizePath($(MSBuildThisFileDirectory), '..\tasks\$(_TaskTargetFramework)\$(MSBuildThisFileName).dll')) + <_EFCustomTasksAssembly> + $([MSBuild]::NormalizePath($(MSBuildThisFileDirectory), + '..\tasks\$(_TaskTargetFramework)\$(MSBuildThisFileName).dll')) + publish publish * - + \ No newline at end of file diff --git a/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.targets b/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.targets index 759688a46c7..ce2f7cf90a5 100644 --- a/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.targets +++ b/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.targets @@ -1,10 +1,14 @@ - + + <_FullOutputPath>$([MSBuild]::NormalizePath('$(MSBuildProjectDirectory)', '$(OutputPath)')) <_FullIntermediateOutputPath>$([MSBuild]::NormalizePath('$(MSBuildProjectDirectory)', '$(IntermediateOutputPath)')) - <_FullIntermediateOutputPath Condition="'$(AppendRuntimeIdentifierToOutputPath)' == 'true' And '$(RuntimeIdentifier)' != '' And '$(_UsingDefaultRuntimeIdentifier)' != 'true' And '$(UseArtifactsIntermediateOutput)' != 'true'">$([MSBuild]::NormalizePath('$(_FullIntermediateOutputPath)', '../')) + <_FullIntermediateOutputPath Condition="'$(AppendRuntimeIdentifierToOutputPath)' == 'true' And '$(RuntimeIdentifier)' != '' And '$(_UsingDefaultRuntimeIdentifier)' != 'true' And '$(UseArtifactsIntermediateOutput)' != 'true'"> + $([MSBuild]::NormalizePath('$(_FullIntermediateOutputPath)', + '../')) + $(_FullIntermediateOutputPath)$(AssemblyName).EFGeneratedSources.Build.txt $(_FullIntermediateOutputPath)$(AssemblyName).EFGeneratedSources.Publish.txt <_AssemblyFullName>$(_FullOutputPath)$(AssemblyName).dll @@ -115,24 +119,24 @@ For Publish: + Condition="'$(_EFGenerationStage)'=='build'" /> + Condition="'$(_EFGenerationStage)'=='publish'" /> + Condition="'$(_EFGenerationStage)'=='build'" /> + Condition="'$(_EFGenerationStage)'=='publish'" /> - + + Text="If %24(EFScaffoldModelStage) is set to 'publish' then %24(EFPrecompileQueriesStage) must also be set to 'publish'." /> @@ -140,11 +144,11 @@ For Publish: BeforeTargets="_EFProcessGeneratedFiles;_EFCleanGeneratedFiles"> - + - + @@ -212,7 +216,7 @@ For Publish: Condition="'%(_MSBuildProjectReferenceExistent.BuildReference)' == 'true' and '@(ProjectReferenceWithConfiguration)' != '' " ContinueOnError="$(ContinueOnError)" SkipNonexistentTargets="true" - RemoveProperties="%(_MSBuildProjectReferenceExistent.GlobalPropertiesToRemove)$(_GlobalPropertiesToRemoveFromProjectReferences)"/> + RemoveProperties="%(_MSBuildProjectReferenceExistent.GlobalPropertiesToRemove)$(_GlobalPropertiesToRemoveFromProjectReferences)" /> diff --git a/src/EFCore.Tools/EFCore.Tools.nuspec b/src/EFCore.Tools/EFCore.Tools.nuspec index 0048a2705c0..1f664c557c2 100644 --- a/src/EFCore.Tools/EFCore.Tools.nuspec +++ b/src/EFCore.Tools/EFCore.Tools.nuspec @@ -25,4 +25,4 @@ - + \ No newline at end of file diff --git a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs index 58d4cbff5b3..087fb8e7410 100644 --- a/src/EFCore/Extensions/Internal/ExpressionExtensions.cs +++ b/src/EFCore/Extensions/Internal/ExpressionExtensions.cs @@ -1,9 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - - // ReSharper disable once CheckNamespace + namespace Microsoft.EntityFrameworkCore.Internal; /// diff --git a/src/Microsoft.Data.Sqlite.Core/Extensions/SQLitePCLExtensions.cs b/src/Microsoft.Data.Sqlite.Core/Extensions/SQLitePCLExtensions.cs index c854b8f837a..452ca0e596c 100644 --- a/src/Microsoft.Data.Sqlite.Core/Extensions/SQLitePCLExtensions.cs +++ b/src/Microsoft.Data.Sqlite.Core/Extensions/SQLitePCLExtensions.cs @@ -5,30 +5,29 @@ // ReSharper disable once CheckNamespace // ReSharper disable InconsistentNaming -namespace SQLitePCL +namespace SQLitePCL; + +internal static class SQLitePCLExtensions { - internal static class SQLitePCLExtensions + private static readonly Dictionary _knownLibraries = new() { - private static readonly Dictionary _knownLibraries = new() - { - { "e_sqlcipher", true }, - { "e_sqlite3", false }, - { "e_sqlite3mc", true }, - { "sqlcipher", true }, - { "sqlite3mc", true }, - { "winsqlite3", false } - }; + { "e_sqlcipher", true }, + { "e_sqlite3", false }, + { "e_sqlite3mc", true }, + { "sqlcipher", true }, + { "sqlite3mc", true }, + { "winsqlite3", false } + }; - public static bool? EncryptionSupported() - => EncryptionSupported(out _); + public static bool? EncryptionSupported() + => EncryptionSupported(out _); - public static bool? EncryptionSupported(out string libraryName) - { - libraryName = raw.GetNativeLibraryName(); + public static bool? EncryptionSupported(out string libraryName) + { + libraryName = raw.GetNativeLibraryName(); - return _knownLibraries.TryGetValue(libraryName, out var supported) - ? supported - : default(bool?); - } + return _knownLibraries.TryGetValue(libraryName, out var supported) + ? supported + : default(bool?); } } diff --git a/src/Microsoft.Data.Sqlite.Core/Extensions/SqliteConnectionExtensions.cs b/src/Microsoft.Data.Sqlite.Core/Extensions/SqliteConnectionExtensions.cs index 962fd020807..a658d2b7540 100644 --- a/src/Microsoft.Data.Sqlite.Core/Extensions/SqliteConnectionExtensions.cs +++ b/src/Microsoft.Data.Sqlite.Core/Extensions/SqliteConnectionExtensions.cs @@ -3,38 +3,37 @@ // ReSharper disable once CheckNamespace -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +internal static class SqliteConnectionExtensions { - internal static class SqliteConnectionExtensions + public static int ExecuteNonQuery( + this SqliteConnection connection, + string commandText, + params SqliteParameter[] parameters) { - public static int ExecuteNonQuery( - this SqliteConnection connection, - string commandText, - params SqliteParameter[] parameters) - { - using var command = connection.CreateCommand(); - command.CommandText = commandText; - command.Parameters.AddRange(parameters); + using var command = connection.CreateCommand(); + command.CommandText = commandText; + command.Parameters.AddRange(parameters); - return command.ExecuteNonQuery(); - } + return command.ExecuteNonQuery(); + } - public static T ExecuteScalar( - this SqliteConnection connection, - string commandText, - params SqliteParameter[] parameters) - => (T)connection.ExecuteScalar(commandText, parameters)!; + public static T ExecuteScalar( + this SqliteConnection connection, + string commandText, + params SqliteParameter[] parameters) + => (T)connection.ExecuteScalar(commandText, parameters)!; - private static object? ExecuteScalar( - this SqliteConnection connection, - string commandText, - params SqliteParameter[] parameters) - { - using var command = connection.CreateCommand(); - command.CommandText = commandText; - command.Parameters.AddRange(parameters); + private static object? ExecuteScalar( + this SqliteConnection connection, + string commandText, + params SqliteParameter[] parameters) + { + using var command = connection.CreateCommand(); + command.CommandText = commandText; + command.Parameters.AddRange(parameters); - return command.ExecuteScalar(); - } + return command.ExecuteScalar(); } } diff --git a/src/Microsoft.Data.Sqlite.Core/Extensions/TypeExtensions.cs b/src/Microsoft.Data.Sqlite.Core/Extensions/TypeExtensions.cs index de3a197fb11..03916df6aff 100644 --- a/src/Microsoft.Data.Sqlite.Core/Extensions/TypeExtensions.cs +++ b/src/Microsoft.Data.Sqlite.Core/Extensions/TypeExtensions.cs @@ -2,14 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // ReSharper disable once CheckNamespace -namespace System + +namespace System; + +internal static class TypeExtensions { - internal static class TypeExtensions - { - public static Type UnwrapEnumType(this Type type) - => type.IsEnum ? Enum.GetUnderlyingType(type) : type; - - public static Type UnwrapNullableType(this Type type) - => Nullable.GetUnderlyingType(type) ?? type; - } + public static Type UnwrapEnumType(this Type type) + => type.IsEnum ? Enum.GetUnderlyingType(type) : type; + + public static Type UnwrapNullableType(this Type type) + => Nullable.GetUnderlyingType(type) ?? type; } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteBlob.cs b/src/Microsoft.Data.Sqlite.Core/SqliteBlob.cs index bbcb2a263ef..641e05dac57 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteBlob.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteBlob.cs @@ -8,345 +8,344 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Provides methods to access the contents of a blob. +/// +/// BLOB I/O +public class SqliteBlob : Stream { + private sqlite3_blob? _blob; + private readonly SqliteConnection _connection; + private long _position; + /// - /// Provides methods to access the contents of a blob. + /// Initializes a new instance of the class. /// + /// An open connection to the database. + /// The name of table containing the blob. + /// The name of the column containing the blob. + /// The rowid of the row containing the blob. + /// A value indicating whether the blob is read-only. /// BLOB I/O - public class SqliteBlob : Stream + public SqliteBlob( + SqliteConnection connection, + string tableName, + string columnName, + long rowid, + bool readOnly = false) + : this(connection, SqliteConnection.MainDatabaseName, tableName, columnName, rowid, readOnly) { - private sqlite3_blob? _blob; - private readonly SqliteConnection _connection; - private long _position; - - /// - /// Initializes a new instance of the class. - /// - /// An open connection to the database. - /// The name of table containing the blob. - /// The name of the column containing the blob. - /// The rowid of the row containing the blob. - /// A value indicating whether the blob is read-only. - /// BLOB I/O - public SqliteBlob( - SqliteConnection connection, - string tableName, - string columnName, - long rowid, - bool readOnly = false) - : this(connection, SqliteConnection.MainDatabaseName, tableName, columnName, rowid, readOnly) + } + + /// + /// Initializes a new instance of the class. + /// + /// An open connection to the database. + /// The name of the attached database containing the blob. + /// The name of table containing the blob. + /// The name of the column containing the blob. + /// The rowid of the row containing the blob. + /// A value indicating whether the blob is read-only. + /// BLOB I/O + public SqliteBlob( + SqliteConnection connection, + string databaseName, + string tableName, + string columnName, + long rowid, + bool readOnly = false) + { + if (connection?.State != ConnectionState.Open) { + throw new InvalidOperationException(Resources.SqlBlobRequiresOpenConnection); } - /// - /// Initializes a new instance of the class. - /// - /// An open connection to the database. - /// The name of the attached database containing the blob. - /// The name of table containing the blob. - /// The name of the column containing the blob. - /// The rowid of the row containing the blob. - /// A value indicating whether the blob is read-only. - /// BLOB I/O - public SqliteBlob( - SqliteConnection connection, - string databaseName, - string tableName, - string columnName, - long rowid, - bool readOnly = false) + if (tableName is null) { - if (connection?.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.SqlBlobRequiresOpenConnection); - } + throw new ArgumentNullException(nameof(tableName)); + } - if (tableName is null) - { - throw new ArgumentNullException(nameof(tableName)); - } + if (columnName is null) + { + throw new ArgumentNullException(nameof(columnName)); + } - if (columnName is null) - { - throw new ArgumentNullException(nameof(columnName)); - } + _connection = connection; + CanWrite = !readOnly; + var rc = sqlite3_blob_open( + _connection.Handle, + databaseName, + tableName, + columnName, + rowid, + readOnly ? 0 : 1, + out _blob); + SqliteException.ThrowExceptionForRC(rc, _connection.Handle); + Length = sqlite3_blob_bytes(_blob); + } - _connection = connection; - CanWrite = !readOnly; - var rc = sqlite3_blob_open( - _connection.Handle, - databaseName, - tableName, - columnName, - rowid, - readOnly ? 0 : 1, - out _blob); - SqliteException.ThrowExceptionForRC(rc, _connection.Handle); - Length = sqlite3_blob_bytes(_blob); - } + /// + /// Gets a value indicating whether the current stream supports reading. + /// Always true. + /// + /// if the stream supports reading; otherwise, . + public override bool CanRead + => true; - /// - /// Gets a value indicating whether the current stream supports reading. - /// Always true. - /// - /// if the stream supports reading; otherwise, . - public override bool CanRead - => true; - - /// - /// Gets a value indicating whether the current stream supports writing. - /// - /// if the stream supports writing; otherwise, . - public override bool CanWrite { get; } - - /// - /// Gets a value indicating whether the current stream supports seeking. - /// Always true. - /// - /// if the stream supports seeking; otherwise, . - public override bool CanSeek - => true; - - /// - /// Gets the length in bytes of the stream. - /// - /// A long value representing the length of the stream in bytes. - public override long Length { get; } - - /// - /// Gets or sets the position within the current stream. - /// - /// The current position within the stream. - public override long Position - { - get => _position; - set - { - if (value < 0) - { - // NB: Message is provided by the framework - throw new ArgumentOutOfRangeException(nameof(value), value, message: null); - } + /// + /// Gets a value indicating whether the current stream supports writing. + /// + /// if the stream supports writing; otherwise, . + public override bool CanWrite { get; } - _position = value; - } - } + /// + /// Gets a value indicating whether the current stream supports seeking. + /// Always true. + /// + /// if the stream supports seeking; otherwise, . + public override bool CanSeek + => true; - /// - /// Reads a sequence of bytes from the current stream and advances the position - /// within the stream by the number of bytes read. - /// - /// - /// An array of bytes. When this method returns, the buffer contains the specified byte array - /// with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. - /// - /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. - /// The maximum number of bytes to be read from the current stream. - /// The total number of bytes read into the buffer. - public override int Read(byte[] buffer, int offset, int count) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } + /// + /// Gets the length in bytes of the stream. + /// + /// A long value representing the length of the stream in bytes. + public override long Length { get; } - if (offset < 0) + /// + /// Gets or sets the position within the current stream. + /// + /// The current position within the stream. + public override long Position + { + get => _position; + set + { + if (value < 0) { // NB: Message is provided by the framework - throw new ArgumentOutOfRangeException(nameof(offset), offset, message: null); + throw new ArgumentOutOfRangeException(nameof(value), value, message: null); } - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), count, message: null); - } + _position = value; + } + } - if (offset + count > buffer.Length) - { - throw new ArgumentException(Resources.InvalidOffsetAndCount); - } + /// + /// Reads a sequence of bytes from the current stream and advances the position + /// within the stream by the number of bytes read. + /// + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array + /// with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// The total number of bytes read into the buffer. + public override int Read(byte[] buffer, int offset, int count) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + if (offset < 0) + { + // NB: Message is provided by the framework + throw new ArgumentOutOfRangeException(nameof(offset), offset, message: null); + } - return Read(buffer.AsSpan(offset, count)); + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), count, message: null); + } + + if (offset + count > buffer.Length) + { + throw new ArgumentException(Resources.InvalidOffsetAndCount); } - /// - /// Reads a sequence of bytes from the current stream and advances the position within the stream by the - /// number of bytes read. - /// - /// - /// A region of memory. When this method returns, the contents of this region are replaced by the bytes read - /// from the current source. - /// - /// - /// The total number of bytes read into the buffer. This can be less than the number of bytes allocated in - /// the buffer if that many bytes are not currently available, or zero (0) if the end of the stream has been - /// reached. - /// + return Read(buffer.AsSpan(offset, count)); + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the + /// number of bytes read. + /// + /// + /// A region of memory. When this method returns, the contents of this region are replaced by the bytes read + /// from the current source. + /// + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes allocated in + /// the buffer if that many bytes are not currently available, or zero (0) if the end of the stream has been + /// reached. + /// #if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER - public override int Read(Span buffer) + public override int Read(Span buffer) #else public virtual int Read(Span buffer) #endif + { + if (_blob == null) { - if (_blob == null) - { - throw new ObjectDisposedException(objectName: null); - } - - var position = _position; - if (position > Length) - { - position = Length; - } - - var count = buffer.Length; - if (position + count > Length) - { - count = (int)(Length - position); - } + throw new ObjectDisposedException(objectName: null); + } - var rc = sqlite3_blob_read(_blob, buffer.Slice(0, count), (int)position); - SqliteException.ThrowExceptionForRC(rc, _connection.Handle); - _position += count; - return count; + var position = _position; + if (position > Length) + { + position = Length; } - /// - /// Writes a sequence of bytes to the current stream and advances the current position - /// within this stream by the number of bytes written. - /// - /// An array of bytes. This method copies count bytes from buffer to the current stream. - /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. - /// The number of bytes to be written to the current stream. - public override void Write(byte[] buffer, int offset, int count) + var count = buffer.Length; + if (position + count > Length) { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } + count = (int)(Length - position); + } - if (offset < 0) - { - // NB: Message is provided by the framework - throw new ArgumentOutOfRangeException(nameof(offset), offset, message: null); - } + var rc = sqlite3_blob_read(_blob, buffer.Slice(0, count), (int)position); + SqliteException.ThrowExceptionForRC(rc, _connection.Handle); + _position += count; + return count; + } - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), count, message: null); - } + /// + /// Writes a sequence of bytes to the current stream and advances the current position + /// within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + public override void Write(byte[] buffer, int offset, int count) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } - if (offset + count > buffer.Length) - { - throw new ArgumentException(Resources.InvalidOffsetAndCount); - } + if (offset < 0) + { + // NB: Message is provided by the framework + throw new ArgumentOutOfRangeException(nameof(offset), offset, message: null); + } - if (_blob == null) - { - throw new ObjectDisposedException(objectName: null); - } + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), count, message: null); + } - Write(buffer.AsSpan(offset, count)); + if (offset + count > buffer.Length) + { + throw new ArgumentException(Resources.InvalidOffsetAndCount); } - /// - /// Writes a sequence of bytes to the current stream and advances the current position within this stream by - /// the number of bytes written. - /// - /// - /// A region of memory. This method copies the contents of this region to the current stream. - /// + if (_blob == null) + { + throw new ObjectDisposedException(objectName: null); + } + + Write(buffer.AsSpan(offset, count)); + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by + /// the number of bytes written. + /// + /// + /// A region of memory. This method copies the contents of this region to the current stream. + /// #if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER - public override void Write(ReadOnlySpan buffer) + public override void Write(ReadOnlySpan buffer) #else public virtual void Write(ReadOnlySpan buffer) #endif + { + if (!CanWrite) { - if (!CanWrite) - { - throw new NotSupportedException(Resources.WriteNotSupported); - } - - var position = _position; - if (position > Length) - { - position = Length; - } - - var count = buffer.Length; - if (position + count > Length) - { - throw new NotSupportedException(Resources.ResizeNotSupported); - } + throw new NotSupportedException(Resources.WriteNotSupported); + } - var rc = sqlite3_blob_write(_blob, buffer.Slice(0, count), (int)position); - SqliteException.ThrowExceptionForRC(rc, _connection.Handle); - _position += count; + var position = _position; + if (position > Length) + { + position = Length; } - /// - /// Sets the position within the current stream. - /// - /// A byte offset relative to the origin parameter. - /// A value indicating the reference point used to obtain the new position. - /// The new position within the current stream. - public override long Seek(long offset, SeekOrigin origin) + var count = buffer.Length; + if (position + count > Length) { - long position; - switch (origin) - { - case SeekOrigin.Begin: - position = offset; - break; - case SeekOrigin.Current: - position = _position + offset; - break; - case SeekOrigin.End: - position = Length + offset; - break; - default: - throw new ArgumentException(Resources.InvalidEnumValue(typeof(SeekOrigin), origin), nameof(origin)); - } + throw new NotSupportedException(Resources.ResizeNotSupported); + } - if (position < 0) - { - throw new IOException(Resources.SeekBeforeBegin); - } + var rc = sqlite3_blob_write(_blob, buffer.Slice(0, count), (int)position); + SqliteException.ThrowExceptionForRC(rc, _connection.Handle); + _position += count; + } - return _position = position; + /// + /// Sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value indicating the reference point used to obtain the new position. + /// The new position within the current stream. + public override long Seek(long offset, SeekOrigin origin) + { + long position; + switch (origin) + { + case SeekOrigin.Begin: + position = offset; + break; + case SeekOrigin.Current: + position = _position + offset; + break; + case SeekOrigin.End: + position = Length + offset; + break; + default: + throw new ArgumentException(Resources.InvalidEnumValue(typeof(SeekOrigin), origin), nameof(origin)); } - /// - /// Releases any resources used by the blob and closes it. - /// - /// - /// true to release managed and unmanaged resources; to release only unmanaged resources. - /// - protected override void Dispose(bool disposing) + if (position < 0) { - if (_blob != null) - { - _blob.Dispose(); - _blob = null; - } + throw new IOException(Resources.SeekBeforeBegin); } - /// - /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. - /// Does nothing. - /// - public override void Flush() + return _position = position; + } + + /// + /// Releases any resources used by the blob and closes it. + /// + /// + /// true to release managed and unmanaged resources; to release only unmanaged resources. + /// + protected override void Dispose(bool disposing) + { + if (_blob != null) { + _blob.Dispose(); + _blob = null; } + } - /// - /// Sets the length of the current stream. This is not supported by sqlite blobs. - /// Not supported. - /// - /// The desired length of the current stream in bytes. - /// Always. - public override void SetLength(long value) - => throw new NotSupportedException(Resources.ResizeNotSupported); + /// + /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. + /// Does nothing. + /// + public override void Flush() + { } + + /// + /// Sets the length of the current stream. This is not supported by sqlite blobs. + /// Not supported. + /// + /// The desired length of the current stream in bytes. + /// Always. + public override void SetLength(long value) + => throw new NotSupportedException(Resources.ResizeNotSupported); } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteCacheMode.cs b/src/Microsoft.Data.Sqlite.Core/SqliteCacheMode.cs index 7badfe965c2..cd919bf23f8 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteCacheMode.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteCacheMode.cs @@ -1,28 +1,27 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Represents the caching modes that can be used when creating a new . +/// +public enum SqliteCacheMode { /// - /// Represents the caching modes that can be used when creating a new . + /// Default mode. /// - public enum SqliteCacheMode - { - /// - /// Default mode. - /// - Default, + Default, - /// - /// Private-cache mode. Each connection uses a private cache. - /// - Private, + /// + /// Private-cache mode. Each connection uses a private cache. + /// + Private, - /// - /// Shared-cache mode. Connections share a cache. This mode can change the behavior of transaction and table - /// locking. - /// - /// SQLite Shared-Cache Mode - Shared - } + /// + /// Shared-cache mode. Connections share a cache. This mode can change the behavior of transaction and table + /// locking. + /// + /// SQLite Shared-Cache Mode + Shared } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteCommand.cs b/src/Microsoft.Data.Sqlite.Core/SqliteCommand.cs index bf195df29ee..01b3eed8555 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteCommand.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteCommand.cs @@ -15,533 +15,530 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Represents a SQL statement to be executed against a SQLite database. +/// +/// Batching +/// Database Errors +/// Async Limitations +public class SqliteCommand : DbCommand { + private SqliteParameterCollection? _parameters; + + private readonly List<(sqlite3_stmt Statement, int ParamCount)> _preparedStatements = new(1); + private SqliteConnection? _connection; + private string _commandText = string.Empty; + private bool _prepared; + private int? _commandTimeout; + /// - /// Represents a SQL statement to be executed against a SQLite database. + /// Initializes a new instance of the class. /// - /// Batching - /// Database Errors - /// Async Limitations - public class SqliteCommand : DbCommand + public SqliteCommand() { - private SqliteParameterCollection? _parameters; - - private readonly List<(sqlite3_stmt Statement, int ParamCount)> _preparedStatements = new(1); - private SqliteConnection? _connection; - private string _commandText = string.Empty; - private bool _prepared; - private int? _commandTimeout; - - /// - /// Initializes a new instance of the class. - /// - public SqliteCommand() - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// The SQL to execute against the database. - public SqliteCommand(string? commandText) - => CommandText = commandText; - - /// - /// Initializes a new instance of the class. - /// - /// The SQL to execute against the database. - /// The connection used by the command. - public SqliteCommand(string? commandText, SqliteConnection? connection) - : this(commandText) - { - Connection = connection; - } + /// + /// Initializes a new instance of the class. + /// + /// The SQL to execute against the database. + public SqliteCommand(string? commandText) + => CommandText = commandText; + + /// + /// Initializes a new instance of the class. + /// + /// The SQL to execute against the database. + /// The connection used by the command. + public SqliteCommand(string? commandText, SqliteConnection? connection) + : this(commandText) + => Connection = connection; - /// - /// Initializes a new instance of the class. - /// - /// The SQL to execute against the database. - /// The connection used by the command. - /// The transaction within which the command executes. - public SqliteCommand(string? commandText, SqliteConnection? connection, SqliteTransaction? transaction) - : this(commandText, connection) - => Transaction = transaction; - - /// - /// Gets or sets a value indicating how is interpreted. Only - /// is supported. - /// - /// A value indicating how is interpreted. - public override CommandType CommandType + /// + /// Initializes a new instance of the class. + /// + /// The SQL to execute against the database. + /// The connection used by the command. + /// The transaction within which the command executes. + public SqliteCommand(string? commandText, SqliteConnection? connection, SqliteTransaction? transaction) + : this(commandText, connection) + => Transaction = transaction; + + /// + /// Gets or sets a value indicating how is interpreted. Only + /// is supported. + /// + /// A value indicating how is interpreted. + public override CommandType CommandType + { + get => CommandType.Text; + set { - get => CommandType.Text; - set + if (value != CommandType.Text) { - if (value != CommandType.Text) - { - throw new ArgumentException(Resources.InvalidCommandType(value)); - } + throw new ArgumentException(Resources.InvalidCommandType(value)); } } + } - /// - /// Gets or sets the SQL to execute against the database. - /// - /// The SQL to execute against the database. - /// Batching - [AllowNull] - public override string CommandText + /// + /// Gets or sets the SQL to execute against the database. + /// + /// The SQL to execute against the database. + /// Batching + [AllowNull] + public override string CommandText + { + get => _commandText; + set { - get => _commandText; - set + if (DataReader != null) { - if (DataReader != null) - { - throw new InvalidOperationException(Resources.SetRequiresNoOpenReader(nameof(CommandText))); - } + throw new InvalidOperationException(Resources.SetRequiresNoOpenReader(nameof(CommandText))); + } - if (value != _commandText) - { - DisposePreparedStatements(); - _commandText = value ?? string.Empty; - } + if (value != _commandText) + { + DisposePreparedStatements(); + _commandText = value ?? string.Empty; } } + } - /// - /// Gets or sets the connection used by the command. - /// - /// The connection used by the command. - public new virtual SqliteConnection? Connection + /// + /// Gets or sets the connection used by the command. + /// + /// The connection used by the command. + public new virtual SqliteConnection? Connection + { + get => _connection; + set { - get => _connection; - set + if (DataReader != null) { - if (DataReader != null) - { - throw new InvalidOperationException(Resources.SetRequiresNoOpenReader(nameof(Connection))); - } + throw new InvalidOperationException(Resources.SetRequiresNoOpenReader(nameof(Connection))); + } - if (value != _connection) - { - DisposePreparedStatements(); + if (value != _connection) + { + DisposePreparedStatements(); - _connection?.RemoveCommand(this); - _connection = value; - value?.AddCommand(this); - } + _connection?.RemoveCommand(this); + _connection = value; + value?.AddCommand(this); } } + } + + /// + /// Gets or sets the connection used by the command. Must be a . + /// + /// The connection used by the command. + protected override DbConnection? DbConnection + { + get => Connection; + set => Connection = (SqliteConnection?)value; + } + + /// + /// Gets or sets the transaction within which the command executes. + /// + /// The transaction within which the command executes. + public new virtual SqliteTransaction? Transaction { get; set; } + + /// + /// Gets or sets the transaction within which the command executes. Must be a . + /// + /// The transaction within which the command executes. + protected override DbTransaction? DbTransaction + { + get => Transaction; + set => Transaction = (SqliteTransaction?)value; + } + + /// + /// Gets the collection of parameters used by the command. + /// + /// The collection of parameters used by the command. + /// Parameters + public new virtual SqliteParameterCollection Parameters + => _parameters ??= []; + + /// + /// Gets the collection of parameters used by the command. + /// + /// The collection of parameters used by the command. + protected override DbParameterCollection DbParameterCollection + => Parameters; + + /// + /// Gets or sets the number of seconds to wait before terminating the attempt to execute the command. + /// Defaults to 30. A value of 0 means no timeout. + /// + /// The number of seconds to wait before terminating the attempt to execute the command. + /// + /// The timeout is used when the command is waiting to obtain a lock on the table. + /// + /// Database Errors + public override int CommandTimeout + { + get => _commandTimeout ?? _connection?.DefaultTimeout ?? 30; + set => _commandTimeout = value; + } - /// - /// Gets or sets the connection used by the command. Must be a . - /// - /// The connection used by the command. - protected override DbConnection? DbConnection + /// + /// Gets or sets a value indicating whether the command should be visible in an interface control. + /// + /// A value indicating whether the command should be visible in an interface control. + public override bool DesignTimeVisible { get; set; } + + /// + /// Gets or sets a value indicating how the results are applied to the row being updated. + /// + /// A value indicating how the results are applied to the row being updated. + public override UpdateRowSource UpdatedRowSource { get; set; } + + /// + /// Gets or sets the data reader currently being used by the command, or null if none. + /// + /// The data reader currently being used by the command. + protected internal virtual SqliteDataReader? DataReader { get; set; } + + /// + /// Releases any resources used by the connection and closes it. + /// + /// + /// to release managed and unmanaged resources; + /// to release only unmanaged resources. + /// + protected override void Dispose(bool disposing) + { + DisposePreparedStatements(disposing); + + if (disposing) { - get => Connection; - set => Connection = (SqliteConnection?)value; + _connection?.RemoveCommand(this); } - /// - /// Gets or sets the transaction within which the command executes. - /// - /// The transaction within which the command executes. - public new virtual SqliteTransaction? Transaction { get; set; } - - /// - /// Gets or sets the transaction within which the command executes. Must be a . - /// - /// The transaction within which the command executes. - protected override DbTransaction? DbTransaction + base.Dispose(disposing); + } + + /// + /// Creates a new parameter. + /// + /// The new parameter. + public new virtual SqliteParameter CreateParameter() + => new(); + + /// + /// Creates a new parameter. + /// + /// The new parameter. + protected override DbParameter CreateDbParameter() + => CreateParameter(); + + /// + /// Creates a prepared version of the command on the database. + /// + public override void Prepare() + { + if (_connection?.State != ConnectionState.Open) { - get => Transaction; - set => Transaction = (SqliteTransaction?)value; + throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(Prepare))); } - /// - /// Gets the collection of parameters used by the command. - /// - /// The collection of parameters used by the command. - /// Parameters - public new virtual SqliteParameterCollection Parameters - => _parameters ??= []; - - /// - /// Gets the collection of parameters used by the command. - /// - /// The collection of parameters used by the command. - protected override DbParameterCollection DbParameterCollection - => Parameters; - - /// - /// Gets or sets the number of seconds to wait before terminating the attempt to execute the command. - /// Defaults to 30. A value of 0 means no timeout. - /// - /// The number of seconds to wait before terminating the attempt to execute the command. - /// - /// The timeout is used when the command is waiting to obtain a lock on the table. - /// - /// Database Errors - public override int CommandTimeout + if (_prepared) { - get => _commandTimeout ?? _connection?.DefaultTimeout ?? 30; - set => _commandTimeout = value; + return; } - /// - /// Gets or sets a value indicating whether the command should be visible in an interface control. - /// - /// A value indicating whether the command should be visible in an interface control. - public override bool DesignTimeVisible { get; set; } - - /// - /// Gets or sets a value indicating how the results are applied to the row being updated. - /// - /// A value indicating how the results are applied to the row being updated. - public override UpdateRowSource UpdatedRowSource { get; set; } - - /// - /// Gets or sets the data reader currently being used by the command, or null if none. - /// - /// The data reader currently being used by the command. - protected internal virtual SqliteDataReader? DataReader { get; set; } - - /// - /// Releases any resources used by the connection and closes it. - /// - /// - /// to release managed and unmanaged resources; - /// to release only unmanaged resources. - /// - protected override void Dispose(bool disposing) + using var enumerator = PrepareAndEnumerateStatements().GetEnumerator(); + while (enumerator.MoveNext()) { - DisposePreparedStatements(disposing); + } + } - if (disposing) - { - _connection?.RemoveCommand(this); - } + /// + /// Executes the against the database and returns a data reader. + /// + /// The data reader. + /// A SQLite error occurs during execution. + /// Database Errors + /// Batching + public new virtual SqliteDataReader ExecuteReader() + => ExecuteReader(CommandBehavior.Default); - base.Dispose(disposing); + /// + /// Executes the against the database and returns a data reader. + /// + /// A description of the results of the query and its effect on the database. + /// The data reader. + /// A SQLite error occurs during execution. + /// Database Errors + /// Batching + public new virtual SqliteDataReader ExecuteReader(CommandBehavior behavior) + { + if (DataReader != null) + { + throw new InvalidOperationException(Resources.DataReaderOpen); } - /// - /// Creates a new parameter. - /// - /// The new parameter. - public new virtual SqliteParameter CreateParameter() - => new(); - - /// - /// Creates a new parameter. - /// - /// The new parameter. - protected override DbParameter CreateDbParameter() - => CreateParameter(); - - /// - /// Creates a prepared version of the command on the database. - /// - public override void Prepare() + if (_connection?.State != ConnectionState.Open) { - if (_connection?.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(Prepare))); - } - - if (_prepared) - { - return; - } - - using var enumerator = PrepareAndEnumerateStatements().GetEnumerator(); - while (enumerator.MoveNext()) - { - } + throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteReader))); } - /// - /// Executes the against the database and returns a data reader. - /// - /// The data reader. - /// A SQLite error occurs during execution. - /// Database Errors - /// Batching - public new virtual SqliteDataReader ExecuteReader() - => ExecuteReader(CommandBehavior.Default); - - /// - /// Executes the against the database and returns a data reader. - /// - /// A description of the results of the query and its effect on the database. - /// The data reader. - /// A SQLite error occurs during execution. - /// Database Errors - /// Batching - public new virtual SqliteDataReader ExecuteReader(CommandBehavior behavior) + if (Transaction != _connection.Transaction) { - if (DataReader != null) - { - throw new InvalidOperationException(Resources.DataReaderOpen); - } - - if (_connection?.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteReader))); - } - - if (Transaction != _connection.Transaction) - { - throw new InvalidOperationException( - Transaction == null - ? Resources.TransactionRequired - : Resources.TransactionConnectionMismatch); - } + throw new InvalidOperationException( + Transaction == null + ? Resources.TransactionRequired + : Resources.TransactionConnectionMismatch); + } - if (_connection.Transaction?.ExternalRollback == true) - { - throw new InvalidOperationException(Resources.TransactionCompleted); - } + if (_connection.Transaction?.ExternalRollback == true) + { + throw new InvalidOperationException(Resources.TransactionCompleted); + } - var closeConnection = behavior.HasFlag(CommandBehavior.CloseConnection); + var closeConnection = behavior.HasFlag(CommandBehavior.CloseConnection); - var dataReader = new SqliteDataReader(this, GetStatements(), closeConnection); - dataReader.NextResult(); + var dataReader = new SqliteDataReader(this, GetStatements(), closeConnection); + dataReader.NextResult(); - return DataReader = dataReader; - } + return DataReader = dataReader; + } - private IEnumerable GetStatements() + private IEnumerable GetStatements() + { + foreach (var (stmt, expectedParams) in !_prepared + ? PrepareAndEnumerateStatements() + : _preparedStatements) { - foreach ((var stmt, var expectedParams) in !_prepared - ? PrepareAndEnumerateStatements() - : _preparedStatements) - { - var boundParams = _parameters?.Bind(stmt, Connection!.Handle!) ?? 0; + var boundParams = _parameters?.Bind(stmt, Connection!.Handle!) ?? 0; - if (expectedParams != boundParams) + if (expectedParams != boundParams) + { + var unboundParams = new List(); + for (var i = 1; i <= expectedParams; i++) { - var unboundParams = new List(); - for (var i = 1; i <= expectedParams; i++) - { - var name = sqlite3_bind_parameter_name(stmt, i).utf8_to_string(); - - if (_parameters != null - && !_parameters.Cast().Any(p => p.ParameterName == name)) - { - unboundParams.Add(name); - } - } + var name = sqlite3_bind_parameter_name(stmt, i).utf8_to_string(); - if (sqlite3_libversion_number() < 3028000 || sqlite3_stmt_isexplain(stmt) == 0) + if (_parameters != null + && !_parameters.Cast().Any(p => p.ParameterName == name)) { - throw new InvalidOperationException(Resources.MissingParameters(string.Join(", ", unboundParams))); + unboundParams.Add(name); } } - yield return stmt; + if (sqlite3_libversion_number() < 3028000 || sqlite3_stmt_isexplain(stmt) == 0) + { + throw new InvalidOperationException(Resources.MissingParameters(string.Join(", ", unboundParams))); + } } + + yield return stmt; } + } - /// - /// Executes the against the database and returns a data reader. - /// - /// A description of query's results and its effect on the database. - /// The data reader. - protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) - => ExecuteReader(behavior); - - /// - /// Executes the asynchronously against the database and returns a data reader. - /// - /// A task representing the asynchronous operation. - /// Async Limitations - /// Batching - /// Database Errors - public new virtual Task ExecuteReaderAsync() - => ExecuteReaderAsync(CommandBehavior.Default, CancellationToken.None); - - /// - /// Executes the asynchronously against the database and returns a data reader. - /// - /// The token to monitor for cancellation requests. - /// A task representing the asynchronous operation. - /// Async Limitations - /// Batching - /// Database Errors - /// If the is canceled. - public new virtual Task ExecuteReaderAsync(CancellationToken cancellationToken) - => ExecuteReaderAsync(CommandBehavior.Default, cancellationToken); - - /// - /// Executes the asynchronously against the database and returns a data reader. - /// - /// A description of query's results and its effect on the database. - /// A task representing the asynchronous operation. - /// Async Limitations - /// Batching - /// Database Errors - public new virtual Task ExecuteReaderAsync(CommandBehavior behavior) - => ExecuteReaderAsync(behavior, CancellationToken.None); - - /// - /// Executes the asynchronously against the database and returns a data reader. - /// - /// A description of query's results and its effect on the database. - /// The token to monitor for cancellation requests. - /// A task representing the asynchronous operation. - /// Async Limitations - /// Batching - /// Database Errors - /// If the is canceled. - public new virtual Task ExecuteReaderAsync( - CommandBehavior behavior, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); + /// + /// Executes the against the database and returns a data reader. + /// + /// A description of query's results and its effect on the database. + /// The data reader. + protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) + => ExecuteReader(behavior); - return Task.FromResult(ExecuteReader(behavior)); - } + /// + /// Executes the asynchronously against the database and returns a data reader. + /// + /// A task representing the asynchronous operation. + /// Async Limitations + /// Batching + /// Database Errors + public new virtual Task ExecuteReaderAsync() + => ExecuteReaderAsync(CommandBehavior.Default, CancellationToken.None); - /// - /// Executes the asynchronously against the database and returns a data reader. - /// - /// A description of query's results and its effect on the database. - /// The token to monitor for cancellation requests. - /// A task representing the asynchronous operation. - /// Async Limitations - /// If the is canceled. - protected override async Task ExecuteDbDataReaderAsync( - CommandBehavior behavior, - CancellationToken cancellationToken) - => await ExecuteReaderAsync(behavior, cancellationToken).ConfigureAwait(false); - - /// - /// Executes the against the database. - /// - /// The number of rows inserted, updated, or deleted. -1 for SELECT statements. - /// A SQLite error occurs during execution. - /// Database Errors - public override int ExecuteNonQuery() - { - if (_connection?.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteNonQuery))); - } + /// + /// Executes the asynchronously against the database and returns a data reader. + /// + /// The token to monitor for cancellation requests. + /// A task representing the asynchronous operation. + /// Async Limitations + /// Batching + /// Database Errors + /// If the is canceled. + public new virtual Task ExecuteReaderAsync(CancellationToken cancellationToken) + => ExecuteReaderAsync(CommandBehavior.Default, cancellationToken); - var reader = ExecuteReader(); - reader.Dispose(); + /// + /// Executes the asynchronously against the database and returns a data reader. + /// + /// A description of query's results and its effect on the database. + /// A task representing the asynchronous operation. + /// Async Limitations + /// Batching + /// Database Errors + public new virtual Task ExecuteReaderAsync(CommandBehavior behavior) + => ExecuteReaderAsync(behavior, CancellationToken.None); - return reader.RecordsAffected; - } + /// + /// Executes the asynchronously against the database and returns a data reader. + /// + /// A description of query's results and its effect on the database. + /// The token to monitor for cancellation requests. + /// A task representing the asynchronous operation. + /// Async Limitations + /// Batching + /// Database Errors + /// If the is canceled. + public new virtual Task ExecuteReaderAsync( + CommandBehavior behavior, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); - /// - /// Executes the against the database and returns the result. - /// - /// The first column of the first row of the results, or null if no results. - /// A SQLite error occurs during execution. - /// Database Errors - public override object? ExecuteScalar() - { - if (_connection?.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteScalar))); - } + return Task.FromResult(ExecuteReader(behavior)); + } - using var reader = ExecuteReader(); - return reader.Read() - ? reader.GetValue(0) - : null; - } + /// + /// Executes the asynchronously against the database and returns a data reader. + /// + /// A description of query's results and its effect on the database. + /// The token to monitor for cancellation requests. + /// A task representing the asynchronous operation. + /// Async Limitations + /// If the is canceled. + protected override async Task ExecuteDbDataReaderAsync( + CommandBehavior behavior, + CancellationToken cancellationToken) + => await ExecuteReaderAsync(behavior, cancellationToken).ConfigureAwait(false); - /// - /// Attempts to cancel the execution of the command. Does nothing. - /// - public override void Cancel() + /// + /// Executes the against the database. + /// + /// The number of rows inserted, updated, or deleted. -1 for SELECT statements. + /// A SQLite error occurs during execution. + /// Database Errors + public override int ExecuteNonQuery() + { + if (_connection?.State != ConnectionState.Open) { + throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteNonQuery))); } - private IEnumerable<(sqlite3_stmt Statement, int ParamCount)> PrepareAndEnumerateStatements() - { - DisposePreparedStatements(disposing: false); + var reader = ExecuteReader(); + reader.Dispose(); - var byteCount = Encoding.UTF8.GetByteCount(_commandText); - var sql = new byte[byteCount + 1]; - Encoding.UTF8.GetBytes(_commandText, 0, _commandText.Length, sql, 0); + return reader.RecordsAffected; + } - var totalElapsedTime = TimeSpan.Zero; - int rc; - sqlite3_stmt stmt; - var start = 0; - do - { - var timer = SharedStopwatch.StartNew(); + /// + /// Executes the against the database and returns the result. + /// + /// The first column of the first row of the results, or null if no results. + /// A SQLite error occurs during execution. + /// Database Errors + public override object? ExecuteScalar() + { + if (_connection?.State != ConnectionState.Open) + { + throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(ExecuteScalar))); + } - ReadOnlySpan tail; - while (IsBusy(rc = sqlite3_prepare_v2(_connection!.Handle, sql.AsSpan(start), out stmt, out tail))) - { - if (CommandTimeout != 0 - && (totalElapsedTime + timer.Elapsed).TotalMilliseconds >= CommandTimeout * 1000L) - { - break; - } + using var reader = ExecuteReader(); + return reader.Read() + ? reader.GetValue(0) + : null; + } - Thread.Sleep(150); - } + /// + /// Attempts to cancel the execution of the command. Does nothing. + /// + public override void Cancel() + { + } - totalElapsedTime += timer.Elapsed; - start = sql.Length - tail.Length; + private IEnumerable<(sqlite3_stmt Statement, int ParamCount)> PrepareAndEnumerateStatements() + { + DisposePreparedStatements(disposing: false); - SqliteException.ThrowExceptionForRC(rc, _connection.Handle); + var byteCount = Encoding.UTF8.GetByteCount(_commandText); + var sql = new byte[byteCount + 1]; + Encoding.UTF8.GetBytes(_commandText, 0, _commandText.Length, sql, 0); - // Statement was empty, white space, or a comment - if (stmt.IsInvalid) - { - if (start < byteCount) - { - continue; - } + var totalElapsedTime = TimeSpan.Zero; + int rc; + sqlite3_stmt stmt; + var start = 0; + do + { + var timer = SharedStopwatch.StartNew(); + ReadOnlySpan tail; + while (IsBusy(rc = sqlite3_prepare_v2(_connection!.Handle, sql.AsSpan(start), out stmt, out tail))) + { + if (CommandTimeout != 0 + && (totalElapsedTime + timer.Elapsed).TotalMilliseconds >= CommandTimeout * 1000L) + { break; } - var paramsCount = sqlite3_bind_parameter_count(stmt); - var statementWithParams = (stmt, paramsCount); + Thread.Sleep(150); + } + + totalElapsedTime += timer.Elapsed; + start = sql.Length - tail.Length; - _preparedStatements.Add(statementWithParams); + SqliteException.ThrowExceptionForRC(rc, _connection.Handle); + + // Statement was empty, white space, or a comment + if (stmt.IsInvalid) + { + if (start < byteCount) + { + continue; + } - yield return statementWithParams; + break; } - while (start < byteCount); - _prepared = true; + var paramsCount = sqlite3_bind_parameter_count(stmt); + var statementWithParams = (stmt, paramsCount); + + _preparedStatements.Add(statementWithParams); + + yield return statementWithParams; } + while (start < byteCount); - private void DisposePreparedStatements(bool disposing = true) + _prepared = true; + } + + private void DisposePreparedStatements(bool disposing = true) + { + if (disposing + && DataReader != null) { - if (disposing - && DataReader != null) - { - DataReader.Dispose(); - DataReader = null; - } + DataReader.Dispose(); + DataReader = null; + } - if (_preparedStatements != null) + if (_preparedStatements != null) + { + foreach (var (stmt, _) in _preparedStatements) { - foreach ((var stmt, _) in _preparedStatements) - { - stmt.Dispose(); - } - - _preparedStatements.Clear(); + stmt.Dispose(); } - _prepared = false; + _preparedStatements.Clear(); } - private static bool IsBusy(int rc) - => rc is SQLITE_LOCKED or SQLITE_BUSY or SQLITE_LOCKED_SHAREDCACHE; + _prepared = false; } + + private static bool IsBusy(int rc) + => rc is SQLITE_LOCKED or SQLITE_BUSY or SQLITE_LOCKED_SHAREDCACHE; } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.CreateAggregate.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.CreateAggregate.cs index 4edec19a030..11d8a1a816b 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.CreateAggregate.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.CreateAggregate.cs @@ -1,1104 +1,1580 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// + +#nullable enable using System; -#nullable enable +namespace Microsoft.Data.Sqlite; -namespace Microsoft.Data.Sqlite +partial class SqliteConnection { - partial class SqliteConnection - { - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 0, default!, IfNotNull(func, (a, r) => func!(a)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) + => CreateAggregateCore(name, 0, default!, IfNotNull(func, (a, r) => func!(a)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 1, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 1, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!)), a => a, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 2, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 2, default!, + IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!)), a => a, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 3, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 3, default!, + IfNotNull( + func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), a => a, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 4, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 4, default!, + IfNotNull( + func, + (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), + a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 5, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 5, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 6, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 6, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 7, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 7, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 8, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 8, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), a => a, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 9, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 9, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 10, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 10, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 11, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 11, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 12, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 12, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), a => a, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 13, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 13, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 14, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 14, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the fifteenth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 15, default!, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the fifteenth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 15, default!, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the accumulator value. - /// The name of the SQL function. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, -1, default!, IfNotNull(func, (a, r) => func!(a, GetValues(r))), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the accumulator value. + /// The name of the SQL function. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, -1, default!, IfNotNull(func, (a, r) => func!(a, GetValues(r))), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 0, seed, IfNotNull(func, (a, r) => func!(a)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore(name, 0, seed, IfNotNull(func, (a, r) => func!(a)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 1, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 1, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 2, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 2, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!)), + a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 3, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 3, seed, + IfNotNull( + func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), a => a, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 4, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 4, seed, + IfNotNull( + func, + (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), + a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 5, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 5, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 6, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 6, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 7, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 7, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 8, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 8, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), a => a, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 9, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 9, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 10, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 10, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 11, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 11, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 12, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 12, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), a => a, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 13, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 13, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 14, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 14, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the fifteenth parameter of the function. - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, 15, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the fifteenth parameter of the function. + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, 15, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the accumulator value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, bool isDeterministic = false) - => CreateAggregateCore(name, -1, seed, IfNotNull(func, (a, r) => func!(a, GetValues(r))), a => a, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the accumulator value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + bool isDeterministic = false) + => CreateAggregateCore( + name, -1, seed, IfNotNull(func, (a, r) => func!(a, GetValues(r))), a => a, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 0, seed, IfNotNull(func, (a, r) => func!(a)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 0, seed, IfNotNull(func, (a, r) => func!(a)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 1, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 1, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!)), resultSelector, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 2, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 2, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!)), + resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 3, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 3, seed, + IfNotNull( + func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), resultSelector, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 4, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 4, seed, + IfNotNull( + func, + (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), + resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 5, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 5, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 6, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 6, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 7, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 7, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 8, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 8, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), resultSelector, + isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 9, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 9, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 10, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 10, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 11, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 11, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 12, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 12, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), + resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 13, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 13, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 14, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 14, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the fifteenth parameter of the function. - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, 15, seed, IfNotNull(func, (a, r) => func!(a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), resultSelector, isDeterministic); + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the fifteenth parameter of the function. + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, 15, seed, + IfNotNull( + func, + (a, r) => func!( + a, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), resultSelector, isDeterministic); - /// - /// Creates or redefines an aggregate SQL function. - /// - /// The type of the accumulator value. - /// The type of the resulting value. - /// The name of the SQL function. - /// The initial accumulator value. - /// An accumulator function to be invoked on each element. Pass null to delete a function. - /// - /// A function to transform the final accumulator value into the result value. Pass null to - /// delete a function. - /// - /// Flag indicating whether the aggregate is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateAggregate(string name, TAccumulate seed, Func? func, Func? resultSelector, bool isDeterministic = false) - => CreateAggregateCore(name, -1, seed, IfNotNull(func, (a, r) => func!(a, GetValues(r))), resultSelector, isDeterministic); - } + /// + /// Creates or redefines an aggregate SQL function. + /// + /// The type of the accumulator value. + /// The type of the resulting value. + /// The name of the SQL function. + /// The initial accumulator value. + /// An accumulator function to be invoked on each element. Pass null to delete a function. + /// + /// A function to transform the final accumulator value into the result value. Pass null to + /// delete a function. + /// + /// Flag indicating whether the aggregate is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateAggregate( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic = false) + => CreateAggregateCore( + name, -1, seed, IfNotNull(func, (a, r) => func!(a, GetValues(r))), resultSelector, isDeterministic); } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.CreateFunction.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.CreateFunction.cs index cfeda05a378..560bfb9256d 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.CreateFunction.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.CreateFunction.cs @@ -1,723 +1,1014 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// + +#nullable enable using System; -#nullable enable +namespace Microsoft.Data.Sqlite; -namespace Microsoft.Data.Sqlite +partial class SqliteConnection { - partial class SqliteConnection - { - /// - /// Creates or redefines a SQL function. - /// - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 0, null, IfNotNull(function, (s, r) => function!()), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 1, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 2, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 3, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 4, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 5, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 6, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 7, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 8, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 9, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 10, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 11, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 12, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 13, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 14, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the fifteenth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 15, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the fifteenth parameter of the function. - /// The type of the sixteenth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 16, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!, r.GetFieldValue(15)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the resulting value. - /// The name of the SQL function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, -1, null, IfNotNull(function, (s, r) => function!(GetValues(r))), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 0, state, IfNotNull(function, (s, r) => function!(s)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 1, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 2, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 3, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 4, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 5, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 6, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 7, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 8, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 9, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 10, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 11, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 12, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 13, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 14, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the first parameter of the function. - /// The type of the second parameter of the function. - /// The type of the third parameter of the function. - /// The type of the fourth parameter of the function. - /// The type of the fifth parameter of the function. - /// The type of the sixth parameter of the function. - /// The type of the seventh parameter of the function. - /// The type of the eighth parameter of the function. - /// The type of the ninth parameter of the function. - /// The type of the tenth parameter of the function. - /// The type of the eleventh parameter of the function. - /// The type of the twelfth parameter of the function. - /// The type of the thirteenth parameter of the function. - /// The type of the fourteenth parameter of the function. - /// The type of the fifteenth parameter of the function. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, 15, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), isDeterministic); - - /// - /// Creates or redefines a SQL function. - /// - /// The type of the state. - /// The type of the resulting value. - /// The name of the SQL function. - /// An object available during each invocation of the function. - /// The function to be invoked. - /// Flag indicating whether the function is deterministic. - /// User-Defined Functions - /// Data Types - public virtual void CreateFunction(string name, TState state, Func? function, bool isDeterministic = false) - => CreateFunctionCore(name, -1, state, IfNotNull(function, (s, r) => function!(s, GetValues(r))), isDeterministic); - } + /// + /// Creates or redefines a SQL function. + /// + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) + => CreateFunctionCore(name, 0, null, IfNotNull(function, (s, r) => function!()), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) + => CreateFunctionCore( + name, 1, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) + => CreateFunctionCore( + name, 2, null, IfNotNull(function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!)), + isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) + => CreateFunctionCore( + name, 3, null, + IfNotNull( + function, (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 4, null, + IfNotNull( + function, + (s, r) => function!(r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), + isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 5, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 6, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 7, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 8, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 9, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 10, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 11, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 12, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), + isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 13, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 14, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the fifteenth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 15, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the fifteenth parameter of the function. + /// The type of the sixteenth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 16, null, + IfNotNull( + function, + (s, r) => function!( + r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!, r.GetFieldValue(15)!)), + isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the resulting value. + /// The name of the SQL function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction(string name, Func? function, bool isDeterministic = false) + => CreateFunctionCore(name, -1, null, IfNotNull(function, (s, r) => function!(GetValues(r))), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore(name, 0, state, IfNotNull(function, (s, r) => function!(s)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 1, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 2, state, IfNotNull(function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!)), + isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 3, state, + IfNotNull( + function, (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!)), + isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 4, state, + IfNotNull( + function, + (s, r) => function!(s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!)), + isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 5, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 6, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 7, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 8, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 9, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 10, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 11, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 12, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!)), + isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 13, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 14, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the first parameter of the function. + /// The type of the second parameter of the function. + /// The type of the third parameter of the function. + /// The type of the fourth parameter of the function. + /// The type of the fifth parameter of the function. + /// The type of the sixth parameter of the function. + /// The type of the seventh parameter of the function. + /// The type of the eighth parameter of the function. + /// The type of the ninth parameter of the function. + /// The type of the tenth parameter of the function. + /// The type of the eleventh parameter of the function. + /// The type of the twelfth parameter of the function. + /// The type of the thirteenth parameter of the function. + /// The type of the fourteenth parameter of the function. + /// The type of the fifteenth parameter of the function. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore( + name, 15, state, + IfNotNull( + function, + (s, r) => function!( + s, r.GetFieldValue(0)!, r.GetFieldValue(1)!, r.GetFieldValue(2)!, r.GetFieldValue(3)!, + r.GetFieldValue(4)!, r.GetFieldValue(5)!, r.GetFieldValue(6)!, r.GetFieldValue(7)!, + r.GetFieldValue(8)!, r.GetFieldValue(9)!, r.GetFieldValue(10)!, r.GetFieldValue(11)!, + r.GetFieldValue(12)!, r.GetFieldValue(13)!, r.GetFieldValue(14)!)), isDeterministic); + + /// + /// Creates or redefines a SQL function. + /// + /// The type of the state. + /// The type of the resulting value. + /// The name of the SQL function. + /// An object available during each invocation of the function. + /// The function to be invoked. + /// Flag indicating whether the function is deterministic. + /// User-Defined Functions + /// Data Types + public virtual void CreateFunction( + string name, + TState state, + Func? function, + bool isDeterministic = false) + => CreateFunctionCore(name, -1, state, IfNotNull(function, (s, r) => function!(s, GetValues(r))), isDeterministic); } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs index 88efdbeb07f..3062c0f923c 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs @@ -14,1018 +14,1006 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Represents a connection to a SQLite database. +/// +/// Connection Strings +/// Async Limitations +public partial class SqliteConnection : DbConnection { - /// - /// Represents a connection to a SQLite database. - /// - /// Connection Strings - /// Async Limitations - public partial class SqliteConnection : DbConnection - { - internal const string MainDatabaseName = "main"; + internal const string MainDatabaseName = "main"; - private const int SQLITE_WIN32_DATA_DIRECTORY_TYPE = 1; - private const int SQLITE_WIN32_TEMP_DIRECTORY_TYPE = 2; + private const int SQLITE_WIN32_DATA_DIRECTORY_TYPE = 1; + private const int SQLITE_WIN32_TEMP_DIRECTORY_TYPE = 2; - private readonly List> _commands = []; + private readonly List> _commands = []; - private Dictionary? _collations; + private Dictionary? _collations; - private Dictionary<(string name, int arity), (int flags, object? state, delegate_function_scalar? func)>? _functions; + private Dictionary<(string name, int arity), (int flags, object? state, delegate_function_scalar? func)>? _functions; - private Dictionary<(string name, int arity), (int flags, object? state, delegate_function_aggregate_step? func_step, - delegate_function_aggregate_final? func_final)>? _aggregates; + private Dictionary<(string name, int arity), (int flags, object? state, delegate_function_aggregate_step? func_step, + delegate_function_aggregate_final? func_final)>? _aggregates; - private HashSet<(string file, string? proc)>? _extensions; + private HashSet<(string file, string? proc)>? _extensions; - private string _connectionString; - private ConnectionState _state; - private SqliteConnectionInternal? _innerConnection; - private bool _extensionsEnabled; - private int? _defaultTimeout; + private string _connectionString; + private ConnectionState _state; + private SqliteConnectionInternal? _innerConnection; + private bool _extensionsEnabled; + private int? _defaultTimeout; - private static readonly StateChangeEventArgs _fromClosedToOpenEventArgs = new StateChangeEventArgs(ConnectionState.Closed, ConnectionState.Open); - private static readonly StateChangeEventArgs _fromOpenToClosedEventArgs = new StateChangeEventArgs(ConnectionState.Open, ConnectionState.Closed); + private static readonly StateChangeEventArgs _fromClosedToOpenEventArgs = new(ConnectionState.Closed, ConnectionState.Open); + private static readonly StateChangeEventArgs _fromOpenToClosedEventArgs = new(ConnectionState.Open, ConnectionState.Closed); - private static string[]? NativeDllSearchDirectories; + private static string[]? NativeDllSearchDirectories; - static SqliteConnection() + static SqliteConnection() + { + Type.GetType("SQLitePCL.Batteries_V2, SQLitePCLRaw.batteries_v2") + ?.GetRuntimeMethod("Init", Type.EmptyTypes) + ?.Invoke(null, null); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - Type.GetType("SQLitePCL.Batteries_V2, SQLitePCLRaw.batteries_v2") - ?.GetRuntimeMethod("Init", Type.EmptyTypes) - ?.Invoke(null, null); + Type? appDataType = null; + Type? storageFolderType = null; + try + { + appDataType = Type.GetType("Windows.Storage.ApplicationData, Windows, ContentType=WindowsRuntime") + ?? Type.GetType("Windows.Storage.ApplicationData, Microsoft.Windows.SDK.NET"); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + storageFolderType = Type.GetType("Windows.Storage.StorageFolder, Windows, ContentType=WindowsRuntime") + ?? Type.GetType("Windows.Storage.StorageFolder, Microsoft.Windows.SDK.NET"); + } + catch { - Type? appDataType = null; - Type? storageFolderType = null; - try - { - appDataType = Type.GetType("Windows.Storage.ApplicationData, Windows, ContentType=WindowsRuntime") - ?? Type.GetType("Windows.Storage.ApplicationData, Microsoft.Windows.SDK.NET"); + // Ignore "Could not load assembly." or any type initialization error. + } - storageFolderType = Type.GetType("Windows.Storage.StorageFolder, Windows, ContentType=WindowsRuntime") - ?? Type.GetType("Windows.Storage.StorageFolder, Microsoft.Windows.SDK.NET"); - } - catch - { - // Ignore "Could not load assembly." or any type initialization error. - } + object? currentAppData = null; + try + { + currentAppData = appDataType?.GetRuntimeProperty("Current")?.GetValue(null); + } + catch (TargetInvocationException) + { + // Ignore "The process has no package identity." + } - object? currentAppData = null; - try - { - currentAppData = appDataType?.GetRuntimeProperty("Current")?.GetValue(null); - } - catch (TargetInvocationException) + if (currentAppData != null) + { + var localFolder = appDataType?.GetRuntimeProperty("LocalFolder")?.GetValue(currentAppData); + var localFolderPath = (string?)storageFolderType?.GetRuntimeProperty("Path")?.GetValue(localFolder); + if (localFolderPath != null) { - // Ignore "The process has no package identity." + var rc = sqlite3_win32_set_directory(SQLITE_WIN32_DATA_DIRECTORY_TYPE, localFolderPath); + Debug.Assert(rc == SQLITE_OK); } - if (currentAppData != null) + var tempFolder = appDataType?.GetRuntimeProperty("TemporaryFolder")?.GetValue(currentAppData); + var tempFolderPath = (string?)storageFolderType?.GetRuntimeProperty("Path")?.GetValue(tempFolder); + if (tempFolderPath != null) { - var localFolder = appDataType?.GetRuntimeProperty("LocalFolder")?.GetValue(currentAppData); - var localFolderPath = (string?)storageFolderType?.GetRuntimeProperty("Path")?.GetValue(localFolder); - if (localFolderPath != null) - { - var rc = sqlite3_win32_set_directory(SQLITE_WIN32_DATA_DIRECTORY_TYPE, localFolderPath); - Debug.Assert(rc == SQLITE_OK); - } - - var tempFolder = appDataType?.GetRuntimeProperty("TemporaryFolder")?.GetValue(currentAppData); - var tempFolderPath = (string?)storageFolderType?.GetRuntimeProperty("Path")?.GetValue(tempFolder); - if (tempFolderPath != null) - { - var rc = sqlite3_win32_set_directory(SQLITE_WIN32_TEMP_DIRECTORY_TYPE, tempFolderPath); - Debug.Assert(rc == SQLITE_OK); - } + var rc = sqlite3_win32_set_directory(SQLITE_WIN32_TEMP_DIRECTORY_TYPE, tempFolderPath); + Debug.Assert(rc == SQLITE_OK); } } } + } - /// - /// Initializes a new instance of the class. - /// - public SqliteConnection() - : this(null) - { - } + /// + /// Initializes a new instance of the class. + /// + public SqliteConnection() + : this(null) + { + } - /// - /// Initializes a new instance of the class. - /// - /// The string used to open the connection. - /// Connection Strings - /// - public SqliteConnection(string? connectionString) - => ConnectionString = connectionString; - - /// - /// Gets a handle to underlying database connection. - /// - /// A handle to underlying database connection. - /// Interoperability - public virtual sqlite3? Handle - => _innerConnection?.Handle; - - /// - /// Gets or sets a string used to open the connection. - /// - /// A string used to open the connection. - /// Connection Strings - /// - [AllowNull] - public override string ConnectionString - { - get => _connectionString; + /// + /// Initializes a new instance of the class. + /// + /// The string used to open the connection. + /// Connection Strings + /// + public SqliteConnection(string? connectionString) + => ConnectionString = connectionString; - [MemberNotNull(nameof(_connectionString), nameof(PoolGroup))] - set - { - if (State != ConnectionState.Closed) - { - throw new InvalidOperationException(Resources.ConnectionStringRequiresClosedConnection); - } + /// + /// Gets a handle to underlying database connection. + /// + /// A handle to underlying database connection. + /// Interoperability + public virtual sqlite3? Handle + => _innerConnection?.Handle; - _connectionString = value ?? string.Empty; + /// + /// Gets or sets a string used to open the connection. + /// + /// A string used to open the connection. + /// Connection Strings + /// + [AllowNull] + public override string ConnectionString + { + get => _connectionString; - PoolGroup = SqliteConnectionFactory.Instance.GetPoolGroup(_connectionString); + [MemberNotNull(nameof(_connectionString), nameof(PoolGroup))] + set + { + if (State != ConnectionState.Closed) + { + throw new InvalidOperationException(Resources.ConnectionStringRequiresClosedConnection); } - } - - internal SqliteConnectionPoolGroup PoolGroup { get; set; } - internal SqliteConnectionStringBuilder ConnectionOptions - => PoolGroup.ConnectionOptions; + _connectionString = value ?? string.Empty; - /// - /// Gets the name of the current database. Always 'main'. - /// - /// The name of the current database. - public override string Database - => MainDatabaseName; + PoolGroup = SqliteConnectionFactory.Instance.GetPoolGroup(_connectionString); + } + } - /// - /// Gets the path to the database file. Will be absolute for open connections. - /// - /// The path to the database file. - public override string DataSource - { - get - { - string? dataSource = null; - if (State == ConnectionState.Open) - { - dataSource = sqlite3_db_filename(Handle, MainDatabaseName).utf8_to_string(); - } + internal SqliteConnectionPoolGroup PoolGroup { get; set; } - return dataSource ?? ConnectionOptions.DataSource; - } - } + internal SqliteConnectionStringBuilder ConnectionOptions + => PoolGroup.ConnectionOptions; - /// - /// Gets or sets the default value for commands created using - /// this connection. This is also used for internal commands in methods like - /// . - /// - /// The default value. - /// Database Errors - public virtual int DefaultTimeout - { - get => _defaultTimeout ?? ConnectionOptions.DefaultTimeout; - set => _defaultTimeout = value; - } + /// + /// Gets the name of the current database. Always 'main'. + /// + /// The name of the current database. + public override string Database + => MainDatabaseName; - /// - /// Gets the version of SQLite used by the connection. - /// - /// The version of SQLite used by the connection. - public override string ServerVersion - => sqlite3_libversion().utf8_to_string(); - - /// - /// Gets the current state of the connection. - /// - /// The current state of the connection. - public override ConnectionState State - => _state; - - /// - /// Gets the for this connection. - /// - /// The . - protected override DbProviderFactory DbProviderFactory - => SqliteFactory.Instance; - - /// - /// Gets or sets the transaction currently being used by the connection, or null if none. - /// - /// The transaction currently being used by the connection. - protected internal virtual SqliteTransaction? Transaction { get; set; } - - /// - /// Empties the connection pool. - /// - /// Any open connections will not be returned to the pool when closed. - public static void ClearAllPools() - => SqliteConnectionFactory.Instance.ClearPools(); - - /// - /// Empties the connection pool associated with the connection. - /// - /// The connection. - /// Any open connections will not be returned to the pool when closed. - public static void ClearPool(SqliteConnection connection) - => connection.PoolGroup.Clear(); - - /// - /// Opens a connection to the database using the value of . If - /// Mode=ReadWriteCreate is used (the default) the file is created, if it doesn't already exist. - /// - /// A SQLite error occurs while opening the connection. - public override void Open() + /// + /// Gets the path to the database file. Will be absolute for open connections. + /// + /// The path to the database file. + public override string DataSource + { + get { + string? dataSource = null; if (State == ConnectionState.Open) { - return; + dataSource = sqlite3_db_filename(Handle, MainDatabaseName).utf8_to_string(); } - _innerConnection = SqliteConnectionFactory.Instance.GetConnection(this); - - int rc; - - _state = ConnectionState.Open; - try - { - if (ConnectionOptions.ForeignKeys.HasValue) - { - this.ExecuteNonQuery( - "PRAGMA foreign_keys = " + (ConnectionOptions.ForeignKeys.Value ? "1" : "0") + ";"); - } + return dataSource ?? ConnectionOptions.DataSource; + } + } - if (ConnectionOptions.RecursiveTriggers) - { - this.ExecuteNonQuery("PRAGMA recursive_triggers = 1;"); - } + /// + /// Gets or sets the default value for commands created using + /// this connection. This is also used for internal commands in methods like + /// . + /// + /// The default value. + /// Database Errors + public virtual int DefaultTimeout + { + get => _defaultTimeout ?? ConnectionOptions.DefaultTimeout; + set => _defaultTimeout = value; + } - if (_collations != null) - { - foreach (var item in _collations) - { - rc = sqlite3_create_collation(Handle, item.Key, item.Value.state, item.Value.collation); - SqliteException.ThrowExceptionForRC(rc, Handle); - } - } + /// + /// Gets the version of SQLite used by the connection. + /// + /// The version of SQLite used by the connection. + public override string ServerVersion + => sqlite3_libversion().utf8_to_string(); - if (_functions != null) - { - foreach (var item in _functions) - { - rc = sqlite3_create_function(Handle, item.Key.name, item.Key.arity, item.Value.state, item.Value.func); - SqliteException.ThrowExceptionForRC(rc, Handle); - } - } + /// + /// Gets the current state of the connection. + /// + /// The current state of the connection. + public override ConnectionState State + => _state; - if (_aggregates != null) - { - foreach (var item in _aggregates) - { - rc = sqlite3_create_function( - Handle, item.Key.name, item.Key.arity, item.Value.state, item.Value.func_step, item.Value.func_final); - SqliteException.ThrowExceptionForRC(rc, Handle); - } - } + /// + /// Gets the for this connection. + /// + /// The . + protected override DbProviderFactory DbProviderFactory + => SqliteFactory.Instance; - if (_extensions != null - && _extensions.Count != 0) - { - rc = sqlite3_db_config(Handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, out _); - SqliteException.ThrowExceptionForRC(rc, Handle); + /// + /// Gets or sets the transaction currently being used by the connection, or null if none. + /// + /// The transaction currently being used by the connection. + protected internal virtual SqliteTransaction? Transaction { get; set; } - foreach (var item in _extensions) - { - LoadExtensionCore(item.file, item.proc); - } - } + /// + /// Empties the connection pool. + /// + /// Any open connections will not be returned to the pool when closed. + public static void ClearAllPools() + => SqliteConnectionFactory.Instance.ClearPools(); - if (_extensionsEnabled) - { - rc = sqlite3_enable_load_extension(Handle, _extensionsEnabled ? 1 : 0); - SqliteException.ThrowExceptionForRC(rc, Handle); - } - } - catch - { - _innerConnection.Close(); - _innerConnection = null; + /// + /// Empties the connection pool associated with the connection. + /// + /// The connection. + /// Any open connections will not be returned to the pool when closed. + public static void ClearPool(SqliteConnection connection) + => connection.PoolGroup.Clear(); - _state = ConnectionState.Closed; + /// + /// Opens a connection to the database using the value of . If + /// Mode=ReadWriteCreate is used (the default) the file is created, if it doesn't already exist. + /// + /// A SQLite error occurs while opening the connection. + public override void Open() + { + if (State == ConnectionState.Open) + { + return; + } - throw; - } + _innerConnection = SqliteConnectionFactory.Instance.GetConnection(this); - OnStateChange(_fromClosedToOpenEventArgs); - } + int rc; - /// - /// Closes the connection to the database. Open transactions are rolled back. - /// - public override void Close() + _state = ConnectionState.Open; + try { - if (State != ConnectionState.Open) + if (ConnectionOptions.ForeignKeys.HasValue) { - return; + this.ExecuteNonQuery( + "PRAGMA foreign_keys = " + (ConnectionOptions.ForeignKeys.Value ? "1" : "0") + ";"); } - Transaction?.Dispose(); - - var commands = _commands; - for (var i = commands.Count - 1; i >= 0; i--) + if (ConnectionOptions.RecursiveTriggers) { - var reference = commands[i]; - if (reference.TryGetTarget(out var command)) - { - // NB: Calls RemoveCommand() - command.Dispose(); - } + this.ExecuteNonQuery("PRAGMA recursive_triggers = 1;"); } - _commands.Clear(); - _innerConnection!.Close(); - _innerConnection = null; - - _state = ConnectionState.Closed; - OnStateChange(_fromOpenToClosedEventArgs); - } - - internal void Deactivate() - { - int rc; - if (_collations != null) { - foreach (var item in _collations.Keys) + foreach (var item in _collations) { - rc = sqlite3_create_collation(Handle, item, null, null); + rc = sqlite3_create_collation(Handle, item.Key, item.Value.state, item.Value.collation); SqliteException.ThrowExceptionForRC(rc, Handle); } } if (_functions != null) { - foreach (var (name, arity) in _functions.Keys) + foreach (var item in _functions) { - rc = sqlite3_create_function(Handle, name, arity, null, null); + rc = sqlite3_create_function(Handle, item.Key.name, item.Key.arity, item.Value.state, item.Value.func); SqliteException.ThrowExceptionForRC(rc, Handle); } } if (_aggregates != null) { - foreach (var (name, arity) in _aggregates.Keys) + foreach (var item in _aggregates) { rc = sqlite3_create_function( - Handle, name, arity, null, null, null); + Handle, item.Key.name, item.Key.arity, item.Value.state, item.Value.func_step, item.Value.func_final); SqliteException.ThrowExceptionForRC(rc, Handle); } } - // TODO: Unload extensions (currently not supported by SQLite) + if (_extensions != null + && _extensions.Count != 0) + { + rc = sqlite3_db_config(Handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, out _); + SqliteException.ThrowExceptionForRC(rc, Handle); + + foreach (var item in _extensions) + { + LoadExtensionCore(item.file, item.proc); + } + } + if (_extensionsEnabled) { - rc = sqlite3_enable_load_extension(Handle, 0); + rc = sqlite3_enable_load_extension(Handle, _extensionsEnabled ? 1 : 0); SqliteException.ThrowExceptionForRC(rc, Handle); } } + catch + { + _innerConnection.Close(); + _innerConnection = null; + + _state = ConnectionState.Closed; + + throw; + } + + OnStateChange(_fromClosedToOpenEventArgs); + } + + /// + /// Closes the connection to the database. Open transactions are rolled back. + /// + public override void Close() + { + if (State != ConnectionState.Open) + { + return; + } - /// - /// Releases any resources used by the connection and closes it. - /// - /// - /// to release managed and unmanaged resources; - /// to release only unmanaged resources. - /// - protected override void Dispose(bool disposing) + Transaction?.Dispose(); + + var commands = _commands; + for (var i = commands.Count - 1; i >= 0; i--) { - if (disposing) + var reference = commands[i]; + if (reference.TryGetTarget(out var command)) { - Close(); + // NB: Calls RemoveCommand() + command.Dispose(); } - - base.Dispose(disposing); } - /// - /// Creates a new command associated with the connection. - /// - /// The new command. - /// - /// The command's property will also be set to the current - /// transaction. - /// - public new virtual SqliteCommand CreateCommand() - => new() - { - Connection = this, - CommandTimeout = DefaultTimeout, - Transaction = Transaction - }; + _commands.Clear(); + _innerConnection!.Close(); + _innerConnection = null; - /// - /// Creates a new command associated with the connection. - /// - /// The new command. - protected override DbCommand CreateDbCommand() - => CreateCommand(); + _state = ConnectionState.Closed; + OnStateChange(_fromOpenToClosedEventArgs); + } - internal void AddCommand(SqliteCommand command) - => _commands.Add(new WeakReference(command)); + internal void Deactivate() + { + int rc; - internal void RemoveCommand(SqliteCommand command) + if (_collations != null) { - for (var i = _commands.Count - 1; i >= 0; i--) + foreach (var item in _collations.Keys) { - var reference = _commands[i]; - if (reference != null - && reference.TryGetTarget(out var item) - && item == command) - { - _commands.RemoveAt(i); - } + rc = sqlite3_create_collation(Handle, item, null, null); + SqliteException.ThrowExceptionForRC(rc, Handle); } } - /// - /// Create custom collation. - /// - /// Name of the collation. - /// Method that compares two strings. - /// Collation - public virtual void CreateCollation(string name, Comparison? comparison) - => CreateCollation( - name, null, comparison != null ? (_, s1, s2) => comparison(s1, s2) : (Func?)null); - - /// - /// Create custom collation. - /// - /// The type of the state object. - /// Name of the collation. - /// State object passed to each invocation of the collation. - /// Method that compares two strings, using additional state. - /// Collation - public virtual void CreateCollation(string name, T state, Func? comparison) + if (_functions != null) { - if (string.IsNullOrEmpty(name)) + foreach (var (name, arity) in _functions.Keys) { - throw new ArgumentNullException(nameof(name)); + rc = sqlite3_create_function(Handle, name, arity, null, null); + SqliteException.ThrowExceptionForRC(rc, Handle); } + } - var collation = comparison != null ? (v, s1, s2) => comparison((T)v, s1, s2) : (strdelegate_collation?)null; - - if (State == ConnectionState.Open) + if (_aggregates != null) + { + foreach (var (name, arity) in _aggregates.Keys) { - var rc = sqlite3_create_collation(Handle, name, state, collation); + rc = sqlite3_create_function( + Handle, name, arity, null, null, null); SqliteException.ThrowExceptionForRC(rc, Handle); } + } - _collations ??= new Dictionary(StringComparer.OrdinalIgnoreCase); - _collations[name] = (state, collation); + // TODO: Unload extensions (currently not supported by SQLite) + if (_extensionsEnabled) + { + rc = sqlite3_enable_load_extension(Handle, 0); + SqliteException.ThrowExceptionForRC(rc, Handle); } + } - /// - /// Begins a transaction on the connection. - /// - /// The transaction. - /// A SQLite error occurs during execution. - /// Transactions - /// Database Errors - public new virtual SqliteTransaction BeginTransaction() - => BeginTransaction(IsolationLevel.Unspecified); - - /// - /// Begins a transaction on the connection. - /// - /// - /// to defer the creation of the transaction. - /// This also causes transactions to upgrade from read transactions to write transactions as needed by their commands. - /// - /// The transaction. - /// - /// Warning, commands inside a deferred transaction can fail if they cause the - /// transaction to be upgraded from a read transaction to a write transaction - /// but the database is locked. The application will need to retry the entire - /// transaction when this happens. - /// - /// A SQLite error occurs during execution. - /// Transactions - /// Database Errors - public virtual SqliteTransaction BeginTransaction(bool deferred) - => BeginTransaction(IsolationLevel.Unspecified, deferred); - - /// - /// Begins a transaction on the connection. - /// - /// The isolation level of the transaction. - /// The transaction. - protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) - => BeginTransaction(isolationLevel); - - /// - /// Begins a transaction on the connection. - /// - /// The isolation level of the transaction. - /// The transaction. - /// A SQLite error occurs during execution. - /// Transactions - /// Database Errors - public new virtual SqliteTransaction BeginTransaction(IsolationLevel isolationLevel) - => BeginTransaction(isolationLevel, deferred: isolationLevel == IsolationLevel.ReadUncommitted); - - /// - /// Begins a transaction on the connection. - /// - /// The isolation level of the transaction. - /// - /// to defer the creation of the transaction. - /// This also causes transactions to upgrade from read transactions to write transactions as needed by their commands. - /// - /// The transaction. - /// - /// Warning, commands inside a deferred transaction can fail if they cause the - /// transaction to be upgraded from a read transaction to a write transaction - /// but the database is locked. The application will need to retry the entire - /// transaction when this happens. - /// - /// A SQLite error occurs during execution. - /// Transactions - /// Database Errors - public virtual SqliteTransaction BeginTransaction(IsolationLevel isolationLevel, bool deferred) + /// + /// Releases any resources used by the connection and closes it. + /// + /// + /// to release managed and unmanaged resources; + /// to release only unmanaged resources. + /// + protected override void Dispose(bool disposing) + { + if (disposing) { - if (State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(BeginTransaction))); - } + Close(); + } + + base.Dispose(disposing); + } - if (Transaction != null) + /// + /// Creates a new command associated with the connection. + /// + /// The new command. + /// + /// The command's property will also be set to the current + /// transaction. + /// + public new virtual SqliteCommand CreateCommand() + => new() + { + Connection = this, + CommandTimeout = DefaultTimeout, + Transaction = Transaction + }; + + /// + /// Creates a new command associated with the connection. + /// + /// The new command. + protected override DbCommand CreateDbCommand() + => CreateCommand(); + + internal void AddCommand(SqliteCommand command) + => _commands.Add(new WeakReference(command)); + + internal void RemoveCommand(SqliteCommand command) + { + for (var i = _commands.Count - 1; i >= 0; i--) + { + var reference = _commands[i]; + if (reference != null + && reference.TryGetTarget(out var item) + && item == command) { - throw new InvalidOperationException(Resources.ParallelTransactionsNotSupported); + _commands.RemoveAt(i); } + } + } + + /// + /// Create custom collation. + /// + /// Name of the collation. + /// Method that compares two strings. + /// Collation + public virtual void CreateCollation(string name, Comparison? comparison) + => CreateCollation( + // ReSharper disable once RedundantCast + name, null, comparison != null ? (_, s1, s2) => comparison(s1, s2) : (Func?)null); - return Transaction = new SqliteTransaction(this, isolationLevel, deferred); + /// + /// Create custom collation. + /// + /// The type of the state object. + /// Name of the collation. + /// State object passed to each invocation of the collation. + /// Method that compares two strings, using additional state. + /// Collation + public virtual void CreateCollation(string name, T state, Func? comparison) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentNullException(nameof(name)); } - /// - /// Changes the current database. Not supported. - /// - /// The name of the database to use. - /// Always. - public override void ChangeDatabase(string databaseName) - => throw new NotSupportedException(); - - /// - /// Enables extension loading on the connection. - /// - /// to enable; to disable. - /// Extensions - public virtual void EnableExtensions(bool enable = true) + var collation = comparison != null ? (v, s1, s2) => comparison((T)v, s1, s2) : (strdelegate_collation?)null; + + if (State == ConnectionState.Open) { - if (State == ConnectionState.Open) - { - var rc = sqlite3_enable_load_extension(Handle, enable ? 1 : 0); - SqliteException.ThrowExceptionForRC(rc, Handle); - } + var rc = sqlite3_create_collation(Handle, name, state, collation); + SqliteException.ThrowExceptionForRC(rc, Handle); + } - _extensionsEnabled = enable; + _collations ??= new Dictionary(StringComparer.OrdinalIgnoreCase); + _collations[name] = (state, collation); + } + + /// + /// Begins a transaction on the connection. + /// + /// The transaction. + /// A SQLite error occurs during execution. + /// Transactions + /// Database Errors + public new virtual SqliteTransaction BeginTransaction() + => BeginTransaction(IsolationLevel.Unspecified); + + /// + /// Begins a transaction on the connection. + /// + /// + /// to defer the creation of the transaction. + /// This also causes transactions to upgrade from read transactions to write transactions as needed by their commands. + /// + /// The transaction. + /// + /// Warning, commands inside a deferred transaction can fail if they cause the + /// transaction to be upgraded from a read transaction to a write transaction + /// but the database is locked. The application will need to retry the entire + /// transaction when this happens. + /// + /// A SQLite error occurs during execution. + /// Transactions + /// Database Errors + public virtual SqliteTransaction BeginTransaction(bool deferred) + => BeginTransaction(IsolationLevel.Unspecified, deferred); + + /// + /// Begins a transaction on the connection. + /// + /// The isolation level of the transaction. + /// The transaction. + protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) + => BeginTransaction(isolationLevel); + + /// + /// Begins a transaction on the connection. + /// + /// The isolation level of the transaction. + /// The transaction. + /// A SQLite error occurs during execution. + /// Transactions + /// Database Errors + public new virtual SqliteTransaction BeginTransaction(IsolationLevel isolationLevel) + => BeginTransaction(isolationLevel, deferred: isolationLevel == IsolationLevel.ReadUncommitted); + + /// + /// Begins a transaction on the connection. + /// + /// The isolation level of the transaction. + /// + /// to defer the creation of the transaction. + /// This also causes transactions to upgrade from read transactions to write transactions as needed by their commands. + /// + /// The transaction. + /// + /// Warning, commands inside a deferred transaction can fail if they cause the + /// transaction to be upgraded from a read transaction to a write transaction + /// but the database is locked. The application will need to retry the entire + /// transaction when this happens. + /// + /// A SQLite error occurs during execution. + /// Transactions + /// Database Errors + public virtual SqliteTransaction BeginTransaction(IsolationLevel isolationLevel, bool deferred) + { + if (State != ConnectionState.Open) + { + throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(BeginTransaction))); } - /// - /// Loads a SQLite extension library. - /// - /// The shared library containing the extension. - /// The entry point. If null, the default entry point is used. - /// Extensions - public virtual void LoadExtension(string file, string? proc = null) + if (Transaction != null) { - if (State == ConnectionState.Open) - { - int rc; + throw new InvalidOperationException(Resources.ParallelTransactionsNotSupported); + } - if (!_extensionsEnabled) - { - rc = sqlite3_db_config(Handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, out _); - SqliteException.ThrowExceptionForRC(rc, Handle); - } + return Transaction = new SqliteTransaction(this, isolationLevel, deferred); + } - LoadExtensionCore(file, proc); - } + /// + /// Changes the current database. Not supported. + /// + /// The name of the database to use. + /// Always. + public override void ChangeDatabase(string databaseName) + => throw new NotSupportedException(); - _extensions ??= new HashSet<(string, string?)>(); - _extensions.Add((file, proc)); + /// + /// Enables extension loading on the connection. + /// + /// to enable; to disable. + /// Extensions + public virtual void EnableExtensions(bool enable = true) + { + if (State == ConnectionState.Open) + { + var rc = sqlite3_enable_load_extension(Handle, enable ? 1 : 0); + SqliteException.ThrowExceptionForRC(rc, Handle); } - private void LoadExtensionCore(string file, string? proc) + _extensionsEnabled = enable; + } + + /// + /// Loads a SQLite extension library. + /// + /// The shared library containing the extension. + /// The entry point. If null, the default entry point is used. + /// Extensions + public virtual void LoadExtension(string file, string? proc = null) + { + if (State == ConnectionState.Open) { - SqliteException? firstException = null; - foreach (var path in GetLoadExtensionPaths(file)) + int rc; + + if (!_extensionsEnabled) { - var rc = sqlite3_load_extension(Handle, utf8z.FromString(path), utf8z.FromString(proc), out var errmsg); - if (rc == SQLITE_OK) - { - return; - } + rc = sqlite3_db_config(Handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, out _); + SqliteException.ThrowExceptionForRC(rc, Handle); + } - if (firstException == null) - { - // We store the first exception so that error message looks more obvious if file appears in there - firstException = new SqliteException(Resources.SqliteNativeError(rc, errmsg.utf8_to_string()), rc, rc); - } + LoadExtensionCore(file, proc); + } + + _extensions ??= []; + _extensions.Add((file, proc)); + } + + private void LoadExtensionCore(string file, string? proc) + { + SqliteException? firstException = null; + foreach (var path in GetLoadExtensionPaths(file)) + { + var rc = sqlite3_load_extension(Handle, utf8z.FromString(path), utf8z.FromString(proc), out var errmsg); + if (rc == SQLITE_OK) + { + return; } - if (firstException != null) + if (firstException == null) { - throw firstException; + // We store the first exception so that error message looks more obvious if file appears in there + firstException = new SqliteException(Resources.SqliteNativeError(rc, errmsg.utf8_to_string()), rc, rc); } } - private static IEnumerable GetLoadExtensionPaths(string file) + if (firstException != null) + { + throw firstException; + } + } + + private static IEnumerable GetLoadExtensionPaths(string file) + { + // we always try original input first + yield return file; + + var dirName = Path.GetDirectoryName(file); + + // we don't try to guess directories for user, if they pass a path either absolute or relative - they're on their own + if (!string.IsNullOrEmpty(dirName)) { - // we always try original input first - yield return file; + yield break; + } - string? dirName = Path.GetDirectoryName(file); + var shouldTryAddingLibPrefix = + !file.StartsWith("lib", StringComparison.Ordinal) && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - // we don't try to guess directories for user, if they pass a path either absolute or relative - they're on their own - if (!string.IsNullOrEmpty(dirName)) - { - yield break; - } + if (shouldTryAddingLibPrefix) + { + yield return $"lib{file}"; + } - bool shouldTryAddingLibPrefix = !file.StartsWith("lib", StringComparison.Ordinal) && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + NativeDllSearchDirectories ??= GetNativeDllSearchDirectories(); + + foreach (var dir in NativeDllSearchDirectories) + { + yield return Path.Combine(dir, file); if (shouldTryAddingLibPrefix) { - yield return $"lib{file}"; + yield return Path.Combine(dir, $"lib{file}"); } + } + } - NativeDllSearchDirectories ??= GetNativeDllSearchDirectories(); + private static string[] GetNativeDllSearchDirectories() + { + var searchDirs = AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES") as string; + return string.IsNullOrEmpty(searchDirs) + ? [] + : searchDirs!.Split([Path.PathSeparator], StringSplitOptions.RemoveEmptyEntries); + } - foreach (string dir in NativeDllSearchDirectories) - { - yield return Path.Combine(dir, file); + /// + /// Backup of the connected database. + /// + /// The destination of the backup. + /// Online Backup + public virtual void BackupDatabase(SqliteConnection destination) + => BackupDatabase(destination, MainDatabaseName, MainDatabaseName); - if (shouldTryAddingLibPrefix) - { - yield return Path.Combine(dir, $"lib{file}"); - } - } + /// + /// Backup of the connected database. + /// + /// The destination of the backup. + /// The name of the destination database. + /// The name of the source database. + /// Online Backup + public virtual void BackupDatabase(SqliteConnection destination, string destinationName, string sourceName) + { + if (State != ConnectionState.Open) + { + throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(BackupDatabase))); } - private static string[] GetNativeDllSearchDirectories() + if (destination == null) { - string? searchDirs = AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES") as string; - - if (string.IsNullOrEmpty(searchDirs)) - { - return []; - } + throw new ArgumentNullException(nameof(destination)); + } - return searchDirs!.Split([ Path.PathSeparator ], StringSplitOptions.RemoveEmptyEntries); + var close = false; + if (destination.State != ConnectionState.Open) + { + destination.Open(); + close = true; } - /// - /// Backup of the connected database. - /// - /// The destination of the backup. - /// Online Backup - public virtual void BackupDatabase(SqliteConnection destination) - => BackupDatabase(destination, MainDatabaseName, MainDatabaseName); - - /// - /// Backup of the connected database. - /// - /// The destination of the backup. - /// The name of the destination database. - /// The name of the source database. - /// Online Backup - public virtual void BackupDatabase(SqliteConnection destination, string destinationName, string sourceName) + try { - if (State != ConnectionState.Open) + using var backup = sqlite3_backup_init(destination.Handle, destinationName, Handle, sourceName); + int rc; + if (backup.IsInvalid) { - throw new InvalidOperationException(Resources.CallRequiresOpenConnection(nameof(BackupDatabase))); + rc = sqlite3_errcode(destination.Handle); + SqliteException.ThrowExceptionForRC(rc, destination.Handle); } - if (destination == null) + rc = sqlite3_backup_step(backup, -1); + SqliteException.ThrowExceptionForRC(rc, destination.Handle); + } + finally + { + if (close) { - throw new ArgumentNullException(nameof(destination)); + destination.Close(); } + } + } - var close = false; - if (destination.State != ConnectionState.Open) - { - destination.Open(); - close = true; - } + /// + /// Returns schema information for the data source of this connection. + /// + /// Schema information. + public override DataTable GetSchema() + => GetSchema(DbMetaDataCollectionNames.MetaDataCollections); - try - { - using var backup = sqlite3_backup_init(destination.Handle, destinationName, Handle, sourceName); - int rc; - if (backup.IsInvalid) - { - rc = sqlite3_errcode(destination.Handle); - SqliteException.ThrowExceptionForRC(rc, destination.Handle); - } + /// + /// Returns schema information for the data source of this connection. + /// + /// The name of the schema. + /// Schema information. + public override DataTable GetSchema(string collectionName) + => GetSchema(collectionName, []); - rc = sqlite3_backup_step(backup, -1); - SqliteException.ThrowExceptionForRC(rc, destination.Handle); - } - finally + /// + /// Returns schema information for the data source of this connection. + /// + /// The name of the schema. + /// The restrictions. + /// Schema information. + public override DataTable GetSchema(string collectionName, string?[] restrictionValues) + { + if (restrictionValues is not null && restrictionValues.Length != 0) + { + throw new ArgumentException(Resources.TooManyRestrictions(collectionName)); + } + + if (string.Equals(collectionName, DbMetaDataCollectionNames.MetaDataCollections, StringComparison.OrdinalIgnoreCase)) + { + return new DataTable(DbMetaDataCollectionNames.MetaDataCollections) { - if (close) + Columns = { - destination.Close(); - } - } + DbMetaDataColumnNames.CollectionName, + { DbMetaDataColumnNames.NumberOfRestrictions, typeof(int) }, + { DbMetaDataColumnNames.NumberOfIdentifierParts, typeof(int) } + }, + Rows = { { DbMetaDataCollectionNames.MetaDataCollections, 0, 0 }, { DbMetaDataCollectionNames.ReservedWords, 0, 0 } } + }; } - /// - /// Returns schema information for the data source of this connection. - /// - /// Schema information. - public override DataTable GetSchema() - => GetSchema(DbMetaDataCollectionNames.MetaDataCollections); - - /// - /// Returns schema information for the data source of this connection. - /// - /// The name of the schema. - /// Schema information. - public override DataTable GetSchema(string collectionName) - => GetSchema(collectionName, []); - - /// - /// Returns schema information for the data source of this connection. - /// - /// The name of the schema. - /// The restrictions. - /// Schema information. - public override DataTable GetSchema(string collectionName, string?[] restrictionValues) + if (string.Equals(collectionName, DbMetaDataCollectionNames.ReservedWords, StringComparison.OrdinalIgnoreCase)) { - if (restrictionValues is not null && restrictionValues.Length != 0) - { - throw new ArgumentException(Resources.TooManyRestrictions(collectionName)); - } + var dataTable = new DataTable(DbMetaDataCollectionNames.ReservedWords) { Columns = { DbMetaDataColumnNames.ReservedWord } }; - if (string.Equals(collectionName, DbMetaDataCollectionNames.MetaDataCollections, StringComparison.OrdinalIgnoreCase)) - { - return new DataTable(DbMetaDataCollectionNames.MetaDataCollections) - { - Columns = - { - { DbMetaDataColumnNames.CollectionName }, - { DbMetaDataColumnNames.NumberOfRestrictions, typeof(int) }, - { DbMetaDataColumnNames.NumberOfIdentifierParts, typeof(int) } - }, - Rows = - { - new object[] { DbMetaDataCollectionNames.MetaDataCollections, 0, 0 }, - new object[] { DbMetaDataCollectionNames.ReservedWords, 0, 0 } - } - }; - } - else if (string.Equals(collectionName, DbMetaDataCollectionNames.ReservedWords, StringComparison.OrdinalIgnoreCase)) + int rc; + string keyword; + var count = sqlite3_keyword_count(); + for (var i = 0; i < count; i++) { - var dataTable = new DataTable(DbMetaDataCollectionNames.ReservedWords) - { - Columns = - { - { DbMetaDataColumnNames.ReservedWord } - } - }; + rc = sqlite3_keyword_name(i, out keyword); + SqliteException.ThrowExceptionForRC(rc, null); - int rc; - string keyword; - var count = sqlite3_keyword_count(); - for (var i = 0; i < count; i++) - { - rc = sqlite3_keyword_name(i, out keyword); - SqliteException.ThrowExceptionForRC(rc, null); + dataTable.Rows.Add(keyword); + } - dataTable.Rows.Add([keyword]); - } + return dataTable; + } - return dataTable; - } + throw new ArgumentException(Resources.UnknownCollection(collectionName)); + } - throw new ArgumentException(Resources.UnknownCollection(collectionName)); + private void CreateFunctionCore( + string name, + int arity, + TState state, + Func? function, + bool isDeterministic) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); } - private void CreateFunctionCore( - string name, - int arity, - TState state, - Func? function, - bool isDeterministic) + delegate_function_scalar? func = null; + if (function != null) { - if (name == null) + func = (ctx, user_data, args) => { - throw new ArgumentNullException(nameof(name)); - } + // TODO: Avoid allocation when niladic + var values = new SqliteParameterReader(name, args); - delegate_function_scalar? func = null; - if (function != null) - { - func = (ctx, user_data, args) => + try { - // TODO: Avoid allocation when niladic - var values = new SqliteParameterReader(name, args); + // TODO: Avoid closure by passing function via user_data + var result = function((TState)user_data, values); - 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) + { + sqlite3_result_error(ctx, ex.Message); - new SqliteResultBinder(ctx, result).Bind(); - } - catch (Exception ex) + if (ex is SqliteException sqlEx) { - sqlite3_result_error(ctx, ex.Message); - - if (ex is SqliteException sqlEx) - { - // NB: This must be called after sqlite3_result_error() - sqlite3_result_error_code(ctx, sqlEx.SqliteErrorCode); - } + // NB: This must be called after sqlite3_result_error() + sqlite3_result_error_code(ctx, sqlEx.SqliteErrorCode); } - }; - } + } + }; + } - var flags = isDeterministic ? SQLITE_DETERMINISTIC : 0; + var flags = isDeterministic ? SQLITE_DETERMINISTIC : 0; - if (State == ConnectionState.Open) - { - var rc = sqlite3_create_function( - Handle, - name, - arity, - flags, - state, - func); - SqliteException.ThrowExceptionForRC(rc, Handle); - } + if (State == ConnectionState.Open) + { + var rc = sqlite3_create_function( + Handle, + name, + arity, + flags, + state, + func); + SqliteException.ThrowExceptionForRC(rc, Handle); + } - _functions ??= new Dictionary<(string, int), (int, object?, delegate_function_scalar?)>(FunctionsKeyComparer.Instance); - _functions[(name, arity)] = (flags, state, func); + _functions ??= new Dictionary<(string, int), (int, object?, delegate_function_scalar?)>(FunctionsKeyComparer.Instance); + _functions[(name, arity)] = (flags, state, func); + } + + private void CreateAggregateCore( + string name, + int arity, + TAccumulate seed, + Func? func, + Func? resultSelector, + bool isDeterministic) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); } - private void CreateAggregateCore( - string name, - int arity, - TAccumulate seed, - Func? func, - Func? resultSelector, - bool isDeterministic) + delegate_function_aggregate_step? func_step = null; + if (func != null) { - if (name == null) + func_step = static (ctx, user_data, args) => { - throw new ArgumentNullException(nameof(name)); - } + var definition = (AggregateDefinition)user_data; + ctx.state ??= new AggregateContext(definition.Seed); - delegate_function_aggregate_step? func_step = null; - if (func != null) - { - func_step = static (ctx, user_data, args) => + var context = (AggregateContext)ctx.state; + if (context.Exception != null) { - var definition = (AggregateDefinition)user_data; - ctx.state ??= new AggregateContext(definition.Seed); + return; + } - var context = (AggregateContext)ctx.state; - if (context.Exception != null) - { - return; - } + // TODO: Avoid allocation when niladic + var reader = new SqliteParameterReader(definition.Name, args); + + try + { + // NB: No need to set ctx.state since we just mutate the instance + context.Accumulate = definition.Func!(context.Accumulate, reader); + } + catch (Exception ex) + { + context.Exception = ex; + } + }; + } - // TODO: Avoid allocation when niladic - var reader = new SqliteParameterReader(definition.Name, args); + delegate_function_aggregate_final? func_final = null; + if (resultSelector != null) + { + func_final = static (ctx, user_data) => + { + var definition = (AggregateDefinition)user_data; + ctx.state ??= new AggregateContext(definition.Seed); + var context = (AggregateContext)ctx.state; + + if (context.Exception == null) + { try { - // NB: No need to set ctx.state since we just mutate the instance - context.Accumulate = definition.Func!(context.Accumulate, reader); + var result = definition.ResultSelector!(context.Accumulate); + + new SqliteResultBinder(ctx, result).Bind(); } catch (Exception ex) { context.Exception = ex; } - }; - } + } - delegate_function_aggregate_final? func_final = null; - if (resultSelector != null) - { - func_final = static (ctx, user_data) => + if (context.Exception != null) { - var definition = (AggregateDefinition)user_data; - ctx.state ??= new AggregateContext(definition.Seed); + sqlite3_result_error(ctx, context.Exception.Message); - var context = (AggregateContext)ctx.state; - - if (context.Exception == null) + if (context.Exception is SqliteException sqlEx) { - try - { - var result = definition.ResultSelector!(context.Accumulate); - - new SqliteResultBinder(ctx, result).Bind(); - } - catch (Exception ex) - { - context.Exception = ex; - } + // NB: This must be called after sqlite3_result_error() + sqlite3_result_error_code(ctx, sqlEx.SqliteErrorCode); } + } + }; + } - if (context.Exception != null) - { - sqlite3_result_error(ctx, context.Exception.Message); + var flags = isDeterministic ? SQLITE_DETERMINISTIC : 0; + var state = new AggregateDefinition(name, seed, func, resultSelector); - if (context.Exception is SqliteException sqlEx) - { - // NB: This must be called after sqlite3_result_error() - sqlite3_result_error_code(ctx, sqlEx.SqliteErrorCode); - } - } - }; - } + if (State == ConnectionState.Open) + { + var rc = sqlite3_create_function( + Handle, + name, + arity, + flags, + state, + func_step, + func_final); + SqliteException.ThrowExceptionForRC(rc, Handle); + } - var flags = isDeterministic ? SQLITE_DETERMINISTIC : 0; - var state = new AggregateDefinition(name, seed, func, resultSelector); + _aggregates ??= + new Dictionary<(string, int), (int, object?, delegate_function_aggregate_step?, delegate_function_aggregate_final?)>( + FunctionsKeyComparer.Instance); + _aggregates[(name, arity)] = (flags, state, func_step, func_final); + } - if (State == ConnectionState.Open) - { - var rc = sqlite3_create_function( - Handle, - name, - arity, - flags, - state, - func_step, - func_final); - SqliteException.ThrowExceptionForRC(rc, Handle); - } + private static Func? IfNotNull( + object? x, + Func value) + => x != null ? value : null; - _aggregates ??= - new Dictionary<(string, int), (int, object?, delegate_function_aggregate_step?, delegate_function_aggregate_final?)>( - FunctionsKeyComparer.Instance); - _aggregates[(name, arity)] = (flags, state, func_step, func_final); - } + private static object?[] GetValues(SqliteValueReader reader) + { + var values = new object?[reader.FieldCount]; + reader.GetValues(values); - private static Func? IfNotNull( - object? x, - Func value) - => x != null ? value : null; + return values; + } - private static object?[] GetValues(SqliteValueReader reader) - { - var values = new object?[reader.FieldCount]; - reader.GetValues(values); + private sealed class AggregateDefinition( + string name, + TAccumulate seed, + Func? func, + Func? resultSelector) + { + public string Name { get; } = name; + public TAccumulate Seed { get; } = seed; + public Func? Func { get; } = func; + public Func? ResultSelector { get; } = resultSelector; + } - return values; - } + private sealed class AggregateContext(T seed) + { + public T Accumulate { get; set; } = seed; + public Exception? Exception { get; set; } + } - private sealed class AggregateDefinition( - string name, - TAccumulate seed, - Func? func, - Func? resultSelector) - { - public string Name { get; } = name; - public TAccumulate Seed { get; } = seed; - public Func? Func { get; } = func; - public Func? ResultSelector { get; } = resultSelector; - } + private sealed class FunctionsKeyComparer : IEqualityComparer<(string name, int arity)> + { + public static readonly FunctionsKeyComparer Instance = new(); - private sealed class AggregateContext(T seed) - { - public T Accumulate { get; set; } = seed; - public Exception? Exception { get; set; } - } + public bool Equals((string name, int arity) x, (string name, int arity) y) + => StringComparer.OrdinalIgnoreCase.Equals(x.name, y.name) + && x.arity == y.arity; - private sealed class FunctionsKeyComparer : IEqualityComparer<(string name, int arity)> + public int GetHashCode((string name, int arity) obj) { - public static readonly FunctionsKeyComparer Instance = new(); - - public bool Equals((string name, int arity) x, (string name, int arity) y) - => StringComparer.OrdinalIgnoreCase.Equals(x.name, y.name) - && x.arity == y.arity; + var nameHashCode = StringComparer.OrdinalIgnoreCase.GetHashCode(obj.name); + var arityHashCode = obj.arity.GetHashCode(); - public int GetHashCode((string name, int arity) obj) - { - var nameHashCode = StringComparer.OrdinalIgnoreCase.GetHashCode(obj.name); - var arityHashCode = obj.arity.GetHashCode(); - - return ((int)(((uint)nameHashCode << 5) | ((uint)nameHashCode >> 27)) + nameHashCode) ^ arityHashCode; - } + return ((int)(((uint)nameHashCode << 5) | ((uint)nameHashCode >> 27)) + nameHashCode) ^ arityHashCode; } } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionFactory.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionFactory.cs index 313b7876a23..1182ae0b20d 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionFactory.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionFactory.cs @@ -5,174 +5,172 @@ using System.Collections.Generic; using System.Threading; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +internal class SqliteConnectionFactory { - internal class SqliteConnectionFactory - { - public static readonly SqliteConnectionFactory Instance = new(); + public static readonly SqliteConnectionFactory Instance = new(); #pragma warning disable IDE0052 // Remove unread private members - private readonly Timer _pruneTimer; + private readonly Timer _pruneTimer; #pragma warning restore IDE0052 // Remove unread private members - private readonly List _idlePoolGroups = []; - private readonly List _poolsToRelease = []; - private readonly ReaderWriterLockSlim _lock = new(); + private readonly List _idlePoolGroups = []; + private readonly List _poolsToRelease = []; + private readonly ReaderWriterLockSlim _lock = new(); - private Dictionary _poolGroups = new(); + private Dictionary _poolGroups = new(); - protected SqliteConnectionFactory() - { - AppDomain.CurrentDomain.DomainUnload += (_, _) => ClearPools(); - AppDomain.CurrentDomain.ProcessExit += (_, _) => ClearPools(); + protected SqliteConnectionFactory() + { + AppDomain.CurrentDomain.DomainUnload += (_, _) => ClearPools(); + AppDomain.CurrentDomain.ProcessExit += (_, _) => ClearPools(); - _pruneTimer = new Timer(PruneCallback, null, TimeSpan.FromMinutes(4), TimeSpan.FromSeconds(30)); - } + _pruneTimer = new Timer(PruneCallback, null, TimeSpan.FromMinutes(4), TimeSpan.FromSeconds(30)); + } - public SqliteConnectionInternal GetConnection(SqliteConnection outerConnection) + public SqliteConnectionInternal GetConnection(SqliteConnection outerConnection) + { + var poolGroup = outerConnection.PoolGroup; + if (poolGroup is { IsDisabled: true, IsNonPooled: false }) { - var poolGroup = outerConnection.PoolGroup; - if (poolGroup is { IsDisabled: true, IsNonPooled: false }) - { - poolGroup = GetPoolGroup(poolGroup.ConnectionString); - outerConnection.PoolGroup = poolGroup; - } + poolGroup = GetPoolGroup(poolGroup.ConnectionString); + outerConnection.PoolGroup = poolGroup; + } - var pool = poolGroup.GetPool(); + var pool = poolGroup.GetPool(); - var connection = pool == null - ? new SqliteConnectionInternal(outerConnection.ConnectionOptions) - : pool.GetConnection(); - connection.Activate(outerConnection); + var connection = pool == null + ? new SqliteConnectionInternal(outerConnection.ConnectionOptions) + : pool.GetConnection(); + connection.Activate(outerConnection); - return connection; - } + return connection; + } - public SqliteConnectionPoolGroup GetPoolGroup(string connectionString) - { - _lock.EnterUpgradeableReadLock(); + public SqliteConnectionPoolGroup GetPoolGroup(string connectionString) + { + _lock.EnterUpgradeableReadLock(); - try + try + { + if (!_poolGroups.TryGetValue(connectionString, out var poolGroup) + || (poolGroup.IsDisabled + && !poolGroup.IsNonPooled)) { - if (!_poolGroups.TryGetValue(connectionString, out var poolGroup) - || (poolGroup.IsDisabled - && !poolGroup.IsNonPooled)) - { - var connectionOptions = new SqliteConnectionStringBuilder(connectionString); + var connectionOptions = new SqliteConnectionStringBuilder(connectionString); - _lock.EnterWriteLock(); + _lock.EnterWriteLock(); - try - { - if (!_poolGroups.TryGetValue(connectionString, out poolGroup)) - { - var isNonPooled = connectionOptions.DataSource == ":memory:" - || connectionOptions.Mode == SqliteOpenMode.Memory - || connectionOptions.DataSource.Length == 0 - || !connectionOptions.Pooling; - - poolGroup = new SqliteConnectionPoolGroup(connectionOptions, connectionString, isNonPooled); - _poolGroups.Add(connectionString, poolGroup); - } - } - finally + try + { + if (!_poolGroups.TryGetValue(connectionString, out poolGroup)) { - _lock.ExitWriteLock(); + var isNonPooled = connectionOptions.DataSource == ":memory:" + || connectionOptions.Mode == SqliteOpenMode.Memory + || connectionOptions.DataSource.Length == 0 + || !connectionOptions.Pooling; + + poolGroup = new SqliteConnectionPoolGroup(connectionOptions, connectionString, isNonPooled); + _poolGroups.Add(connectionString, poolGroup); } } - - return poolGroup; + finally + { + _lock.ExitWriteLock(); + } } - finally + + return poolGroup; + } + finally + { + _lock.ExitUpgradeableReadLock(); + } + } + + public void ReleasePool(SqliteConnectionPool pool, bool clearing) + { + pool.Shutdown(); + + lock (_poolsToRelease) + { + if (clearing) { - _lock.ExitUpgradeableReadLock(); + pool.Clear(); } + + _poolsToRelease.Add(pool); } + } - public void ReleasePool(SqliteConnectionPool pool, bool clearing) - { - pool.Shutdown(); + public void ClearPools() + { + _lock.EnterWriteLock(); - lock (_poolsToRelease) + try + { + foreach (var entry in _poolGroups) { - if (clearing) - { - pool.Clear(); - } - - _poolsToRelease.Add(pool); + entry.Value.Clear(); } } - - public void ClearPools() + finally { - _lock.EnterWriteLock(); + _lock.ExitWriteLock(); + } + } - try + private void PruneCallback(object? _) + { + lock (_poolsToRelease) + { + for (var i = _poolsToRelease.Count - 1; i >= 0; i--) { - foreach (var entry in _poolGroups) + var pool = _poolsToRelease[i]; + + pool.Clear(); + + if (pool.Count == 0) { - entry.Value.Clear(); + _poolsToRelease.Remove(pool); } } - finally - { - _lock.ExitWriteLock(); - } } - private void PruneCallback(object? _) + _lock.EnterWriteLock(); + + try { - lock (_poolsToRelease) + for (var i = _idlePoolGroups.Count - 1; i >= 0; i--) { - for (var i = _poolsToRelease.Count - 1; i >= 0; i--) - { - var pool = _poolsToRelease[i]; - - pool.Clear(); + var poolGroup = _idlePoolGroups[i]; - if (pool.Count == 0) - { - _poolsToRelease.Remove(pool); - } + if (!poolGroup.Clear()) + { + _idlePoolGroups.Remove(poolGroup); } } - _lock.EnterWriteLock(); - - try + var activePoolGroups = new Dictionary(); + foreach (var entry in _poolGroups) { + var poolGroup = entry.Value; - for (var i = _idlePoolGroups.Count - 1; i >= 0; i--) + if (poolGroup.Prune()) { - var poolGroup = _idlePoolGroups[i]; - - if (!poolGroup.Clear()) - { - _idlePoolGroups.Remove(poolGroup); - } + _idlePoolGroups.Add(poolGroup); } - - var activePoolGroups = new Dictionary(); - foreach (var entry in _poolGroups) + else { - var poolGroup = entry.Value; - - if (poolGroup.Prune()) - { - _idlePoolGroups.Add(poolGroup); - } - else - { - activePoolGroups.Add(entry.Key, poolGroup); - } + activePoolGroups.Add(entry.Key, poolGroup); } - - _poolGroups = activePoolGroups; - } - finally - { - _lock.ExitWriteLock(); } + + _poolGroups = activePoolGroups; + } + finally + { + _lock.ExitWriteLock(); } } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionInternal.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionInternal.cs index acb4e688cd2..cb7e7164867 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionInternal.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionInternal.cs @@ -7,243 +7,241 @@ using System.Threading; using Microsoft.Data.Sqlite.Properties; using SQLitePCL; - using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +internal class SqliteConnectionInternal { - internal class SqliteConnectionInternal - { - private const string DataDirectoryMacro = "|DataDirectory|"; + private const string DataDirectoryMacro = "|DataDirectory|"; - private readonly sqlite3 _db; - private readonly WeakReference _outerConnection = new(null); + private readonly sqlite3 _db; + private readonly WeakReference _outerConnection = new(null); - private SqliteConnectionPool? _pool; - private volatile bool _active; - private volatile bool _canBePooled = true; + private SqliteConnectionPool? _pool; + private volatile bool _active; + private volatile bool _canBePooled = true; - public SqliteConnectionInternal(SqliteConnectionStringBuilder connectionOptions, SqliteConnectionPool? pool = null) - { - var filename = connectionOptions.DataSource; - var flags = 0; + public SqliteConnectionInternal(SqliteConnectionStringBuilder connectionOptions, SqliteConnectionPool? pool = null) + { + var filename = connectionOptions.DataSource; + var flags = 0; - if (filename.StartsWith("file:", StringComparison.OrdinalIgnoreCase)) - { - flags |= SQLITE_OPEN_URI; - } + if (filename.StartsWith("file:", StringComparison.OrdinalIgnoreCase)) + { + flags |= SQLITE_OPEN_URI; + } - switch (connectionOptions.Mode) - { - case SqliteOpenMode.ReadOnly: - flags |= SQLITE_OPEN_READONLY; - break; - - case SqliteOpenMode.ReadWrite: - flags |= SQLITE_OPEN_READWRITE; - break; - - case SqliteOpenMode.Memory: - flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY; - if ((flags & SQLITE_OPEN_URI) == 0) - { - flags |= SQLITE_OPEN_URI; - filename = "file:" + filename; - } - - break; - - default: - Debug.Assert( - connectionOptions.Mode == SqliteOpenMode.ReadWriteCreate, - "connectionOptions.Mode is not ReadWriteCreate"); - flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; - break; - } + switch (connectionOptions.Mode) + { + case SqliteOpenMode.ReadOnly: + flags |= SQLITE_OPEN_READONLY; + break; - switch (connectionOptions.Cache) - { - case SqliteCacheMode.Shared: - flags |= SQLITE_OPEN_SHAREDCACHE; - break; - - case SqliteCacheMode.Private: - flags |= SQLITE_OPEN_PRIVATECACHE; - break; - - default: - Debug.Assert( - connectionOptions.Cache == SqliteCacheMode.Default, - "connectionOptions.Cache is not Default."); - break; - } + case SqliteOpenMode.ReadWrite: + flags |= SQLITE_OPEN_READWRITE; + break; - var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory") as string; - if (!string.IsNullOrEmpty(dataDirectory) - && (flags & SQLITE_OPEN_URI) == 0 - && !filename.Equals(":memory:", StringComparison.OrdinalIgnoreCase)) - { - if (filename.StartsWith(DataDirectoryMacro, StringComparison.InvariantCultureIgnoreCase)) - { - filename = Path.Combine(dataDirectory, filename.Substring(DataDirectoryMacro.Length)); - } - else if (!Path.IsPathRooted(filename)) + case SqliteOpenMode.Memory: + flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY; + if ((flags & SQLITE_OPEN_URI) == 0) { - filename = Path.Combine(dataDirectory, filename); + flags |= SQLITE_OPEN_URI; + filename = "file:" + filename; } - } - var vfs = !string.IsNullOrWhiteSpace(connectionOptions.Vfs) - ? connectionOptions.Vfs - : null; - var rc = sqlite3_open_v2(filename, out _db, flags, vfs: vfs); - try - { - SqliteException.ThrowExceptionForRC(rc, _db); + break; - if (connectionOptions.Password.Length != 0) - { - if (SQLitePCLExtensions.EncryptionSupported(out var libraryName) == false) - { - throw new InvalidOperationException(Resources.EncryptionNotSupported(libraryName)); - } - - // NB: SQLite doesn't support parameters in PRAGMA statements, so we escape the value using the - // quote function before concatenating. - var quotedPassword = ExecuteScalar( - "SELECT quote($password);", - connectionOptions.Password, - connectionOptions.DefaultTimeout); - ExecuteNonQuery( - "PRAGMA key = " + quotedPassword + ";", - connectionOptions.DefaultTimeout); + default: + Debug.Assert( + connectionOptions.Mode == SqliteOpenMode.ReadWriteCreate, + "connectionOptions.Mode is not ReadWriteCreate"); + flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + break; + } - if (SQLitePCLExtensions.EncryptionSupported() != false) - { - // NB: Forces decryption. Throws when the key is incorrect. - ExecuteNonQuery( - "SELECT COUNT(*) FROM sqlite_master;", - connectionOptions.DefaultTimeout); - } - } + switch (connectionOptions.Cache) + { + case SqliteCacheMode.Shared: + flags |= SQLITE_OPEN_SHAREDCACHE; + break; + + case SqliteCacheMode.Private: + flags |= SQLITE_OPEN_PRIVATECACHE; + break; + + default: + Debug.Assert( + connectionOptions.Cache == SqliteCacheMode.Default, + "connectionOptions.Cache is not Default."); + break; + } + + var dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory") as string; + if (!string.IsNullOrEmpty(dataDirectory) + && (flags & SQLITE_OPEN_URI) == 0 + && !filename.Equals(":memory:", StringComparison.OrdinalIgnoreCase)) + { + if (filename.StartsWith(DataDirectoryMacro, StringComparison.InvariantCultureIgnoreCase)) + { + filename = Path.Combine(dataDirectory, filename.Substring(DataDirectoryMacro.Length)); + } + else if (!Path.IsPathRooted(filename)) + { + filename = Path.Combine(dataDirectory, filename); + } + } + + var vfs = !string.IsNullOrWhiteSpace(connectionOptions.Vfs) + ? connectionOptions.Vfs + : null; + var rc = sqlite3_open_v2(filename, out _db, flags, vfs: vfs); + try + { + SqliteException.ThrowExceptionForRC(rc, _db); - if (connectionOptions.ForeignKeys.HasValue) + if (connectionOptions.Password.Length != 0) + { + if (SQLitePCLExtensions.EncryptionSupported(out var libraryName) == false) { - ExecuteNonQuery( - "PRAGMA foreign_keys = " + (connectionOptions.ForeignKeys.Value ? "1" : "0") + ";", - connectionOptions.DefaultTimeout); + throw new InvalidOperationException(Resources.EncryptionNotSupported(libraryName)); } - if (connectionOptions.RecursiveTriggers) + // NB: SQLite doesn't support parameters in PRAGMA statements, so we escape the value using the + // quote function before concatenating. + var quotedPassword = ExecuteScalar( + "SELECT quote($password);", + connectionOptions.Password, + connectionOptions.DefaultTimeout); + ExecuteNonQuery( + "PRAGMA key = " + quotedPassword + ";", + connectionOptions.DefaultTimeout); + + if (SQLitePCLExtensions.EncryptionSupported() != false) { + // NB: Forces decryption. Throws when the key is incorrect. ExecuteNonQuery( - "PRAGMA recursive_triggers = 1;", + "SELECT COUNT(*) FROM sqlite_master;", connectionOptions.DefaultTimeout); } } - catch + + if (connectionOptions.ForeignKeys.HasValue) { - _db.Dispose(); - throw; + ExecuteNonQuery( + "PRAGMA foreign_keys = " + (connectionOptions.ForeignKeys.Value ? "1" : "0") + ";", + connectionOptions.DefaultTimeout); } - _pool = pool; + if (connectionOptions.RecursiveTriggers) + { + ExecuteNonQuery( + "PRAGMA recursive_triggers = 1;", + connectionOptions.DefaultTimeout); + } + } + catch + { + _db.Dispose(); + throw; } - public bool Leaked - => _active && !_outerConnection.TryGetTarget(out _); + _pool = pool; + } - public bool CanBePooled - => _canBePooled && !_outerConnection.TryGetTarget(out _); + public bool Leaked + => _active && !_outerConnection.TryGetTarget(out _); - public sqlite3? Handle - => _db; + public bool CanBePooled + => _canBePooled && !_outerConnection.TryGetTarget(out _); - public void DoNotPool() - => _canBePooled = false; + public sqlite3? Handle + => _db; - public void Activate(SqliteConnection outerConnection) - { - _active = true; - _outerConnection.SetTarget(outerConnection); - } + public void DoNotPool() + => _canBePooled = false; - public void Close() + public void Activate(SqliteConnection outerConnection) + { + _active = true; + _outerConnection.SetTarget(outerConnection); + } + + public void Close() + { + if (_pool != null) { - if (_pool != null) - { - _pool.Return(this); - } - else - { - Dispose(); - } + _pool.Return(this); } - - public void Deactivate() + else { - if (_outerConnection.TryGetTarget(out var outerConnection)) - { - outerConnection!.Deactivate(); - } - - _outerConnection.SetTarget(null); - _active = false; + Dispose(); } + } - public void Dispose() + public void Deactivate() + { + if (_outerConnection.TryGetTarget(out var outerConnection)) { - _db.Dispose(); - _pool = null; + outerConnection!.Deactivate(); } - private void ExecuteNonQuery(string sql, int timeout) - => RetryWhileBusy(() => sqlite3_exec(_db, sql), timeout); + _outerConnection.SetTarget(null); + _active = false; + } - private string ExecuteScalar(string sql, string p1, int timeout) - { - var timer = Stopwatch.StartNew(); - sqlite3_stmt stmt = null!; - RetryWhileBusy(() => sqlite3_prepare_v2(_db, sql, out stmt), timeout, timer); - try - { - sqlite3_bind_text(stmt, 1, p1); + public void Dispose() + { + _db.Dispose(); + _pool = null; + } - RetryWhileBusy(() => sqlite3_step(stmt), () => sqlite3_reset(stmt), timeout, timer); + private void ExecuteNonQuery(string sql, int timeout) + => RetryWhileBusy(() => sqlite3_exec(_db, sql), timeout); - return sqlite3_column_text(stmt, 0).utf8_to_string(); - } - finally - { - stmt.Dispose(); - } - } + private string ExecuteScalar(string sql, string p1, int timeout) + { + var timer = Stopwatch.StartNew(); + sqlite3_stmt stmt = null!; + RetryWhileBusy(() => sqlite3_prepare_v2(_db, sql, out stmt), timeout, timer); + try + { + sqlite3_bind_text(stmt, 1, p1); - private void RetryWhileBusy(Func action, int timeout, Stopwatch? timer = null) - => RetryWhileBusy(action, () => { }, timeout, timer); + RetryWhileBusy(() => sqlite3_step(stmt), () => sqlite3_reset(stmt), timeout, timer); - private void RetryWhileBusy(Func action, Action reset, int timeout, Stopwatch? timer = null) + return sqlite3_column_text(stmt, 0).utf8_to_string(); + } + finally { - int rc; - timer ??= Stopwatch.StartNew(); + stmt.Dispose(); + } + } - while (IsBusy(rc = action())) - { - if (timeout != 0 - && timer.ElapsedMilliseconds >= timeout * 1000L) - { - break; - } + private void RetryWhileBusy(Func action, int timeout, Stopwatch? timer = null) + => RetryWhileBusy(action, () => { }, timeout, timer); - reset(); + private void RetryWhileBusy(Func action, Action reset, int timeout, Stopwatch? timer = null) + { + int rc; + timer ??= Stopwatch.StartNew(); - Thread.Sleep(150); + while (IsBusy(rc = action())) + { + if (timeout != 0 + && timer.ElapsedMilliseconds >= timeout * 1000L) + { + break; } - SqliteException.ThrowExceptionForRC(rc, _db); + reset(); + + Thread.Sleep(150); } - private static bool IsBusy(int rc) - => rc is SQLITE_LOCKED or SQLITE_BUSY or SQLITE_LOCKED_SHAREDCACHE; + SqliteException.ThrowExceptionForRC(rc, _db); } + + private static bool IsBusy(int rc) + => rc is SQLITE_LOCKED or SQLITE_BUSY or SQLITE_LOCKED_SHAREDCACHE; } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionPool.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionPool.cs index bfece9a88c0..841626879a6 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionPool.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionPool.cs @@ -6,69 +6,69 @@ using System.Linq; using System.Threading; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +internal class SqliteConnectionPool { - internal class SqliteConnectionPool - { - private static readonly Random _random = new(); + private static readonly Random _random = new(); - private readonly SqliteConnectionStringBuilder _connectionOptions; - private readonly List _connections = []; - private readonly Stack _warmPool = new(); - private readonly Stack _coldPool = new(); + private readonly SqliteConnectionStringBuilder _connectionOptions; + private readonly List _connections = []; + private readonly Stack _warmPool = new(); + private readonly Stack _coldPool = new(); - private Timer? _pruneTimer; - private State _state = State.Active; + private Timer? _pruneTimer; + private State _state = State.Active; - public SqliteConnectionPool(SqliteConnectionStringBuilder connectionOptions) + public SqliteConnectionPool(SqliteConnectionStringBuilder connectionOptions) + { + lock (_random) { - lock (_random) - { - // 2-4 minutes in 10 second intervals - var prunePeriod = TimeSpan.FromSeconds(_random.Next(2 * 6, 4 * 6) * 10); - _pruneTimer = new Timer(PruneCallback, null, prunePeriod, prunePeriod); - } - - _connectionOptions = connectionOptions; + // 2-4 minutes in 10 second intervals + var prunePeriod = TimeSpan.FromSeconds(_random.Next(2 * 6, 4 * 6) * 10); + _pruneTimer = new Timer(PruneCallback, null, prunePeriod, prunePeriod); } - public int Count - => _connections.Count; + _connectionOptions = connectionOptions; + } - public void Shutdown() - { - _state = State.Disabled; + public int Count + => _connections.Count; - _pruneTimer?.Dispose(); - _pruneTimer = null; - } + public void Shutdown() + { + _state = State.Disabled; - public SqliteConnectionInternal GetConnection() + _pruneTimer?.Dispose(); + _pruneTimer = null; + } + + public SqliteConnectionInternal GetConnection() + { + SqliteConnectionInternal? connection = null; + do { - SqliteConnectionInternal? connection = null; - do + lock (_connections) { - lock (_connections) + if (!TryPop(_warmPool, out connection) + && !TryPop(_coldPool, out connection) + && (Count % 2 == 1 || !ReclaimLeakedConnections())) { - if (!TryPop(_warmPool, out connection) - && !TryPop(_coldPool, out connection) - && (Count % 2 == 1 || !ReclaimLeakedConnections())) - { - connection = new SqliteConnectionInternal(_connectionOptions, this); - - _connections.Add(connection); - } + connection = new SqliteConnectionInternal(_connectionOptions, this); + + _connections.Add(connection); } } - while (connection == null); - - return connection; } + while (connection == null); - private static bool TryPop(Stack stack, out SqliteConnectionInternal? connection) - { + return connection; + } + + private static bool TryPop(Stack stack, out SqliteConnectionInternal? connection) + { #if NET5_0_OR_GREATER - return stack.TryPop(out connection); + return stack.TryPop(out connection); #else if (stack.Count > 0) { @@ -79,99 +79,98 @@ private static bool TryPop(Stack stack, out SqliteConn connection = null; return false; #endif - } + } - public void Return(SqliteConnectionInternal connection) + public void Return(SqliteConnectionInternal connection) + { + lock (_connections) { - lock (_connections) - { - connection.Deactivate(); + connection.Deactivate(); - if (_state != State.Disabled - && connection.CanBePooled) - { - _warmPool.Push(connection); - } - else - { - DisposeConnection(connection); - } + if (_state != State.Disabled + && connection.CanBePooled) + { + _warmPool.Push(connection); } - } - - public void Clear() - { - lock (_connections) + else { - foreach (var connection in _connections) - { - connection.DoNotPool(); - } - - while (TryPop(_warmPool, out var connection)) - { - DisposeConnection(connection!); - } - - while (TryPop(_coldPool, out var connection)) - { - DisposeConnection(connection!); - } - - ReclaimLeakedConnections(); + DisposeConnection(connection); } } + } - private void PruneCallback(object? _) + public void Clear() + { + lock (_connections) { - lock (_connections) + foreach (var connection in _connections) { - while (TryPop(_coldPool, out var connection)) - { - DisposeConnection(connection!); - } + connection.DoNotPool(); + } - while (TryPop(_warmPool, out var connection)) - { - _coldPool.Push(connection!); - } + while (TryPop(_warmPool, out var connection)) + { + DisposeConnection(connection!); } - } - private void DisposeConnection(SqliteConnectionInternal connection) - { - lock (_connections) + while (TryPop(_coldPool, out var connection)) { - _connections.Remove(connection); + DisposeConnection(connection!); } - connection.Dispose(); + ReclaimLeakedConnections(); } + } - private bool ReclaimLeakedConnections() + private void PruneCallback(object? _) + { + lock (_connections) { - var leakedConnectionsFound = false; - - List leakedConnections; - lock (_connections) + while (TryPop(_coldPool, out var connection)) { - leakedConnections = _connections.Where(c => c.Leaked).ToList(); + DisposeConnection(connection!); } - foreach (var connection in leakedConnections) + while (TryPop(_warmPool, out var connection)) { - leakedConnectionsFound = true; - - Return(connection); + _coldPool.Push(connection!); } + } + } - return leakedConnectionsFound; + private void DisposeConnection(SqliteConnectionInternal connection) + { + lock (_connections) + { + _connections.Remove(connection); } - private enum State + connection.Dispose(); + } + + private bool ReclaimLeakedConnections() + { + var leakedConnectionsFound = false; + + List leakedConnections; + lock (_connections) { - Active, - Disabled + leakedConnections = _connections.Where(c => c.Leaked).ToList(); + } + + foreach (var connection in leakedConnections) + { + leakedConnectionsFound = true; + + Return(connection); } + + return leakedConnectionsFound; + } + + private enum State + { + Active, + Disabled } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionPoolGroup.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionPoolGroup.cs index 284cd3f6ec1..cfa6e4d9c08 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionPoolGroup.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionPoolGroup.cs @@ -1,102 +1,101 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +internal class SqliteConnectionPoolGroup(SqliteConnectionStringBuilder connectionOptions, string connectionString, bool isNonPooled) { - internal class SqliteConnectionPoolGroup(SqliteConnectionStringBuilder connectionOptions, string connectionString, bool isNonPooled) - { - private SqliteConnectionPool? _pool; - private State _state = State.Active; + private SqliteConnectionPool? _pool; + private State _state = State.Active; - public SqliteConnectionStringBuilder ConnectionOptions { get; } = connectionOptions; - public string ConnectionString { get; } = connectionString; - public bool IsNonPooled { get; } = isNonPooled; + public SqliteConnectionStringBuilder ConnectionOptions { get; } = connectionOptions; + public string ConnectionString { get; } = connectionString; + public bool IsNonPooled { get; } = isNonPooled; - public bool IsDisabled - => _state == State.Disabled; + public bool IsDisabled + => _state == State.Disabled; - public SqliteConnectionPool? GetPool() + public SqliteConnectionPool? GetPool() + { + if (IsNonPooled) { - if (IsNonPooled) + lock (this) { - lock (this) - { - KeepAlive(); - } - - return null; + KeepAlive(); } - if (_pool == null) - { - lock (this) - { - if (_pool == null - && KeepAlive()) - { - _pool = new SqliteConnectionPool(ConnectionOptions); - } - } - } - - return _pool; + return null; } - public bool Clear() + if (_pool == null) { lock (this) { - if (_pool != null) + if (_pool == null + && KeepAlive()) { - SqliteConnectionFactory.Instance.ReleasePool(_pool, clearing: true); - _pool = null; + _pool = new SqliteConnectionPool(ConnectionOptions); } } - - return _pool != null; } - public bool Prune() + return _pool; + } + + public bool Clear() + { + lock (this) { - lock (this) + if (_pool != null) { - if (_pool?.Count == 0) - { - SqliteConnectionFactory.Instance.ReleasePool(_pool, clearing: false); - _pool = null; - } - - if (_pool == null) - { - if (_state == State.Active) - { - _state = State.Idle; - } - else if (_state == State.Idle) - { - _state = State.Disabled; - } - } - - return _state == State.Disabled; + SqliteConnectionFactory.Instance.ReleasePool(_pool, clearing: true); + _pool = null; } } - private bool KeepAlive() + return _pool != null; + } + + public bool Prune() + { + lock (this) { - if (_state == State.Idle) + if (_pool?.Count == 0) + { + SqliteConnectionFactory.Instance.ReleasePool(_pool, clearing: false); + _pool = null; + } + + if (_pool == null) { - _state = State.Active; + if (_state == State.Active) + { + _state = State.Idle; + } + else if (_state == State.Idle) + { + _state = State.Disabled; + } } - return _state == State.Active; + return _state == State.Disabled; } + } - private enum State + private bool KeepAlive() + { + if (_state == State.Idle) { - Active, - Idle, - Disabled + _state = State.Active; } + + return _state == State.Active; + } + + private enum State + { + Active, + Idle, + Disabled } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionStringBuilder.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionStringBuilder.cs index 624966b33fc..680f674b45c 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionStringBuilder.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionStringBuilder.cs @@ -11,490 +11,493 @@ using System.Globalization; using Microsoft.Data.Sqlite.Properties; -namespace Microsoft.Data.Sqlite -{ - /// - /// Provides a simple way to create and manage the contents of connection strings used by - /// . - /// - /// Connection Strings +namespace Microsoft.Data.Sqlite; + +/// +/// Provides a simple way to create and manage the contents of connection strings used by +/// . +/// +/// Connection Strings #if NET5_0_OR_GREATER - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2112:ReflectionToRequiresUnreferencedCode", - Justification = "Suppressing the same warnings as suppressed in the base DbConnectionStringBuilder. See https://github.com/dotnet/runtime/issues/97057")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2113:ReflectionToRequiresUnreferencedCode", - Justification = "Suppressing the same warnings as suppressed in the base DbConnectionStringBuilder. See https://github.com/dotnet/runtime/issues/97057")] +[UnconditionalSuppressMessage( + "ReflectionAnalysis", "IL2112:ReflectionToRequiresUnreferencedCode", + Justification = + "Suppressing the same warnings as suppressed in the base DbConnectionStringBuilder. See https://github.com/dotnet/runtime/issues/97057"), + UnconditionalSuppressMessage( + "ReflectionAnalysis", "IL2113:ReflectionToRequiresUnreferencedCode", + Justification = + "Suppressing the same warnings as suppressed in the base DbConnectionStringBuilder. See https://github.com/dotnet/runtime/issues/97057")] #endif - public class SqliteConnectionStringBuilder : DbConnectionStringBuilder +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 const string PasswordKeyword = "Password"; + private const string ForeignKeysKeyword = "Foreign Keys"; + private const string RecursiveTriggersKeyword = "Recursive Triggers"; + private const string DefaultTimeoutKeyword = "Default Timeout"; + private const string CommandTimeoutKeyword = "Command Timeout"; + private const string PoolingKeyword = "Pooling"; + private const string VfsKeyword = "Vfs"; + + private enum Keywords { - 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 const string PasswordKeyword = "Password"; - private const string ForeignKeysKeyword = "Foreign Keys"; - private const string RecursiveTriggersKeyword = "Recursive Triggers"; - private const string DefaultTimeoutKeyword = "Default Timeout"; - private const string CommandTimeoutKeyword = "Command Timeout"; - private const string PoolingKeyword = "Pooling"; - private const string VfsKeyword = "Vfs"; - - private enum Keywords + DataSource, + Mode, + Cache, + Password, + ForeignKeys, + RecursiveTriggers, + DefaultTimeout, + Pooling, + Vfs, + } + + private static readonly IReadOnlyList _validKeywords; + private static readonly IReadOnlyDictionary _keywords; + + private string _dataSource = string.Empty; + private SqliteOpenMode _mode = SqliteOpenMode.ReadWriteCreate; + private SqliteCacheMode _cache = SqliteCacheMode.Default; + private string _password = string.Empty; + private bool? _foreignKeys; + private bool _recursiveTriggers; + private int _defaultTimeout = 30; + private bool _pooling = true; + private string? _vfs; + + static SqliteConnectionStringBuilder() + { + var validKeywords = new string[9]; + validKeywords[(int)Keywords.DataSource] = DataSourceKeyword; + validKeywords[(int)Keywords.Mode] = ModeKeyword; + validKeywords[(int)Keywords.Cache] = CacheKeyword; + validKeywords[(int)Keywords.Password] = PasswordKeyword; + validKeywords[(int)Keywords.ForeignKeys] = ForeignKeysKeyword; + validKeywords[(int)Keywords.RecursiveTriggers] = RecursiveTriggersKeyword; + validKeywords[(int)Keywords.DefaultTimeout] = DefaultTimeoutKeyword; + validKeywords[(int)Keywords.Pooling] = PoolingKeyword; + validKeywords[(int)Keywords.Vfs] = VfsKeyword; + _validKeywords = validKeywords; + + _keywords = new Dictionary(12, StringComparer.OrdinalIgnoreCase) { - DataSource, - Mode, - Cache, - Password, - ForeignKeys, - RecursiveTriggers, - DefaultTimeout, - Pooling, - Vfs, - } + [DataSourceKeyword] = Keywords.DataSource, + [ModeKeyword] = Keywords.Mode, + [CacheKeyword] = Keywords.Cache, + [PasswordKeyword] = Keywords.Password, + [ForeignKeysKeyword] = Keywords.ForeignKeys, + [RecursiveTriggersKeyword] = Keywords.RecursiveTriggers, + [DefaultTimeoutKeyword] = Keywords.DefaultTimeout, + [PoolingKeyword] = Keywords.Pooling, + [VfsKeyword] = Keywords.Vfs, + + // aliases + [FilenameKeyword] = Keywords.DataSource, + [DataSourceNoSpaceKeyword] = Keywords.DataSource, + [CommandTimeoutKeyword] = Keywords.DefaultTimeout + }; + } + + /// + /// Initializes a new instance of the class. + /// + public SqliteConnectionStringBuilder() + { + } - private static readonly IReadOnlyList _validKeywords; - private static readonly IReadOnlyDictionary _keywords; + /// + /// Initializes a new instance of the class. + /// + /// + /// The initial connection string the builder will represent. Can be null. + /// + public SqliteConnectionStringBuilder(string? connectionString) + => ConnectionString = connectionString; - private string _dataSource = string.Empty; - private SqliteOpenMode _mode = SqliteOpenMode.ReadWriteCreate; - private SqliteCacheMode _cache = SqliteCacheMode.Default; - private string _password = string.Empty; - private bool? _foreignKeys; - private bool _recursiveTriggers; - private int _defaultTimeout = 30; - private bool _pooling = true; - private string? _vfs; + /// + /// Gets or sets the database file. + /// + /// The database file. + [AllowNull] + public virtual string DataSource + { + get => _dataSource; + set => base[DataSourceKeyword] = _dataSource = value ?? string.Empty; + } - static SqliteConnectionStringBuilder() + /// + /// Gets or sets the connection mode. + /// + /// The connection mode. + public virtual SqliteOpenMode Mode + { + get => _mode; + set => base[ModeKeyword] = _mode = value; + } + + /// + /// Gets a collection containing the keys used by the connection string. + /// + /// A collection containing the keys used by the connection string. + public override ICollection Keys + => new ReadOnlyCollection((string[])_validKeywords); + + /// + /// Gets a collection containing the values used by the connection string. + /// + /// A collection containing the values used by the connection string. + public override ICollection Values + { + get { - var validKeywords = new string[9]; - validKeywords[(int)Keywords.DataSource] = DataSourceKeyword; - validKeywords[(int)Keywords.Mode] = ModeKeyword; - validKeywords[(int)Keywords.Cache] = CacheKeyword; - validKeywords[(int)Keywords.Password] = PasswordKeyword; - validKeywords[(int)Keywords.ForeignKeys] = ForeignKeysKeyword; - validKeywords[(int)Keywords.RecursiveTriggers] = RecursiveTriggersKeyword; - validKeywords[(int)Keywords.DefaultTimeout] = DefaultTimeoutKeyword; - validKeywords[(int)Keywords.Pooling] = PoolingKeyword; - validKeywords[(int)Keywords.Vfs] = VfsKeyword; - _validKeywords = validKeywords; - - _keywords = new Dictionary(12, StringComparer.OrdinalIgnoreCase) + var values = new object?[_validKeywords.Count]; + for (var i = 0; i < _validKeywords.Count; i++) { - [DataSourceKeyword] = Keywords.DataSource, - [ModeKeyword] = Keywords.Mode, - [CacheKeyword] = Keywords.Cache, - [PasswordKeyword] = Keywords.Password, - [ForeignKeysKeyword] = Keywords.ForeignKeys, - [RecursiveTriggersKeyword] = Keywords.RecursiveTriggers, - [DefaultTimeoutKeyword] = Keywords.DefaultTimeout, - [PoolingKeyword] = Keywords.Pooling, - [VfsKeyword] = Keywords.Vfs, - - // aliases - [FilenameKeyword] = Keywords.DataSource, - [DataSourceNoSpaceKeyword] = Keywords.DataSource, - [CommandTimeoutKeyword] = Keywords.DefaultTimeout - }; - } + values[i] = GetAt((Keywords)i); + } - /// - /// Initializes a new instance of the class. - /// - public SqliteConnectionStringBuilder() - { + return new ReadOnlyCollection(values); } + } - /// - /// Initializes a new instance of the class. - /// - /// - /// The initial connection string the builder will represent. Can be null. - /// - public SqliteConnectionStringBuilder(string? connectionString) - => ConnectionString = connectionString; - - /// - /// Gets or sets the database file. - /// - /// The database file. - [AllowNull] - public virtual string DataSource - { - get => _dataSource; - set => base[DataSourceKeyword] = _dataSource = value ?? string.Empty; - } + /// + /// Gets or sets the caching mode used by the connection. + /// + /// The caching mode used by the connection. + public virtual SqliteCacheMode Cache + { + get => _cache; + set => base[CacheKeyword] = _cache = value; + } - /// - /// Gets or sets the connection mode. - /// - /// The connection mode. - public virtual SqliteOpenMode Mode - { - get => _mode; - set => base[ModeKeyword] = _mode = value; - } + /// + /// Gets or sets the encryption key. Warning, this has no effect when the native SQLite library doesn't + /// support encryption. When specified, PRAGMA key is sent immediately after opening the connection. + /// + /// The encryption key. + /// Encryption + [AllowNull] + public string Password + { + get => _password; + set => base[PasswordKeyword] = _password = value ?? string.Empty; + } - /// - /// Gets a collection containing the keys used by the connection string. - /// - /// A collection containing the keys used by the connection string. - public override ICollection Keys - => new ReadOnlyCollection((string[])_validKeywords); - - /// - /// Gets a collection containing the values used by the connection string. - /// - /// A collection containing the values used by the connection string. - public override ICollection Values + /// + /// Gets or sets a value indicating whether to enable foreign key constraints. When true, + /// PRAGMA foreign_keys = 1 is sent immediately after opening the connection. When false, + /// PRAGMA foreign_keys = 0 is sent. When null, no pragma is sent. There is no need to enable foreign + /// keys if, like in e_sqlite3, SQLITE_DEFAULT_FOREIGN_KEYS was used to compile the native library. + /// + /// A value indicating whether to enable foreign key constraints. + public bool? ForeignKeys + { + get => _foreignKeys; + set => base[ForeignKeysKeyword] = _foreignKeys = value; + } + + /// + /// Gets or sets a value indicating whether to enable recursive triggers. When true, + /// PRAGMA recursive_triggers is sent immediately after opening the connection. When false, no pragma + /// is sent. + /// + /// A value indicating whether to enable recursive triggers. + public bool RecursiveTriggers + { + get => _recursiveTriggers; + set => base[RecursiveTriggersKeyword] = _recursiveTriggers = value; + } + + /// + /// Gets or sets the default value. + /// + /// The default value. + public int DefaultTimeout + { + get => _defaultTimeout; + set => base[DefaultTimeoutKeyword] = _defaultTimeout = value; + } + + /// + /// Gets or sets a value indicating whether the connection will be pooled. + /// + /// A value indicating whether the connection will be pooled. + public bool Pooling + { + get => _pooling; + set => base[PoolingKeyword] = _pooling = value; + } + + /// + /// Gets or sets the SQLite VFS used by the connection. + /// + /// The SQLite VFS used by the connection. + /// SQLite VFS + public string? Vfs + { + get => _vfs; + set => base[VfsKeyword] = _vfs = value; + } + + /// + /// Gets or sets the value associated with the specified key. + /// + /// The key. + /// The value. + public override object? this[string keyword] + { +#pragma warning disable CS8764 // NB: this["Foreign Keys"] may return null + get => GetAt(GetIndex(keyword)); +#pragma warning restore CS8764 + set { - get + if (value == null) { - var values = new object?[_validKeywords.Count]; - for (var i = 0; i < _validKeywords.Count; i++) - { - values[i] = GetAt((Keywords)i); - } + Remove(keyword); - return new ReadOnlyCollection(values); + return; } - } - /// - /// Gets or sets the caching mode used by the connection. - /// - /// The caching mode used by the connection. - public virtual SqliteCacheMode Cache - { - get => _cache; - set => base[CacheKeyword] = _cache = value; - } + switch (GetIndex(keyword)) + { + case Keywords.DataSource: + DataSource = Convert.ToString(value, CultureInfo.InvariantCulture); + return; - /// - /// Gets or sets the encryption key. Warning, this has no effect when the native SQLite library doesn't - /// support encryption. When specified, PRAGMA key is sent immediately after opening the connection. - /// - /// The encryption key. - /// Encryption - [AllowNull] - public string Password - { - get => _password; - set => base[PasswordKeyword] = _password = value ?? string.Empty; - } + case Keywords.Mode: + Mode = ConvertToEnum(value); + return; - /// - /// Gets or sets a value indicating whether to enable foreign key constraints. When true, - /// PRAGMA foreign_keys = 1 is sent immediately after opening the connection. When false, - /// PRAGMA foreign_keys = 0 is sent. When null, no pragma is sent. There is no need to enable foreign - /// keys if, like in e_sqlite3, SQLITE_DEFAULT_FOREIGN_KEYS was used to compile the native library. - /// - /// A value indicating whether to enable foreign key constraints. - public bool? ForeignKeys - { - get => _foreignKeys; - set => base[ForeignKeysKeyword] = _foreignKeys = value; + case Keywords.Cache: + Cache = ConvertToEnum(value); + return; + + case Keywords.Password: + Password = Convert.ToString(value, CultureInfo.InvariantCulture); + return; + + case Keywords.ForeignKeys: + ForeignKeys = ConvertToNullableBoolean(value); + return; + + case Keywords.RecursiveTriggers: + RecursiveTriggers = Convert.ToBoolean(value, CultureInfo.InvariantCulture); + return; + + case Keywords.DefaultTimeout: + DefaultTimeout = Convert.ToInt32(value); + return; + + case Keywords.Pooling: + Pooling = Convert.ToBoolean(value, CultureInfo.InvariantCulture); + return; + case Keywords.Vfs: + Vfs = Convert.ToString(value, CultureInfo.InvariantCulture); + return; + + default: + Debug.Fail("Unexpected keyword: " + keyword); + return; + } } + } - /// - /// Gets or sets a value indicating whether to enable recursive triggers. When true, - /// PRAGMA recursive_triggers is sent immediately after opening the connection. When false, no pragma - /// is sent. - /// - /// A value indicating whether to enable recursive triggers. - public bool RecursiveTriggers + private static TEnum ConvertToEnum(object value) + where TEnum : struct + { + if (value is string stringValue) { - get => _recursiveTriggers; - set => base[RecursiveTriggersKeyword] = _recursiveTriggers = value; + return (TEnum)Enum.Parse(typeof(TEnum), stringValue, ignoreCase: true); } - /// - /// Gets or sets the default value. - /// - /// The default value. - public int DefaultTimeout + TEnum enumValue; + if (value is TEnum) { - get => _defaultTimeout; - set => base[DefaultTimeoutKeyword] = _defaultTimeout = value; + enumValue = (TEnum)value; } - - /// - /// Gets or sets a value indicating whether the connection will be pooled. - /// - /// A value indicating whether the connection will be pooled. - public bool Pooling + else if (value.GetType().IsEnum) { - get => _pooling; - set => base[PoolingKeyword] = _pooling = value; + throw new ArgumentException(Resources.ConvertFailed(value.GetType(), typeof(TEnum))); } - - /// - /// Gets or sets the SQLite VFS used by the connection. - /// - /// The SQLite VFS used by the connection. - /// SQLite VFS - public string? Vfs + else { - get => _vfs; - set => base[VfsKeyword] = _vfs = value; + enumValue = (TEnum)Enum.ToObject(typeof(TEnum), value); } - /// - /// Gets or sets the value associated with the specified key. - /// - /// The key. - /// The value. - public override object? this[string keyword] + if (!Enum.IsDefined(typeof(TEnum), enumValue)) { -#pragma warning disable CS8764 // NB: this["Foreign Keys"] may return null - get => GetAt(GetIndex(keyword)); -#pragma warning restore CS8764 - 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(value); - return; - - case Keywords.Cache: - Cache = ConvertToEnum(value); - return; - - case Keywords.Password: - Password = Convert.ToString(value, CultureInfo.InvariantCulture); - return; - - case Keywords.ForeignKeys: - ForeignKeys = ConvertToNullableBoolean(value); - return; - - case Keywords.RecursiveTriggers: - RecursiveTriggers = Convert.ToBoolean(value, CultureInfo.InvariantCulture); - return; - - case Keywords.DefaultTimeout: - DefaultTimeout = Convert.ToInt32(value); - return; - - case Keywords.Pooling: - Pooling = Convert.ToBoolean(value, CultureInfo.InvariantCulture); - return; - case Keywords.Vfs: - Vfs = Convert.ToString(value, CultureInfo.InvariantCulture); - return; - - default: - Debug.Fail("Unexpected keyword: " + keyword); - return; - } - } + throw new ArgumentOutOfRangeException( + nameof(value), + value, + Resources.InvalidEnumValue(typeof(TEnum), enumValue)); } - private static TEnum ConvertToEnum(object value) - where TEnum : struct - { - if (value is string stringValue) - { - return (TEnum)Enum.Parse(typeof(TEnum), stringValue, ignoreCase: true); - } + return enumValue; + } - TEnum enumValue; - if (value is TEnum) - { - enumValue = (TEnum)value; - } - else if (value.GetType().IsEnum) - { - throw new ArgumentException(Resources.ConvertFailed(value.GetType(), typeof(TEnum))); - } - else - { - enumValue = (TEnum)Enum.ToObject(typeof(TEnum), value); - } + private static bool? ConvertToNullableBoolean(object value) + => value is null or string { Length: 0 } + ? null + : Convert.ToBoolean(value, CultureInfo.InvariantCulture); - if (!Enum.IsDefined(typeof(TEnum), enumValue)) - { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - Resources.InvalidEnumValue(typeof(TEnum), enumValue)); - } + /// + /// Clears the contents of the builder. + /// + public override void Clear() + { + base.Clear(); - return enumValue; + for (var i = 0; i < _validKeywords.Count; i++) + { + Reset((Keywords)i); } + } - private static bool? ConvertToNullableBoolean(object value) - => value is null or string { Length: 0 } - ? null - : Convert.ToBoolean(value, CultureInfo.InvariantCulture); + /// + /// Determines whether the specified key is used by the connection string. + /// + /// The key to look for. + /// if it is used; otherwise, . + public override bool ContainsKey(string keyword) + => _keywords.ContainsKey(keyword); - /// - /// Clears the contents of the builder. - /// - public override void Clear() + /// + /// Removes the specified key and its value from the connection string. + /// + /// The key to remove. + /// if the key was used; otherwise, . + public override bool Remove(string keyword) + { + if (!_keywords.TryGetValue(keyword, out var index) + || !base.Remove(_validKeywords[(int)index])) { - base.Clear(); - - for (var i = 0; i < _validKeywords.Count; i++) - { - Reset((Keywords)i); - } + return false; } - /// - /// Determines whether the specified key is used by the connection string. - /// - /// The key to look for. - /// if it is used; otherwise, . - public override bool ContainsKey(string keyword) - => _keywords.ContainsKey(keyword); - - /// - /// Removes the specified key and its value from the connection string. - /// - /// The key to remove. - /// if the key was used; otherwise, . - public override bool Remove(string keyword) - { - if (!_keywords.TryGetValue(keyword, out var index) - || !base.Remove(_validKeywords[(int)index])) - { - return false; - } + Reset(index); - Reset(index); + return true; + } - return true; - } + /// + /// Determines whether the specified key should be serialized into the connection string. + /// + /// The key to check. + /// if it should be serialized; otherwise, . + public override bool ShouldSerialize(string keyword) + => _keywords.TryGetValue(keyword, out var index) && base.ShouldSerialize(_validKeywords[(int)index]); - /// - /// Determines whether the specified key should be serialized into the connection string. - /// - /// The key to check. - /// if it should be serialized; otherwise, . - public override bool ShouldSerialize(string keyword) - => _keywords.TryGetValue(keyword, out var index) && base.ShouldSerialize(_validKeywords[(int)index]); - - /// - /// Gets the value of the specified key if it is used. - /// - /// The key. - /// The value. - /// if the key was used; otherwise, . + /// + /// Gets the value of the specified key if it is used. + /// + /// The key. + /// The value. + /// if the key was used; otherwise, . #pragma warning disable CS8765 // NB: TryGetValue("Foreign Keys", out value) returns true, but value may be null - public override bool TryGetValue(string keyword, out object? value) + public override bool TryGetValue(string keyword, out object? value) #pragma warning restore CS8765 + { + if (!_keywords.TryGetValue(keyword, out var index)) { - if (!_keywords.TryGetValue(keyword, out var index)) - { - value = null; + value = null; - return false; - } + return false; + } - value = GetAt(index); + value = GetAt(index); - return true; - } + return true; + } - private object? GetAt(Keywords index) + private object? GetAt(Keywords index) + { + switch (index) { - switch (index) - { - case Keywords.DataSource: - return DataSource; + case Keywords.DataSource: + return DataSource; - case Keywords.Mode: - return Mode; + case Keywords.Mode: + return Mode; - case Keywords.Cache: - return Cache; + case Keywords.Cache: + return Cache; - case Keywords.Password: - return Password; + case Keywords.Password: + return Password; - case Keywords.ForeignKeys: - return ForeignKeys; + case Keywords.ForeignKeys: + return ForeignKeys; - case Keywords.RecursiveTriggers: - return RecursiveTriggers; + case Keywords.RecursiveTriggers: + return RecursiveTriggers; - case Keywords.DefaultTimeout: - return DefaultTimeout; + case Keywords.DefaultTimeout: + return DefaultTimeout; - case Keywords.Pooling: - return Pooling; + case Keywords.Pooling: + return Pooling; - case Keywords.Vfs: - return Vfs; + case Keywords.Vfs: + return Vfs; - default: - Debug.Fail("Unexpected keyword: " + index); - return null; - } + default: + Debug.Fail("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 static Keywords GetIndex(string keyword) + => !_keywords.TryGetValue(keyword, out var index) + ? throw new ArgumentException(Resources.KeywordNotSupported(keyword)) + : index; - private void Reset(Keywords index) + private void Reset(Keywords index) + { + switch (index) { - switch (index) - { - case Keywords.DataSource: - _dataSource = string.Empty; - return; + case Keywords.DataSource: + _dataSource = string.Empty; + return; - case Keywords.Mode: - _mode = SqliteOpenMode.ReadWriteCreate; - return; + case Keywords.Mode: + _mode = SqliteOpenMode.ReadWriteCreate; + return; - case Keywords.Cache: - _cache = SqliteCacheMode.Default; - return; + case Keywords.Cache: + _cache = SqliteCacheMode.Default; + return; - case Keywords.Password: - _password = string.Empty; - return; + case Keywords.Password: + _password = string.Empty; + return; - case Keywords.ForeignKeys: - _foreignKeys = null; - return; + case Keywords.ForeignKeys: + _foreignKeys = null; + return; - case Keywords.RecursiveTriggers: - _recursiveTriggers = false; - return; + case Keywords.RecursiveTriggers: + _recursiveTriggers = false; + return; - case Keywords.DefaultTimeout: - _defaultTimeout = 30; - return; + case Keywords.DefaultTimeout: + _defaultTimeout = 30; + return; - case Keywords.Pooling: - _pooling = true; - return; + case Keywords.Pooling: + _pooling = true; + return; - case Keywords.Vfs: - _vfs = null; - return; + case Keywords.Vfs: + _vfs = null; + return; - default: - Debug.Fail("Unexpected keyword: " + index); - return; - } + default: + Debug.Fail("Unexpected keyword: " + index); + return; } } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteDataReader.cs b/src/Microsoft.Data.Sqlite.Core/SqliteDataReader.cs index 3e9a21c6a2e..2537670988b 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteDataReader.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteDataReader.cs @@ -15,753 +15,750 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Provides methods for reading the result of a command executed against a SQLite database. +/// +/// Data Types +public class SqliteDataReader : DbDataReader { + private readonly SqliteCommand _command; + private readonly bool _closeConnection; + private TimeSpan _totalElapsedTime; + private IEnumerator? _stmtEnumerator; + private SqliteDataRecord? _record; + private bool _closed; + private int _recordsAffected = -1; + + internal SqliteDataReader( + SqliteCommand command, + IEnumerable stmts, + bool closeConnection) + { + _command = command; + _stmtEnumerator = stmts.GetEnumerator(); + _closeConnection = closeConnection; + } + /// - /// Provides methods for reading the result of a command executed against a SQLite database. + /// Gets the depth of nesting for the current row. Always zero. /// - /// Data Types - public class SqliteDataReader : DbDataReader - { - private readonly SqliteCommand _command; - private readonly bool _closeConnection; - private TimeSpan _totalElapsedTime; - private IEnumerator? _stmtEnumerator; - private SqliteDataRecord? _record; - private bool _closed; - private int _recordsAffected = -1; - - internal SqliteDataReader( - SqliteCommand command, - IEnumerable stmts, - bool closeConnection) - { - _command = command; - _stmtEnumerator = stmts.GetEnumerator(); - _closeConnection = closeConnection; - } + /// The depth of nesting for the current row. + public override int Depth + => 0; - /// - /// Gets the depth of nesting for the current row. Always zero. - /// - /// The depth of nesting for the current row. - public override int Depth - => 0; - - /// - /// Gets the number of columns in the current row. - /// - /// The number of columns in the current row. - public override int FieldCount - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(FieldCount))) - : (_record?.FieldCount ?? 0); - - /// - /// Gets a handle to underlying prepared statement. - /// - /// A handle to underlying prepared statement. - /// Interoperability - public virtual sqlite3_stmt? Handle - => _record?.Handle; - - /// - /// Gets a value indicating whether the data reader contains any rows. - /// - /// A value indicating whether the data reader contains any rows. - public override bool HasRows - => _record?.HasRows ?? false; - - /// - /// Gets a value indicating whether the data reader is closed. - /// - /// A value indicating whether the data reader is closed. - public override bool IsClosed - => _closed; - - /// - /// Gets the number of rows inserted, updated, or deleted. -1 for SELECT statements. - /// - /// The number of rows inserted, updated, or deleted. - public override int RecordsAffected - => _recordsAffected; - - /// - /// Gets the value of the specified column. - /// - /// The name of the column. The value is case-sensitive. - /// The value. - /// Data Types - public override object this[string name] - => _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record[name]; - - /// - /// Gets the value of the specified column. - /// - /// The zero-based column ordinal. - /// The value. - /// Data Types - public override object this[int ordinal] - => _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record[ordinal]; - - /// - /// Gets an enumerator that can be used to iterate through the rows in the data reader. - /// - /// The enumerator. - public override IEnumerator GetEnumerator() - => new DbEnumerator(this, closeReader: false); - - /// - /// Advances to the next row in the result set. - /// - /// if there are more rows; otherwise, . - public override bool Read() - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(Read))) - : (_record?.Read() ?? false); - - /// - /// Advances to the next result set for batched statements. - /// - /// if there are more result sets; otherwise, . - /// A SQLite error occurs during execution. - /// Batching - /// Database Errors - public override bool NextResult() - { - if (_closed) - { - throw new InvalidOperationException(Resources.DataReaderClosed(nameof(NextResult))); - } + /// + /// Gets the number of columns in the current row. + /// + /// The number of columns in the current row. + public override int FieldCount + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(FieldCount))) + : (_record?.FieldCount ?? 0); - if (_record != null) - { - _record.Dispose(); - _record = null; - } + /// + /// Gets a handle to underlying prepared statement. + /// + /// A handle to underlying prepared statement. + /// Interoperability + public virtual sqlite3_stmt? Handle + => _record?.Handle; - sqlite3_stmt stmt; - int rc; + /// + /// Gets a value indicating whether the data reader contains any rows. + /// + /// A value indicating whether the data reader contains any rows. + public override bool HasRows + => _record?.HasRows ?? false; - while (_stmtEnumerator!.MoveNext()) - { - try - { - stmt = _stmtEnumerator.Current; + /// + /// Gets a value indicating whether the data reader is closed. + /// + /// A value indicating whether the data reader is closed. + public override bool IsClosed + => _closed; - var timer = SharedStopwatch.StartNew(); + /// + /// Gets the number of rows inserted, updated, or deleted. -1 for SELECT statements. + /// + /// The number of rows inserted, updated, or deleted. + public override int RecordsAffected + => _recordsAffected; - while (IsBusy(rc = sqlite3_step(stmt))) - { - if (_command.CommandTimeout != 0 - && (_totalElapsedTime + timer.Elapsed).TotalMilliseconds >= _command.CommandTimeout * 1000L) - { - break; - } + /// + /// Gets the value of the specified column. + /// + /// The name of the column. The value is case-sensitive. + /// The value. + /// Data Types + public override object this[string name] + => _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record[name]; - sqlite3_reset(stmt); + /// + /// Gets the value of the specified column. + /// + /// The zero-based column ordinal. + /// The value. + /// Data Types + public override object this[int ordinal] + => _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record[ordinal]; - // TODO: Consider having an async path that uses Task.Delay() - Thread.Sleep(150); - } + /// + /// Gets an enumerator that can be used to iterate through the rows in the data reader. + /// + /// The enumerator. + public override IEnumerator GetEnumerator() + => new DbEnumerator(this, closeReader: false); + + /// + /// Advances to the next row in the result set. + /// + /// if there are more rows; otherwise, . + public override bool Read() + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(Read))) + : (_record?.Read() ?? false); + + /// + /// Advances to the next result set for batched statements. + /// + /// if there are more result sets; otherwise, . + /// A SQLite error occurs during execution. + /// Batching + /// Database Errors + public override bool NextResult() + { + if (_closed) + { + throw new InvalidOperationException(Resources.DataReaderClosed(nameof(NextResult))); + } - _totalElapsedTime += timer.Elapsed; + if (_record != null) + { + _record.Dispose(); + _record = null; + } - SqliteException.ThrowExceptionForRC(rc, _command.Connection!.Handle); + sqlite3_stmt stmt; + int rc; - // It's a SELECT statement - if (sqlite3_column_count(stmt) != 0) - { - _record = new SqliteDataRecord(stmt, rc != SQLITE_DONE, _command.Connection, AddChanges); + while (_stmtEnumerator!.MoveNext()) + { + try + { + stmt = _stmtEnumerator.Current; - return true; - } + var timer = SharedStopwatch.StartNew(); - while (rc != SQLITE_DONE) + while (IsBusy(rc = sqlite3_step(stmt))) + { + if (_command.CommandTimeout != 0 + && (_totalElapsedTime + timer.Elapsed).TotalMilliseconds >= _command.CommandTimeout * 1000L) { - rc = sqlite3_step(stmt); - SqliteException.ThrowExceptionForRC(rc, _command.Connection.Handle); + break; } sqlite3_reset(stmt); - var changes = sqlite3_changes(_command.Connection.Handle); - AddChanges(changes); + // TODO: Consider having an async path that uses Task.Delay() + Thread.Sleep(150); } - catch + + _totalElapsedTime += timer.Elapsed; + + SqliteException.ThrowExceptionForRC(rc, _command.Connection!.Handle); + + // It's a SELECT statement + if (sqlite3_column_count(stmt) != 0) { - sqlite3_reset(_stmtEnumerator.Current); - _stmtEnumerator.Dispose(); - _stmtEnumerator = null; - Dispose(); + _record = new SqliteDataRecord(stmt, rc != SQLITE_DONE, _command.Connection, AddChanges); - throw; + return true; } - } - return false; - } + while (rc != SQLITE_DONE) + { + rc = sqlite3_step(stmt); + SqliteException.ThrowExceptionForRC(rc, _command.Connection.Handle); + } - private static bool IsBusy(int rc) - => rc is SQLITE_LOCKED or SQLITE_BUSY or SQLITE_LOCKED_SHAREDCACHE; + sqlite3_reset(stmt); - private void AddChanges(int changes) - { - if (_recordsAffected == -1) - { - _recordsAffected = changes; + var changes = sqlite3_changes(_command.Connection.Handle); + AddChanges(changes); } - else + catch { - _recordsAffected += changes; + sqlite3_reset(_stmtEnumerator.Current); + _stmtEnumerator.Dispose(); + _stmtEnumerator = null; + Dispose(); + + throw; } } - /// - /// Closes the data reader. - /// - public override void Close() - => Dispose(true); - - /// - /// Releases any resources used by the data reader and closes it. - /// - /// - /// to release managed and unmanaged resources; - /// to release only unmanaged resources. - /// - protected override void Dispose(bool disposing) + return false; + } + + private static bool IsBusy(int rc) + => rc is SQLITE_LOCKED or SQLITE_BUSY or SQLITE_LOCKED_SHAREDCACHE; + + private void AddChanges(int changes) + { + if (_recordsAffected == -1) { - if (!disposing || _closed) - { - return; - } + _recordsAffected = changes; + } + else + { + _recordsAffected += changes; + } + } - _command.DataReader = null; + /// + /// Closes the data reader. + /// + public override void Close() + => Dispose(true); - _record?.Dispose(); - _record = null; + /// + /// Releases any resources used by the data reader and closes it. + /// + /// + /// to release managed and unmanaged resources; + /// to release only unmanaged resources. + /// + protected override void Dispose(bool disposing) + { + if (!disposing || _closed) + { + return; + } - if (_stmtEnumerator != null) + _command.DataReader = null; + + _record?.Dispose(); + _record = null; + + if (_stmtEnumerator != null) + { + try { - try - { - while (NextResult()) - { - } - } - catch + while (NextResult()) { } } + catch + { + } + } - _stmtEnumerator?.Dispose(); + _stmtEnumerator?.Dispose(); - _closed = true; + _closed = true; - if (_closeConnection) - { - _command.Connection!.Close(); - } + if (_closeConnection) + { + _command.Connection!.Close(); } + } + + /// + /// Gets the name of the specified column. + /// + /// The zero-based column ordinal. + /// The name of the column. + public override string GetName(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetName))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetName(ordinal); + + /// + /// Gets the ordinal of the specified column. + /// + /// The name of the column. + /// The zero-based column ordinal. + public override int GetOrdinal(string name) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetOrdinal))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetOrdinal(name); + + /// + /// Gets the declared data type name of the specified column. The storage class is returned for computed + /// columns. + /// + /// The zero-based column ordinal. + /// The data type name of the column. + /// Due to SQLite's dynamic type system, this may not reflect the actual type of the value. + /// Data Types + public override string GetDataTypeName(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDataTypeName))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetDataTypeName(ordinal); - /// - /// Gets the name of the specified column. - /// - /// The zero-based column ordinal. - /// The name of the column. - public override string GetName(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetName))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetName(ordinal); - - /// - /// Gets the ordinal of the specified column. - /// - /// The name of the column. - /// The zero-based column ordinal. - public override int GetOrdinal(string name) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetOrdinal))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetOrdinal(name); - - /// - /// Gets the declared data type name of the specified column. The storage class is returned for computed - /// columns. - /// - /// The zero-based column ordinal. - /// The data type name of the column. - /// Due to SQLite's dynamic type system, this may not reflect the actual type of the value. - /// Data Types - public override string GetDataTypeName(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDataTypeName))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetDataTypeName(ordinal); - - /// - /// Gets the data type of the specified column. - /// - /// The zero-based column ordinal. - /// The data type of the column. + /// + /// Gets the data type of the specified column. + /// + /// The zero-based column ordinal. + /// The data type of the column. #if NET8_0_OR_GREATER - [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] #endif - public override Type GetFieldType(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFieldType))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetFieldType(ordinal); - - /// - /// Gets a value indicating whether the specified column is . - /// - /// The zero-based column ordinal. - /// if the specified column is ; otherwise, . - public override bool IsDBNull(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(IsDBNull))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.IsDBNull(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override bool GetBoolean(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetBoolean))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetBoolean(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override byte GetByte(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetByte))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetByte(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override char GetChar(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetChar))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetChar(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override DateTime GetDateTime(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDateTime))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetDateTime(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public virtual DateTimeOffset GetDateTimeOffset(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDateTimeOffset))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetDateTimeOffset(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public virtual TimeSpan GetTimeSpan(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetTimeSpan))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetTimeSpan(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override decimal GetDecimal(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDecimal))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetDecimal(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override double GetDouble(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDouble))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetDouble(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override float GetFloat(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFloat))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetFloat(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override Guid GetGuid(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetGuid))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetGuid(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override short GetInt16(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetInt16))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetInt16(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override int GetInt32(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetInt32))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetInt32(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override long GetInt64(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetInt64))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetInt64(ordinal); - - /// - /// Gets the value of the specified column as a . - /// - /// The zero-based column ordinal. - /// The value of the column. - public override string GetString(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetString))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetString(ordinal); - - /// - /// Reads a stream of bytes from the specified column. Not supported. - /// - /// The zero-based column ordinal. - /// The index from which to begin the read operation. - /// The buffer into which the data is copied. - /// The index to which the data will be copied. - /// The maximum number of bytes to read. - /// The actual number of bytes read. - public override long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int bufferOffset, int length) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetBytes))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length); - - /// - /// Reads a stream of characters from the specified column. Not supported. - /// - /// The zero-based column ordinal. - /// The index from which to begin the read operation. - /// The buffer into which the data is copied. - /// The index to which the data will be copied. - /// The maximum number of characters to read. - /// The actual number of characters read. - public override long GetChars(int ordinal, long dataOffset, char[]? buffer, int bufferOffset, int length) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetChars))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetChars(ordinal, dataOffset, buffer, bufferOffset, length); - - /// - /// Retrieves data as a Stream. If the reader includes rowid (or any of its aliases), a - /// is returned. Otherwise, the all of the data is read into memory and a - /// is returned. - /// - /// The zero-based column ordinal. - /// The returned object. - /// BLOB I/O - public override Stream GetStream(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetStream))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetStream(ordinal); - - /// - /// Retrieves data as a . - /// - /// The zero-based column ordinal. - /// The returned object. - public override TextReader GetTextReader(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetTextReader))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetTextReader(ordinal); - - /// - /// Gets the value of the specified column. - /// - /// The type of the value. - /// The zero-based column ordinal. - /// The value of the column. - /// Data Types - public override T GetFieldValue(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFieldValue))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetFieldValue(ordinal); - - /// - /// Gets the value of the specified column. - /// - /// The zero-based column ordinal. - /// The value of the column. - /// Data Types - public override object GetValue(int ordinal) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetValue))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetValue(ordinal); - - /// - /// Gets the column values of the current row. - /// - /// An array into which the values are copied. - /// The number of values copied into the array. - /// Data Types - public override int GetValues(object?[] values) - => _closed - ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetValues))) - : _record == null - ? throw new InvalidOperationException(Resources.NoData) - : _record.GetValues(values); - - /// - /// Returns a System.Data.DataTable that describes the column metadata of the System.Data.Common.DbDataReader. - /// - /// A System.Data.DataTable that describes the column metadata. - /// Metadata - public override DataTable GetSchemaTable() + public override Type GetFieldType(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFieldType))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetFieldType(ordinal); + + /// + /// Gets a value indicating whether the specified column is . + /// + /// The zero-based column ordinal. + /// if the specified column is ; otherwise, . + public override bool IsDBNull(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(IsDBNull))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.IsDBNull(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override bool GetBoolean(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetBoolean))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetBoolean(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override byte GetByte(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetByte))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetByte(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override char GetChar(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetChar))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetChar(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override DateTime GetDateTime(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDateTime))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetDateTime(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public virtual DateTimeOffset GetDateTimeOffset(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDateTimeOffset))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetDateTimeOffset(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public virtual TimeSpan GetTimeSpan(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetTimeSpan))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetTimeSpan(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override decimal GetDecimal(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDecimal))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetDecimal(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override double GetDouble(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDouble))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetDouble(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override float GetFloat(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFloat))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetFloat(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override Guid GetGuid(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetGuid))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetGuid(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override short GetInt16(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetInt16))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetInt16(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override int GetInt32(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetInt32))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetInt32(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override long GetInt64(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetInt64))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetInt64(ordinal); + + /// + /// Gets the value of the specified column as a . + /// + /// The zero-based column ordinal. + /// The value of the column. + public override string GetString(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetString))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetString(ordinal); + + /// + /// Reads a stream of bytes from the specified column. Not supported. + /// + /// The zero-based column ordinal. + /// The index from which to begin the read operation. + /// The buffer into which the data is copied. + /// The index to which the data will be copied. + /// The maximum number of bytes to read. + /// The actual number of bytes read. + public override long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int bufferOffset, int length) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetBytes))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length); + + /// + /// Reads a stream of characters from the specified column. Not supported. + /// + /// The zero-based column ordinal. + /// The index from which to begin the read operation. + /// The buffer into which the data is copied. + /// The index to which the data will be copied. + /// The maximum number of characters to read. + /// The actual number of characters read. + public override long GetChars(int ordinal, long dataOffset, char[]? buffer, int bufferOffset, int length) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetChars))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetChars(ordinal, dataOffset, buffer, bufferOffset, length); + + /// + /// Retrieves data as a Stream. If the reader includes rowid (or any of its aliases), a + /// is returned. Otherwise, the all of the data is read into memory and a + /// is returned. + /// + /// The zero-based column ordinal. + /// The returned object. + /// BLOB I/O + public override Stream GetStream(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetStream))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetStream(ordinal); + + /// + /// Retrieves data as a . + /// + /// The zero-based column ordinal. + /// The returned object. + public override TextReader GetTextReader(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetTextReader))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetTextReader(ordinal); + + /// + /// Gets the value of the specified column. + /// + /// The type of the value. + /// The zero-based column ordinal. + /// The value of the column. + /// Data Types + public override T GetFieldValue(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFieldValue))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetFieldValue(ordinal); + + /// + /// Gets the value of the specified column. + /// + /// The zero-based column ordinal. + /// The value of the column. + /// Data Types + public override object GetValue(int ordinal) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetValue))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetValue(ordinal); + + /// + /// Gets the column values of the current row. + /// + /// An array into which the values are copied. + /// The number of values copied into the array. + /// Data Types + public override int GetValues(object?[] values) + => _closed + ? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetValues))) + : _record == null + ? throw new InvalidOperationException(Resources.NoData) + : _record.GetValues(values); + + /// + /// Returns a System.Data.DataTable that describes the column metadata of the System.Data.Common.DbDataReader. + /// + /// A System.Data.DataTable that describes the column metadata. + /// Metadata + public override DataTable GetSchemaTable() + { + if (_closed) { - if (_closed) - { - throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetSchemaTable))); - } + throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetSchemaTable))); + } - if (_record == null) - { - throw new InvalidOperationException(Resources.NoData); - } + if (_record == null) + { + throw new InvalidOperationException(Resources.NoData); + } - var schemaTable = new DataTable("SchemaTable"); - - var columnNameColumn = new DataColumn(SchemaTableColumn.ColumnName, typeof(string)); - var columnOrdinalColumn = new DataColumn(SchemaTableColumn.ColumnOrdinal, typeof(int)); - var columnSizeColumn = new DataColumn(SchemaTableColumn.ColumnSize, typeof(int)); - var numericPrecisionColumn = new DataColumn(SchemaTableColumn.NumericPrecision, typeof(short)); - var numericScaleColumn = new DataColumn(SchemaTableColumn.NumericScale, typeof(short)); - var dataTypeColumn = CreateDataTypeColumn(); - var dataTypeNameColumn = new DataColumn("DataTypeName", typeof(string)); - - var isLongColumn = new DataColumn(SchemaTableColumn.IsLong, typeof(bool)); - var allowDBNullColumn = new DataColumn(SchemaTableColumn.AllowDBNull, typeof(bool)); - - var isUniqueColumn = new DataColumn(SchemaTableColumn.IsUnique, typeof(bool)); - var isKeyColumn = new DataColumn(SchemaTableColumn.IsKey, typeof(bool)); - var isAutoIncrementColumn = new DataColumn(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool)); - - var baseCatalogNameColumn = new DataColumn(SchemaTableOptionalColumn.BaseCatalogName, typeof(string)); - var baseSchemaNameColumn = new DataColumn(SchemaTableColumn.BaseSchemaName, typeof(string)); - var baseTableNameColumn = new DataColumn(SchemaTableColumn.BaseTableName, typeof(string)); - var baseColumnNameColumn = new DataColumn(SchemaTableColumn.BaseColumnName, typeof(string)); - - var baseServerNameColumn = new DataColumn(SchemaTableOptionalColumn.BaseServerName, typeof(string)); - var isAliasedColumn = new DataColumn(SchemaTableColumn.IsAliased, typeof(bool)); - var isExpressionColumn = new DataColumn(SchemaTableColumn.IsExpression, typeof(bool)); - - var columns = schemaTable.Columns; - - columns.Add(columnNameColumn); - columns.Add(columnOrdinalColumn); - columns.Add(columnSizeColumn); - columns.Add(numericPrecisionColumn); - columns.Add(numericScaleColumn); - columns.Add(isUniqueColumn); - columns.Add(isKeyColumn); - columns.Add(baseServerNameColumn); - columns.Add(baseCatalogNameColumn); - columns.Add(baseColumnNameColumn); - columns.Add(baseSchemaNameColumn); - columns.Add(baseTableNameColumn); - columns.Add(dataTypeColumn); - columns.Add(dataTypeNameColumn); - columns.Add(allowDBNullColumn); - columns.Add(isAliasedColumn); - columns.Add(isExpressionColumn); - columns.Add(isAutoIncrementColumn); - columns.Add(isLongColumn); - - for (var i = 0; i < FieldCount; i++) + var schemaTable = new DataTable("SchemaTable"); + + var columnNameColumn = new DataColumn(SchemaTableColumn.ColumnName, typeof(string)); + var columnOrdinalColumn = new DataColumn(SchemaTableColumn.ColumnOrdinal, typeof(int)); + var columnSizeColumn = new DataColumn(SchemaTableColumn.ColumnSize, typeof(int)); + var numericPrecisionColumn = new DataColumn(SchemaTableColumn.NumericPrecision, typeof(short)); + var numericScaleColumn = new DataColumn(SchemaTableColumn.NumericScale, typeof(short)); + var dataTypeColumn = CreateDataTypeColumn(); + var dataTypeNameColumn = new DataColumn("DataTypeName", typeof(string)); + + var isLongColumn = new DataColumn(SchemaTableColumn.IsLong, typeof(bool)); + var allowDBNullColumn = new DataColumn(SchemaTableColumn.AllowDBNull, typeof(bool)); + + var isUniqueColumn = new DataColumn(SchemaTableColumn.IsUnique, typeof(bool)); + var isKeyColumn = new DataColumn(SchemaTableColumn.IsKey, typeof(bool)); + var isAutoIncrementColumn = new DataColumn(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool)); + + var baseCatalogNameColumn = new DataColumn(SchemaTableOptionalColumn.BaseCatalogName, typeof(string)); + var baseSchemaNameColumn = new DataColumn(SchemaTableColumn.BaseSchemaName, typeof(string)); + var baseTableNameColumn = new DataColumn(SchemaTableColumn.BaseTableName, typeof(string)); + var baseColumnNameColumn = new DataColumn(SchemaTableColumn.BaseColumnName, typeof(string)); + + var baseServerNameColumn = new DataColumn(SchemaTableOptionalColumn.BaseServerName, typeof(string)); + var isAliasedColumn = new DataColumn(SchemaTableColumn.IsAliased, typeof(bool)); + var isExpressionColumn = new DataColumn(SchemaTableColumn.IsExpression, typeof(bool)); + + var columns = schemaTable.Columns; + + columns.Add(columnNameColumn); + columns.Add(columnOrdinalColumn); + columns.Add(columnSizeColumn); + columns.Add(numericPrecisionColumn); + columns.Add(numericScaleColumn); + columns.Add(isUniqueColumn); + columns.Add(isKeyColumn); + columns.Add(baseServerNameColumn); + columns.Add(baseCatalogNameColumn); + columns.Add(baseColumnNameColumn); + columns.Add(baseSchemaNameColumn); + columns.Add(baseTableNameColumn); + columns.Add(dataTypeColumn); + columns.Add(dataTypeNameColumn); + columns.Add(allowDBNullColumn); + columns.Add(isAliasedColumn); + columns.Add(isExpressionColumn); + columns.Add(isAutoIncrementColumn); + columns.Add(isLongColumn); + + for (var i = 0; i < FieldCount; i++) + { + var schemaRow = schemaTable.NewRow(); + schemaRow[columnNameColumn] = GetName(i); + schemaRow[columnOrdinalColumn] = i; + schemaRow[columnSizeColumn] = -1; + schemaRow[numericPrecisionColumn] = DBNull.Value; + schemaRow[numericScaleColumn] = DBNull.Value; + schemaRow[baseServerNameColumn] = _command.Connection!.DataSource; + var databaseName = sqlite3_column_database_name(_record.Handle, i).utf8_to_string(); + schemaRow[baseCatalogNameColumn] = databaseName; + var columnName = sqlite3_column_origin_name(_record.Handle, i).utf8_to_string(); + schemaRow[baseColumnNameColumn] = columnName; + schemaRow[baseSchemaNameColumn] = DBNull.Value; + var tableName = sqlite3_column_table_name(_record.Handle, i).utf8_to_string(); + schemaRow[baseTableNameColumn] = tableName; + schemaRow[dataTypeColumn] = GetFieldType(i); + var dataTypeName = GetDataTypeName(i); + schemaRow[dataTypeNameColumn] = dataTypeName; + var isAliased = columnName != GetName(i); + schemaRow[isAliasedColumn] = isAliased; + schemaRow[isExpressionColumn] = columnName == null; + schemaRow[isLongColumn] = DBNull.Value; + + var eponymousVirtualTable = false; + if (tableName != null + && columnName != null) { - var schemaRow = schemaTable.NewRow(); - schemaRow[columnNameColumn] = GetName(i); - schemaRow[columnOrdinalColumn] = i; - schemaRow[columnSizeColumn] = -1; - schemaRow[numericPrecisionColumn] = DBNull.Value; - schemaRow[numericScaleColumn] = DBNull.Value; - schemaRow[baseServerNameColumn] = _command.Connection!.DataSource; - var databaseName = sqlite3_column_database_name(_record.Handle, i).utf8_to_string(); - schemaRow[baseCatalogNameColumn] = databaseName; - var columnName = sqlite3_column_origin_name(_record.Handle, i).utf8_to_string(); - schemaRow[baseColumnNameColumn] = columnName; - schemaRow[baseSchemaNameColumn] = DBNull.Value; - var tableName = sqlite3_column_table_name(_record.Handle, i).utf8_to_string(); - schemaRow[baseTableNameColumn] = tableName; - schemaRow[dataTypeColumn] = GetFieldType(i); - var dataTypeName = GetDataTypeName(i); - schemaRow[dataTypeNameColumn] = dataTypeName; - var isAliased = columnName != GetName(i); - schemaRow[isAliasedColumn] = isAliased; - schemaRow[isExpressionColumn] = columnName == null; - schemaRow[isLongColumn] = DBNull.Value; - - var eponymousVirtualTable = false; - if (tableName != null - && columnName != null) + using (var command = _command.Connection.CreateCommand()) { - 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[isUniqueColumn] = !isAliased && cnt != 0; - - command.Parameters.Clear(); - var columnType = "typeof(\"" + columnName.Replace("\"", "\"\"") + "\")"; - command.CommandText = new StringBuilder() - .AppendLine($"SELECT {columnType}") - .AppendLine($"FROM \"{tableName.Replace("\"", "\"\"")}\"") - .AppendLine($"WHERE {columnType} != 'null'") - .AppendLine($"GROUP BY {columnType}") - .AppendLine("ORDER BY count() DESC") - .AppendLine("LIMIT 1;").ToString(); - - var type = (string?)command.ExecuteScalar(); - schemaRow[dataTypeColumn] = - (type != null) - ? SqliteDataRecord.GetFieldType(type) - : SqliteDataRecord.GetFieldTypeFromSqliteType( - SqliteDataRecord.Sqlite3AffinityType(dataTypeName)); - - command.CommandText = "SELECT COUNT(*) FROM sqlite_master WHERE name = $name AND type IN ('table', 'view')"; - command.Parameters.AddWithValue("$name", tableName); - - eponymousVirtualTable = (long)command.ExecuteScalar()! == 0L; - } - - if (databaseName != null - && !eponymousVirtualTable) - { - var rc = 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[isKeyColumn] = primaryKey != 0; - schemaRow[allowDBNullColumn] = isAliased || notNull == 0; - schemaRow[isAutoIncrementColumn] = autoInc != 0; - } + 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[isUniqueColumn] = !isAliased && cnt != 0; + + command.Parameters.Clear(); + var columnType = "typeof(\"" + columnName.Replace("\"", "\"\"") + "\")"; + command.CommandText = new StringBuilder() + .AppendLine($"SELECT {columnType}") + .AppendLine($"FROM \"{tableName.Replace("\"", "\"\"")}\"") + .AppendLine($"WHERE {columnType} != 'null'") + .AppendLine($"GROUP BY {columnType}") + .AppendLine("ORDER BY count() DESC") + .AppendLine("LIMIT 1;").ToString(); + + var type = (string?)command.ExecuteScalar(); + schemaRow[dataTypeColumn] = + (type != null) + ? SqliteDataRecord.GetFieldType(type) + : SqliteDataRecord.GetFieldTypeFromSqliteType( + SqliteDataRecord.Sqlite3AffinityType(dataTypeName)); + + command.CommandText = "SELECT COUNT(*) FROM sqlite_master WHERE name = $name AND type IN ('table', 'view')"; + command.Parameters.AddWithValue("$name", tableName); + + eponymousVirtualTable = (long)command.ExecuteScalar()! == 0L; } - schemaTable.Rows.Add(schemaRow); + if (databaseName != null + && !eponymousVirtualTable) + { + var rc = 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[isKeyColumn] = primaryKey != 0; + schemaRow[allowDBNullColumn] = isAliased || notNull == 0; + schemaRow[isAutoIncrementColumn] = autoInc != 0; + } } - return schemaTable; + schemaTable.Rows.Add(schemaRow); + } + + return schemaTable; #if NET6_0_OR_GREATER - [UnconditionalSuppressMessage("Trimming", "IL2111:Method with parameters or return value with `DynamicallyAccessedMembersAttribute`" - + " is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.", - Justification = "This is about System.Type.TypeInitializer.get. It is accessed via reflection" - + " as the type parameter in DataColumn is annotated with DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties" + - " However, reflection is only used for nullable columns.")] + [UnconditionalSuppressMessage( + "Trimming", "IL2111:Method with parameters or return value with `DynamicallyAccessedMembersAttribute`" + + " is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.", + Justification = "This is about System.Type.TypeInitializer.get. It is accessed via reflection" + + " as the type parameter in DataColumn is annotated with DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties" + + " However, reflection is only used for nullable columns.")] #endif - static DataColumn CreateDataTypeColumn() - => new(SchemaTableColumn.DataType, typeof(Type)) - { - AllowDBNull = false - }; - } + static DataColumn CreateDataTypeColumn() + => new(SchemaTableColumn.DataType, typeof(Type)) { AllowDBNull = false }; } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs b/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs index def5e0e2b28..7257603d51c 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs @@ -12,507 +12,505 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite -{ +namespace Microsoft.Data.Sqlite; - internal class SqliteDataRecord(sqlite3_stmt stmt, bool hasRows, SqliteConnection connection, Action addChanges) - : SqliteValueReader, IDisposable +internal class SqliteDataRecord(sqlite3_stmt stmt, bool hasRows, SqliteConnection connection, Action addChanges) + : SqliteValueReader, IDisposable +{ + internal class RowIdInfo(int ordinal, string tableName) { - internal class RowIdInfo(int ordinal, string tableName) - { - public int Ordinal { get; set; } = ordinal; - public string TableName { get; set; } = tableName; - } + public int Ordinal { get; set; } = ordinal; + public string TableName { get; set; } = tableName; + } - private byte[][]? _blobCache; - private int?[]? _typeCache; - private Dictionary? _columnNameOrdinalCache; - private string[]? _columnNameCache; - private bool _stepped; - readonly Dictionary RowIds = new Dictionary(); + private byte[][]? _blobCache; + private int?[]? _typeCache; + private Dictionary? _columnNameOrdinalCache; + private string[]? _columnNameCache; + private bool _stepped; + private readonly Dictionary RowIds = new(); - private bool _alreadyThrown; - private bool _alreadyAddedChanges; + private bool _alreadyThrown; + private bool _alreadyAddedChanges; - public virtual object this[string name] - => GetValue(GetOrdinal(name)); + public virtual object this[string name] + => GetValue(GetOrdinal(name)); - public virtual object this[int ordinal] - => GetValue(ordinal); + public virtual object this[int ordinal] + => GetValue(ordinal); - public override int FieldCount - => sqlite3_column_count(Handle); + public override int FieldCount + => sqlite3_column_count(Handle); - public sqlite3_stmt Handle { get; } = stmt; + public sqlite3_stmt Handle { get; } = stmt; - public bool HasRows { get; } = hasRows; + public bool HasRows { get; } = hasRows; - public override bool IsDBNull(int ordinal) - => !_stepped || sqlite3_data_count(Handle) == 0 - ? throw new InvalidOperationException(Resources.NoData) - : base.IsDBNull(ordinal); + public override bool IsDBNull(int ordinal) + => !_stepped || sqlite3_data_count(Handle) == 0 + ? throw new InvalidOperationException(Resources.NoData) + : base.IsDBNull(ordinal); - public override object GetValue(int ordinal) - => !_stepped || sqlite3_data_count(Handle) == 0 - ? throw new InvalidOperationException(Resources.NoData) - : base.GetValue(ordinal)!; + public override object GetValue(int ordinal) + => !_stepped || sqlite3_data_count(Handle) == 0 + ? throw new InvalidOperationException(Resources.NoData) + : base.GetValue(ordinal)!; - protected override double GetDoubleCore(int ordinal) - => sqlite3_column_double(Handle, ordinal); + protected override double GetDoubleCore(int ordinal) + => sqlite3_column_double(Handle, ordinal); - protected override long GetInt64Core(int ordinal) - => sqlite3_column_int64(Handle, ordinal); + protected override long GetInt64Core(int ordinal) + => sqlite3_column_int64(Handle, ordinal); - protected override string GetStringCore(int ordinal) - => sqlite3_column_text(Handle, ordinal).utf8_to_string(); + protected override string GetStringCore(int ordinal) + => sqlite3_column_text(Handle, ordinal).utf8_to_string(); - public override T GetFieldValue(int ordinal) + public override T GetFieldValue(int ordinal) + { + if (typeof(T) == typeof(Stream)) { - if (typeof(T) == typeof(Stream)) - { - return (T)(object)GetStream(ordinal); - } - - if (typeof(T) == typeof(TextReader)) - { - return (T)(object)GetTextReader(ordinal); - } + return (T)(object)GetStream(ordinal); + } - return base.GetFieldValue(ordinal)!; + if (typeof(T) == typeof(TextReader)) + { + return (T)(object)GetTextReader(ordinal); } - protected override byte[] GetBlob(int ordinal) - => base.GetBlob(ordinal)!; + return base.GetFieldValue(ordinal)!; + } + + protected override byte[] GetBlob(int ordinal) + => base.GetBlob(ordinal)!; - protected override byte[] GetBlobCore(int ordinal) - => sqlite3_column_blob(Handle, ordinal).ToArray(); + protected override byte[] GetBlobCore(int ordinal) + => sqlite3_column_blob(Handle, ordinal).ToArray(); - protected override int GetSqliteType(int ordinal) + protected override int GetSqliteType(int ordinal) + { + var type = sqlite3_column_type(Handle, ordinal); + if (type == SQLITE_NULL + && (ordinal < 0 || ordinal >= FieldCount)) { - var type = sqlite3_column_type(Handle, ordinal); - if (type == SQLITE_NULL - && (ordinal < 0 || ordinal >= FieldCount)) - { - // NB: Message is provided by the framework - throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null); - } + // NB: Message is provided by the framework + throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null); + } + + return type; + } + + protected override T GetNull(int ordinal) + => typeof(T) == typeof(DBNull) || typeof(T) == typeof(object) + ? (T)(object)DBNull.Value + : throw new InvalidOperationException(GetOnNullErrorMsg(ordinal)); - return type; + public virtual string GetName(int ordinal) + { + var name = _columnNameCache?[ordinal] ?? sqlite3_column_name(Handle, ordinal).utf8_to_string(); + if (name == null + && (ordinal < 0 || ordinal >= FieldCount)) + { + // NB: Message is provided by the framework + throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null); } - protected override T GetNull(int ordinal) - => typeof(T) == typeof(DBNull) || typeof(T) == typeof(object) - ? (T)(object)DBNull.Value - : throw new InvalidOperationException(GetOnNullErrorMsg(ordinal)); + _columnNameCache ??= new string[FieldCount]; + _columnNameCache[ordinal] = name!; + + return name!; + } - public virtual string GetName(int ordinal) + public virtual int GetOrdinal(string name) + { + if (_columnNameOrdinalCache == null) { - var name = _columnNameCache?[ordinal] ?? sqlite3_column_name(Handle, ordinal).utf8_to_string(); - if (name == null - && (ordinal < 0 || ordinal >= FieldCount)) + _columnNameOrdinalCache = new Dictionary(); + for (var i = 0; i < FieldCount; i++) { - // NB: Message is provided by the framework - throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null); + _columnNameOrdinalCache[GetName(i)] = i; } + } - _columnNameCache ??= new string[FieldCount]; - _columnNameCache[ordinal] = name!; - - return name!; + if (_columnNameOrdinalCache.TryGetValue(name, out var ordinal)) + { + return ordinal; } - public virtual int GetOrdinal(string name) + KeyValuePair? match = null; + foreach (var item in _columnNameOrdinalCache) { - if (_columnNameOrdinalCache == null) + if (string.Equals(name, item.Key, StringComparison.OrdinalIgnoreCase)) { - _columnNameOrdinalCache = new Dictionary(); - for (var i = 0; i < FieldCount; i++) + if (match != null) { - _columnNameOrdinalCache[GetName(i)] = i; + throw new InvalidOperationException( + Resources.AmbiguousColumnName(name, match.Value.Key, item.Key)); } - } - if (_columnNameOrdinalCache.TryGetValue(name, out var ordinal)) - { - return ordinal; + match = item; } + } - KeyValuePair? match = null; - foreach (var item in _columnNameOrdinalCache) - { - if (string.Equals(name, item.Key, StringComparison.OrdinalIgnoreCase)) - { - if (match != null) - { - throw new InvalidOperationException( - Resources.AmbiguousColumnName(name, match.Value.Key, item.Key)); - } + if (match != null) + { + _columnNameOrdinalCache.Add(name, match.Value.Value); - match = item; - } - } + return match.Value.Value; + } - if (match != null) - { - _columnNameOrdinalCache.Add(name, match.Value.Value); + // NB: Message is provided by framework + throw new ArgumentOutOfRangeException(nameof(name), name, message: null); + } - return match.Value.Value; - } + public virtual string GetDataTypeName(int ordinal) + { + var typeName = sqlite3_column_decltype(Handle, ordinal).utf8_to_string(); + if (typeName != null) + { + var i = typeName.IndexOf('('); - // NB: Message is provided by framework - throw new ArgumentOutOfRangeException(nameof(name), name, message: null); + return i == -1 + ? typeName + : typeName.Substring(0, i); } - public virtual string GetDataTypeName(int ordinal) + var sqliteType = GetSqliteType(ordinal); + switch (sqliteType) { - var typeName = sqlite3_column_decltype(Handle, ordinal).utf8_to_string(); - if (typeName != null) - { - var i = typeName.IndexOf('('); - - return i == -1 - ? typeName - : typeName.Substring(0, i); - } + case SQLITE_INTEGER: + return "INTEGER"; - var sqliteType = GetSqliteType(ordinal); - switch (sqliteType) - { - case SQLITE_INTEGER: - return "INTEGER"; - - case SQLITE_FLOAT: - return "REAL"; + case SQLITE_FLOAT: + return "REAL"; - case SQLITE_TEXT: - return "TEXT"; + case SQLITE_TEXT: + return "TEXT"; - default: - Debug.Assert(sqliteType is SQLITE_BLOB or SQLITE_NULL, "Unexpected column type: " + sqliteType); - return "BLOB"; - } + default: + Debug.Assert(sqliteType is SQLITE_BLOB or SQLITE_NULL, "Unexpected column type: " + sqliteType); + return "BLOB"; } + } #if NET6_0_OR_GREATER - [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] #endif - public virtual Type GetFieldType(int ordinal) + public virtual Type GetFieldType(int ordinal) + { + var sqliteType = GetSqliteType(ordinal); + if (sqliteType == SQLITE_NULL) { - var sqliteType = GetSqliteType(ordinal); - if (sqliteType == SQLITE_NULL) - { - sqliteType = _typeCache?[ordinal] ?? Sqlite3AffinityType(GetDataTypeName(ordinal)); - } - else - { - _typeCache ??= new int?[FieldCount]; - _typeCache[ordinal] = sqliteType; - } - - return GetFieldTypeFromSqliteType(sqliteType); + sqliteType = _typeCache?[ordinal] ?? Sqlite3AffinityType(GetDataTypeName(ordinal)); + } + else + { + _typeCache ??= new int?[FieldCount]; + _typeCache[ordinal] = sqliteType; } + return GetFieldTypeFromSqliteType(sqliteType); + } + #if NET6_0_OR_GREATER - [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] #endif - internal static Type GetFieldTypeFromSqliteType(int sqliteType) + internal static Type GetFieldTypeFromSqliteType(int sqliteType) + { + switch (sqliteType) { - switch (sqliteType) - { - case SQLITE_INTEGER: - return typeof(long); + case SQLITE_INTEGER: + return typeof(long); - case SQLITE_FLOAT: - return typeof(double); + case SQLITE_FLOAT: + return typeof(double); - case SQLITE_TEXT: - return typeof(string); + case SQLITE_TEXT: + return typeof(string); - default: - Debug.Assert(sqliteType is SQLITE_BLOB or SQLITE_NULL, "Unexpected column type: " + sqliteType); - return typeof(byte[]); - } + default: + Debug.Assert(sqliteType is SQLITE_BLOB or SQLITE_NULL, "Unexpected column type: " + sqliteType); + return typeof(byte[]); } + } #if NET6_0_OR_GREATER - [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] #endif - public static Type GetFieldType(string type) + public static Type GetFieldType(string type) + { + switch (type) { - switch (type) - { - case "integer": - return typeof(long); + case "integer": + return typeof(long); - case "real": - return typeof(double); + case "real": + return typeof(double); - case "text": - return typeof(string); + case "text": + return typeof(string); - default: - Debug.Assert(type is "blob" or null, "Unexpected column type: " + type); - return typeof(byte[]); - } + default: + Debug.Assert(type is "blob" or null, "Unexpected column type: " + type); + return typeof(byte[]); } + } + + public virtual long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int bufferOffset, int length) + { + using var stream = GetStream(ordinal); - public virtual long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int bufferOffset, int length) + if (buffer == null) { - using var stream = GetStream(ordinal); + return stream.Length; + } - if (buffer == null) - { - return stream.Length; - } + stream.Position = dataOffset; - stream.Position = dataOffset; + return stream.Read(buffer, bufferOffset, length); + } - return stream.Read(buffer, bufferOffset, length); - } + public virtual long GetChars(int ordinal, long dataOffset, char[]? buffer, int bufferOffset, int length) + { + using var reader = new StreamReader(GetStream(ordinal), Encoding.UTF8); - public virtual long GetChars(int ordinal, long dataOffset, char[]? buffer, int bufferOffset, int length) + if (buffer == null) { - using var reader = new StreamReader(GetStream(ordinal), Encoding.UTF8); - - if (buffer == null) + // TODO: Consider using a stackalloc buffer and reading blocks instead + var charCount = 0; + while (reader.Read() != -1) { - // TODO: Consider using a stackalloc buffer and reading blocks instead - var charCount = 0; - while (reader.Read() != -1) - { - charCount++; - } - - return charCount; + charCount++; } - for (var position = 0; position < dataOffset; position++) + return charCount; + } + + for (var position = 0; position < dataOffset; position++) + { + if (reader.Read() == -1) { - if (reader.Read() == -1) - { - // NB: Message is provided by the framework - throw new ArgumentOutOfRangeException(nameof(dataOffset), dataOffset, message: null); - } + // NB: Message is provided by the framework + throw new ArgumentOutOfRangeException(nameof(dataOffset), dataOffset, message: null); } + } + + return reader.Read(buffer, bufferOffset, length); + } - return reader.Read(buffer, bufferOffset, length); + public virtual Stream GetStream(int ordinal) + { + if (ordinal < 0 + || ordinal >= FieldCount) + { + throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null); } - public virtual Stream GetStream(int ordinal) + var blobDatabaseName = sqlite3_column_database_name(Handle, ordinal).utf8_to_string(); + var blobTableName = sqlite3_column_table_name(Handle, ordinal).utf8_to_string(); + + RowIdInfo? rowIdForOrdinal = null; + var rowidkey = $"{blobDatabaseName}_{blobTableName}"; + if (!RowIds.TryGetValue(rowidkey, out rowIdForOrdinal)) { - if (ordinal < 0 - || ordinal >= FieldCount) + var pkColumns = -1L; + for (var i = 0; i < FieldCount; i++) { - throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null); - } + if (i == ordinal) + { + continue; + } - var blobDatabaseName = sqlite3_column_database_name(Handle, ordinal).utf8_to_string(); - var blobTableName = sqlite3_column_table_name(Handle, ordinal).utf8_to_string(); + var databaseName = sqlite3_column_database_name(Handle, i).utf8_to_string(); + if (databaseName != blobDatabaseName) + { + continue; + } - RowIdInfo? rowIdForOrdinal = null; - string rowidkey = $"{blobDatabaseName}_{blobTableName}"; - if (!RowIds.TryGetValue(rowidkey, out rowIdForOrdinal)) - { - var pkColumns = -1L; - for (var i = 0; i < FieldCount; i++) + var tableName = sqlite3_column_table_name(Handle, i).utf8_to_string(); + if (tableName != blobTableName) { - if (i == ordinal) - { - continue; - } + continue; + } - var databaseName = sqlite3_column_database_name(Handle, i).utf8_to_string(); - if (databaseName != blobDatabaseName) - { - continue; - } + var columnName = sqlite3_column_origin_name(Handle, i).utf8_to_string(); + if (columnName == "rowid") + { + rowIdForOrdinal = new RowIdInfo(i, tableName); + RowIds.Add(rowidkey, rowIdForOrdinal); + break; + } - var tableName = sqlite3_column_table_name(Handle, i).utf8_to_string(); - if (tableName != blobTableName) + var rc = sqlite3_table_column_metadata( + connection.Handle, + databaseName, + tableName, + columnName, + out var dataType, + out var collSeq, + out var notNull, + out var primaryKey, + out var autoInc); + SqliteException.ThrowExceptionForRC(rc, connection.Handle); + if (string.Equals(dataType, "INTEGER", StringComparison.OrdinalIgnoreCase) + && primaryKey != 0) + { + if (pkColumns < 0L) { - continue; + using (var command = connection.CreateCommand()) + { + command.CommandText = "SELECT COUNT(*) FROM pragma_table_info($table) WHERE pk != 0;"; + command.Parameters.AddWithValue("$table", tableName); + + pkColumns = (long)command.ExecuteScalar()!; + } } - var columnName = sqlite3_column_origin_name(Handle, i).utf8_to_string(); - if (columnName == "rowid") + if (pkColumns == 1L) { rowIdForOrdinal = new RowIdInfo(i, tableName); RowIds.Add(rowidkey, rowIdForOrdinal); break; } + } + } - var rc = sqlite3_table_column_metadata( - connection.Handle, - databaseName, - tableName, - columnName, - out var dataType, - out var collSeq, - out var notNull, - out var primaryKey, - out var autoInc); - SqliteException.ThrowExceptionForRC(rc, connection.Handle); - if (string.Equals(dataType, "INTEGER", StringComparison.OrdinalIgnoreCase) - && primaryKey != 0) - { - if (pkColumns < 0L) - { - using (var command = connection.CreateCommand()) - { - command.CommandText = "SELECT COUNT(*) FROM pragma_table_info($table) WHERE pk != 0;"; - command.Parameters.AddWithValue("$table", tableName); + //Debug.Assert(rowIdForOrdinal!=null); + //debug assertion no more needed: + //rowIdForOrdinal == null => matching rowid not found, MemoryStream returned + //rowIdForOrdinal != null => matching rowid found, SqliteBlob returned + } - pkColumns = (long)command.ExecuteScalar()!; - } - } + if (rowIdForOrdinal == null) + { + return new MemoryStream(GetCachedBlob(ordinal), false); + } - if (pkColumns == 1L) - { - rowIdForOrdinal = new RowIdInfo(i, tableName); - RowIds.Add(rowidkey, rowIdForOrdinal); - break; - } - } - } + var blobColumnName = sqlite3_column_origin_name(Handle, ordinal).utf8_to_string(); + var rowid = GetInt64(rowIdForOrdinal.Ordinal); - //Debug.Assert(rowIdForOrdinal!=null); - //debug assertion no more needed: - //rowIdForOrdinal == null => matching rowid not found, MemoryStream returned - //rowIdForOrdinal != null => matching rowid found, SqliteBlob returned - } + return new SqliteBlob(connection, blobDatabaseName, blobTableName, blobColumnName, rowid, readOnly: true); + } - if (rowIdForOrdinal == null) - { - return new MemoryStream(GetCachedBlob(ordinal), false); - } + public virtual TextReader GetTextReader(int ordinal) + => IsDBNull(ordinal) + ? new StringReader(string.Empty) + : new StreamReader(GetStream(ordinal), Encoding.UTF8); - var blobColumnName = sqlite3_column_origin_name(Handle, ordinal).utf8_to_string(); - var rowid = GetInt64(rowIdForOrdinal.Ordinal); + public bool Read() + { + if (!_stepped) + { + _stepped = true; - return new SqliteBlob(connection, blobDatabaseName, blobTableName, blobColumnName, rowid, readOnly: true); + return HasRows; } - public virtual TextReader GetTextReader(int ordinal) - => IsDBNull(ordinal) - ? new StringReader(string.Empty) - : new StreamReader(GetStream(ordinal), Encoding.UTF8); + if (sqlite3_data_count(Handle) == 0) + { + return false; + } - public bool Read() + int rc; + try { - if (!_stepped) - { - _stepped = true; + rc = sqlite3_step(Handle); + SqliteException.ThrowExceptionForRC(rc, connection.Handle); + } + catch + { + _alreadyThrown = true; - return HasRows; - } + throw; + } - if (sqlite3_data_count(Handle) == 0) - { - return false; - } + if (_blobCache != null) + { + Array.Clear(_blobCache, 0, _blobCache.Length); + } - int rc; - try - { - rc = sqlite3_step(Handle); - SqliteException.ThrowExceptionForRC(rc, connection.Handle); - } - catch - { - _alreadyThrown = true; + if (rc != SQLITE_DONE) + { + return true; + } - throw; - } + AddChanges(); + _alreadyAddedChanges = true; - if (_blobCache != null) - { - Array.Clear(_blobCache, 0, _blobCache.Length); - } + return false; + } - if (rc != SQLITE_DONE) - { - return true; - } + public void Dispose() + { + var rc = sqlite3_reset(Handle); + if (!_alreadyThrown) + { + SqliteException.ThrowExceptionForRC(rc, connection.Handle); + } + if (!_alreadyAddedChanges) + { AddChanges(); - _alreadyAddedChanges = true; - - return false; } + } - public void Dispose() + private void AddChanges() + { + if (sqlite3_stmt_readonly(Handle) != 0) { - var rc = sqlite3_reset(Handle); - if (!_alreadyThrown) - { - SqliteException.ThrowExceptionForRC(rc, connection.Handle); - } - - if (!_alreadyAddedChanges) - { - AddChanges(); - } + return; } - private void AddChanges() - { - if (sqlite3_stmt_readonly(Handle) != 0) - { - return; - } + var changes = sqlite3_changes(connection.Handle); + addChanges(changes); + } - var changes = sqlite3_changes(connection.Handle); - addChanges(changes); + 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); } - private byte[] GetCachedBlob(int ordinal) + var blob = _blobCache?[ordinal]; + if (blob == null) { - if (ordinal < 0 - || ordinal >= FieldCount) - { - // NB: Message is provided by the framework - throw new ArgumentOutOfRangeException(nameof(ordinal), ordinal, message: null); - } + blob = GetBlob(ordinal); + _blobCache ??= new byte[FieldCount][]; + _blobCache[ordinal] = blob; + } - var blob = _blobCache?[ordinal]; - if (blob == null) - { - blob = GetBlob(ordinal); - _blobCache ??= new byte[FieldCount][]; - _blobCache[ordinal] = blob; - } + return blob; + } - return blob; + internal static int Sqlite3AffinityType(string dataTypeName) + { + if (dataTypeName == null) + { + // if no type is specified then the column has affinity BLOB + return SQLITE_BLOB; } - internal static int Sqlite3AffinityType(string dataTypeName) + var typeRules = new Func[] { - if (dataTypeName == null) - { - // if no type is specified then the column has affinity BLOB - return SQLITE_BLOB; - } - - var typeRules = new Func[] - { - name => Contains(name, "INT") ? SQLITE_INTEGER : (int?)null, - name => Contains(name, "CHAR") - || Contains(name, "CLOB") - || Contains(name, "TEXT") - ? SQLITE_TEXT - : (int?)null, - name => Contains(name, "BLOB") ? SQLITE_BLOB : (int?)null, - name => Contains(name, "REAL") - || Contains(name, "FLOA") - || Contains(name, "DOUB") - ? SQLITE_FLOAT - : (int?)null - }; - - return typeRules.Select(r => r(dataTypeName)).FirstOrDefault(r => r != null) ?? SQLITE_TEXT; // code NUMERICAL affinity as TEXT - } - - private static bool Contains(string haystack, string needle) - => haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0; + name => Contains(name, "INT") ? SQLITE_INTEGER : null, + name => Contains(name, "CHAR") + || Contains(name, "CLOB") + || Contains(name, "TEXT") + ? SQLITE_TEXT + : null, + name => Contains(name, "BLOB") ? SQLITE_BLOB : null, + name => Contains(name, "REAL") + || Contains(name, "FLOA") + || Contains(name, "DOUB") + ? SQLITE_FLOAT + : null + }; + + return typeRules.Select(r => r(dataTypeName)).FirstOrDefault(r => r != null) ?? SQLITE_TEXT; // code NUMERICAL affinity as TEXT } + + private static bool Contains(string haystack, string needle) + => haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0; } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteException.cs b/src/Microsoft.Data.Sqlite.Core/SqliteException.cs index 953f3140427..905148dc04b 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteException.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteException.cs @@ -6,82 +6,81 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Represents a SQLite error. +/// +/// Database Errors +public class SqliteException : DbException { /// - /// Represents a SQLite error. + /// Initializes a new instance of the class. /// - /// Database Errors - public class SqliteException : DbException + /// The message to display for the exception. Can be null. + /// The SQLite error code. + public SqliteException(string? message, int errorCode) + : this(message, errorCode, errorCode) { - /// - /// Initializes a new instance of the class. - /// - /// The message to display for the exception. Can be null. - /// The SQLite error code. - public SqliteException(string? message, int errorCode) - : this(message, errorCode, errorCode) - { - } + } - /// - /// Initializes a new instance of the class. - /// - /// The message to display for the exception. Can be null. - /// The SQLite error code. - /// The extended SQLite error code. - public SqliteException(string? message, int errorCode, int extendedErrorCode) - : base(message) - { - SqliteErrorCode = errorCode; - SqliteExtendedErrorCode = extendedErrorCode; - } + /// + /// Initializes a new instance of the class. + /// + /// The message to display for the exception. Can be null. + /// The SQLite error code. + /// The extended SQLite error code. + public SqliteException(string? message, int errorCode, int extendedErrorCode) + : base(message) + { + SqliteErrorCode = errorCode; + SqliteExtendedErrorCode = extendedErrorCode; + } - /// - /// Gets the SQLite error code. - /// - /// The SQLite error code. - /// SQLite Result Codes - public virtual int SqliteErrorCode { get; } + /// + /// Gets the SQLite error code. + /// + /// The SQLite error code. + /// SQLite Result Codes + public virtual int SqliteErrorCode { get; } - /// - /// Gets the extended SQLite error code. - /// - /// The SQLite error code. - /// SQLite Result Codes - public virtual int SqliteExtendedErrorCode { get; } + /// + /// Gets the extended SQLite error code. + /// + /// The SQLite error code. + /// SQLite Result Codes + public virtual int SqliteExtendedErrorCode { get; } - /// - /// Throws an exception with a specific SQLite error code value. - /// - /// The SQLite error code corresponding to the desired exception. - /// A handle to database connection. - /// - /// No exception is thrown for non-error result codes. - /// - public static void ThrowExceptionForRC(int rc, sqlite3? db) + /// + /// Throws an exception with a specific SQLite error code value. + /// + /// The SQLite error code corresponding to the desired exception. + /// A handle to database connection. + /// + /// No exception is thrown for non-error result codes. + /// + public static void ThrowExceptionForRC(int rc, sqlite3? db) + { + if (rc is SQLITE_OK or SQLITE_ROW or SQLITE_DONE) { - if (rc is SQLITE_OK or SQLITE_ROW or SQLITE_DONE) - { - return; - } - - string message; - int extendedErrorCode; - if (db == null - || db.IsInvalid - || rc != sqlite3_errcode(db)) - { - message = sqlite3_errstr(rc).utf8_to_string() + " " + Resources.DefaultNativeError; - extendedErrorCode = rc; - } - else - { - message = sqlite3_errmsg(db).utf8_to_string(); - extendedErrorCode = sqlite3_extended_errcode(db); - } + return; + } - throw new SqliteException(Resources.SqliteNativeError(rc, message), rc, extendedErrorCode); + string message; + int extendedErrorCode; + if (db == null + || db.IsInvalid + || rc != sqlite3_errcode(db)) + { + message = sqlite3_errstr(rc).utf8_to_string() + " " + Resources.DefaultNativeError; + extendedErrorCode = rc; } + else + { + message = sqlite3_errmsg(db).utf8_to_string(); + extendedErrorCode = sqlite3_extended_errcode(db); + } + + throw new SqliteException(Resources.SqliteNativeError(rc, message), rc, extendedErrorCode); } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteFactory.cs b/src/Microsoft.Data.Sqlite.Core/SqliteFactory.cs index b50e953a888..7d00b262547 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteFactory.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteFactory.cs @@ -3,48 +3,47 @@ using System.Data.Common; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Creates instances of various Microsoft.Data.Sqlite classes. +/// +public class SqliteFactory : DbProviderFactory { - /// - /// Creates instances of various Microsoft.Data.Sqlite classes. - /// - public class SqliteFactory : DbProviderFactory + private SqliteFactory() { - private SqliteFactory() - { - } - - /// - /// The singleton instance. - /// - public static readonly SqliteFactory Instance = new(); - - /// - /// Creates a new command. - /// - /// The new command. - public override DbCommand CreateCommand() - => new SqliteCommand(); - - /// - /// Creates a new connection. - /// - /// The new connection. - public override DbConnection CreateConnection() - => new SqliteConnection(); - - /// - /// Creates a new connection string builder. - /// - /// The new connection string builder. - public override DbConnectionStringBuilder CreateConnectionStringBuilder() - => new SqliteConnectionStringBuilder(); - - /// - /// Creates a new parameter. - /// - /// The new parameter. - public override DbParameter CreateParameter() - => new SqliteParameter(); } + + /// + /// The singleton instance. + /// + public static readonly SqliteFactory Instance = new(); + + /// + /// Creates a new command. + /// + /// The new command. + public override DbCommand CreateCommand() + => new SqliteCommand(); + + /// + /// Creates a new connection. + /// + /// The new connection. + public override DbConnection CreateConnection() + => new SqliteConnection(); + + /// + /// Creates a new connection string builder. + /// + /// The new connection string builder. + public override DbConnectionStringBuilder CreateConnectionStringBuilder() + => new SqliteConnectionStringBuilder(); + + /// + /// Creates a new parameter. + /// + /// The new parameter. + public override DbParameter CreateParameter() + => new SqliteParameter(); } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteOpenMode.cs b/src/Microsoft.Data.Sqlite.Core/SqliteOpenMode.cs index 8fddab78b18..10599108d6a 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteOpenMode.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteOpenMode.cs @@ -1,32 +1,31 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Represents the connection modes that can be used when opening a connection. +/// +public enum SqliteOpenMode { /// - /// Represents the connection modes that can be used when opening a connection. + /// Opens the database for reading and writing, and creates it if it doesn't exist. /// - public enum SqliteOpenMode - { - /// - /// Opens the database for reading and writing, and creates it if it doesn't exist. - /// - ReadWriteCreate, + ReadWriteCreate, - /// - /// Opens the database for reading and writing. - /// - ReadWrite, + /// + /// Opens the database for reading and writing. + /// + ReadWrite, - /// - /// Opens the database in read-only mode. - /// - ReadOnly, + /// + /// Opens the database in read-only mode. + /// + ReadOnly, - /// - /// Opens an in-memory database. - /// - /// In-Memory Databases - Memory - } + /// + /// Opens an in-memory database. + /// + /// In-Memory Databases + Memory } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteParameter.cs b/src/Microsoft.Data.Sqlite.Core/SqliteParameter.cs index d98141b9c62..bd3d7460c0f 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteParameter.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteParameter.cs @@ -9,256 +9,254 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Represents a parameter and its value in a . +/// +/// Due to SQLite's dynamic type system, parameter values are not converted. +/// Parameters +/// Data Types +public class SqliteParameter : DbParameter { + private string _parameterName = string.Empty; + private object? _value; + private int? _size; + private SqliteType? _sqliteType; + private string _sourceColumn = string.Empty; + /// - /// Represents a parameter and its value in a . + /// Initializes a new instance of the class. /// - /// Due to SQLite's dynamic type system, parameter values are not converted. + /// Parameters + public SqliteParameter() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The name of the parameter. + /// The value of the parameter. Can be null. /// Parameters /// Data Types - public class SqliteParameter : DbParameter + public SqliteParameter(string? name, object? value) { - private string _parameterName = string.Empty; - private object? _value; - private int? _size; - private SqliteType? _sqliteType; - private string _sourceColumn = string.Empty; - - /// - /// Initializes a new instance of the class. - /// - /// Parameters - public SqliteParameter() - { - } + ParameterName = name; + Value = value; + } - /// - /// Initializes a new instance of the class. - /// - /// The name of the parameter. - /// The value of the parameter. Can be null. - /// Parameters - /// Data Types - public SqliteParameter(string? name, object? value) - { - ParameterName = name; - Value = value; - } + /// + /// Initializes a new instance of the class. + /// + /// The name of the parameter. + /// The type of the parameter. + /// Parameters + public SqliteParameter(string? name, SqliteType type) + { + ParameterName = name; + SqliteType = type; + } - /// - /// Initializes a new instance of the class. - /// - /// The name of the parameter. - /// The type of the parameter. - /// Parameters - public SqliteParameter(string? name, SqliteType type) - { - ParameterName = name; - SqliteType = type; - } + /// + /// Initializes a new instance of the class. + /// + /// The name of the parameter. + /// The type of the parameter. + /// The maximum size, in bytes, of the parameter. + /// Parameters + public SqliteParameter(string? name, SqliteType type, int size) + : this(name, type) + => Size = size; - /// - /// Initializes a new instance of the class. - /// - /// The name of the parameter. - /// The type of the parameter. - /// The maximum size, in bytes, of the parameter. - /// Parameters - public SqliteParameter(string? name, SqliteType type, int size) - : this(name, type) - => Size = size; - - /// - /// Initializes a new instance of the class. - /// - /// The name of the parameter. - /// The type of the parameter. - /// The maximum size, in bytes, of the parameter. - /// The source column used for loading the value. Can be null. - /// Parameters - public SqliteParameter(string? name, SqliteType type, int size, string? sourceColumn) - : this(name, type, size) - => SourceColumn = sourceColumn; - - /// - /// Gets or sets the type of the parameter. - /// - /// The type of the parameter. - /// Due to SQLite's dynamic type system, parameter values are not converted. - public override DbType DbType { get; set; } = DbType.String; - - /// - /// Gets or sets the SQLite type of the parameter. - /// - /// The SQLite type of the parameter. - /// Parameters - public virtual SqliteType SqliteType - { - get => _sqliteType ?? SqliteValueBinder.GetSqliteType(_value); - set => _sqliteType = value; - } + /// + /// Initializes a new instance of the class. + /// + /// The name of the parameter. + /// The type of the parameter. + /// The maximum size, in bytes, of the parameter. + /// The source column used for loading the value. Can be null. + /// Parameters + public SqliteParameter(string? name, SqliteType type, int size, string? sourceColumn) + : this(name, type, size) + => SourceColumn = sourceColumn; + + /// + /// Gets or sets the type of the parameter. + /// + /// The type of the parameter. + /// Due to SQLite's dynamic type system, parameter values are not converted. + public override DbType DbType { get; set; } = DbType.String; + + /// + /// Gets or sets the SQLite type of the parameter. + /// + /// The SQLite type of the parameter. + /// Parameters + public virtual SqliteType SqliteType + { + get => _sqliteType ?? SqliteValueBinder.GetSqliteType(_value); + set => _sqliteType = value; + } - /// - /// Gets or sets the direction of the parameter. Only is supported. - /// - /// The direction of the parameter. - public override ParameterDirection Direction + /// + /// Gets or sets the direction of the parameter. Only is supported. + /// + /// The direction of the parameter. + public override ParameterDirection Direction + { + get => ParameterDirection.Input; + set { - get => ParameterDirection.Input; - set + if (value != ParameterDirection.Input) { - if (value != ParameterDirection.Input) - { - throw new ArgumentException(Resources.InvalidParameterDirection(value)); - } + throw new ArgumentException(Resources.InvalidParameterDirection(value)); } } + } - /// - /// Gets or sets a value indicating whether the parameter is nullable. - /// - /// A value indicating whether the parameter is nullable. - public override bool IsNullable { get; set; } - - /// - /// Gets or sets the name of the parameter. - /// - /// The name of the parameter. - [AllowNull] - public override string ParameterName - { - get => _parameterName; - set => _parameterName = value ?? string.Empty; - } + /// + /// Gets or sets a value indicating whether the parameter is nullable. + /// + /// A value indicating whether the parameter is nullable. + public override bool IsNullable { get; set; } + + /// + /// Gets or sets the name of the parameter. + /// + /// The name of the parameter. + [AllowNull] + public override string ParameterName + { + get => _parameterName; + set => _parameterName = value ?? string.Empty; + } - /// - /// Gets or sets the maximum size, in bytes, of the parameter. - /// - /// The maximum size, in bytes, of the parameter. - /// Parameters - public override int Size + /// + /// Gets or sets the maximum size, in bytes, of the parameter. + /// + /// The maximum size, in bytes, of the parameter. + /// Parameters + public override int Size + { + get => _size + ?? (_value is string stringValue + ? stringValue.Length + : _value is byte[] byteArray + ? byteArray.Length + : 0); + + set { - get - => _size - ?? (_value is string stringValue - ? stringValue.Length - : _value is byte[] byteArray - ? byteArray.Length - : 0); - - set + if (value < -1) { - if (value < -1) - { - // NB: Message is provided by the framework - throw new ArgumentOutOfRangeException(nameof(value), value, message: null); - } - - _size = value; + // NB: Message is provided by the framework + throw new ArgumentOutOfRangeException(nameof(value), value, message: null); } + + _size = value; } + } - /// - /// Gets or sets the source column used for loading the value. - /// - /// The source column used for loading the value. - [AllowNull] - public override string SourceColumn + /// + /// Gets or sets the source column used for loading the value. + /// + /// The source column used for loading the value. + [AllowNull] + public override string SourceColumn + { + get => _sourceColumn; + set => _sourceColumn = value ?? string.Empty; + } + + /// + /// Gets or sets a value indicating whether the source column is nullable. + /// + /// A value indicating whether the source column is nullable. + public override bool SourceColumnNullMapping { get; set; } + + /// + /// Gets or sets the value of the parameter. + /// + /// The value of the parameter. + /// Due to SQLite's dynamic type system, parameter values are not converted. + /// Data Types + public override object? Value + { + get => _value; + set => _value = value; + } + + /// + /// Resets the property to its original value. + /// + public override void ResetDbType() + => ResetSqliteType(); + + /// + /// Resets the property to its original value. + /// + public virtual void ResetSqliteType() + { + DbType = DbType.String; + _sqliteType = null; + } + + internal bool Bind(sqlite3_stmt stmt, sqlite3 handle) + { + if (string.IsNullOrEmpty(ParameterName)) { - get => _sourceColumn; - set => _sourceColumn = value ?? string.Empty; + throw new InvalidOperationException(Resources.RequiresSet(nameof(ParameterName))); } - /// - /// Gets or sets a value indicating whether the source column is nullable. - /// - /// A value indicating whether the source column is nullable. - public override bool SourceColumnNullMapping { get; set; } - - /// - /// Gets or sets the value of the parameter. - /// - /// The value of the parameter. - /// Due to SQLite's dynamic type system, parameter values are not converted. - /// Data Types - public override object? Value + var index = sqlite3_bind_parameter_index(stmt, ParameterName); + if (index == 0 + && (index = FindPrefixedParameter(stmt)) == 0) { - get => _value; - set { _value = value; } + return false; } - /// - /// Resets the property to its original value. - /// - public override void ResetDbType() - => ResetSqliteType(); - - /// - /// Resets the property to its original value. - /// - public virtual void ResetSqliteType() + if (_value == null) { - DbType = DbType.String; - _sqliteType = null; + throw new InvalidOperationException(Resources.RequiresSet(nameof(Value))); } - internal bool Bind(sqlite3_stmt stmt, sqlite3 handle) + new SqliteParameterBinder(stmt, handle, 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 (string.IsNullOrEmpty(ParameterName)) + if (ParameterName[0] == prefix) { - throw new InvalidOperationException(Resources.RequiresSet(nameof(ParameterName))); + // 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; } - var index = sqlite3_bind_parameter_index(stmt, ParameterName); - if (index == 0 - && (index = FindPrefixedParameter(stmt)) == 0) - { - return false; - } + nextIndex = sqlite3_bind_parameter_index(stmt, prefix + ParameterName); - if (_value == null) + if (nextIndex == 0) { - throw new InvalidOperationException(Resources.RequiresSet(nameof(Value))); + continue; } - new SqliteParameterBinder(stmt, handle, 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 (index != 0) { - 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 = sqlite3_bind_parameter_index(stmt, prefix + ParameterName); - - if (nextIndex == 0) - { - continue; - } - - if (index != 0) - { - throw new InvalidOperationException(Resources.AmbiguousParameterName(ParameterName)); - } - - index = nextIndex; + throw new InvalidOperationException(Resources.AmbiguousParameterName(ParameterName)); } - return index; + index = nextIndex; } + + return index; } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteParameterBinder.cs b/src/Microsoft.Data.Sqlite.Core/SqliteParameterBinder.cs index 39735f94941..fb737b44a12 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteParameterBinder.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteParameterBinder.cs @@ -5,60 +5,59 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +internal class SqliteParameterBinder(sqlite3_stmt stmt, sqlite3 handle, int index, object value, int? size, SqliteType? sqliteType) + : SqliteValueBinder(value, sqliteType) { - internal class SqliteParameterBinder(sqlite3_stmt stmt, sqlite3 handle, int index, object value, int? size, SqliteType? sqliteType) - : SqliteValueBinder(value, sqliteType) + protected override void BindBlob(byte[] value) { - protected override void BindBlob(byte[] value) + var blob = value; + if (ShouldTruncate(value.Length)) { - var blob = value; - if (ShouldTruncate(value.Length)) - { - blob = new byte[size!.Value]; - Array.Copy(value, blob, size.Value); - } - - var rc = sqlite3_bind_blob(stmt, index, blob); - SqliteException.ThrowExceptionForRC(rc, handle); + blob = new byte[size!.Value]; + Array.Copy(value, blob, size.Value); } - protected override void BindDoubleCore(double value) - { - var rc = sqlite3_bind_double(stmt, index, value); - - SqliteException.ThrowExceptionForRC(rc, handle); - } + var rc = sqlite3_bind_blob(stmt, index, blob); + SqliteException.ThrowExceptionForRC(rc, handle); + } - protected override void BindInt64(long value) - { - var rc = sqlite3_bind_int64(stmt, index, value); + protected override void BindDoubleCore(double value) + { + var rc = sqlite3_bind_double(stmt, index, value); - SqliteException.ThrowExceptionForRC(rc, handle); - } + SqliteException.ThrowExceptionForRC(rc, handle); + } - protected override void BindNull() - { - var rc = sqlite3_bind_null(stmt, index); + protected override void BindInt64(long value) + { + var rc = sqlite3_bind_int64(stmt, index, value); - SqliteException.ThrowExceptionForRC(rc, handle); - } + SqliteException.ThrowExceptionForRC(rc, handle); + } - protected override void BindText(string value) - { - var rc = sqlite3_bind_text( - stmt, - index, - ShouldTruncate(value.Length) - ? value.Substring(0, size!.Value) - : value); + protected override void BindNull() + { + var rc = sqlite3_bind_null(stmt, index); - SqliteException.ThrowExceptionForRC(rc, handle); - } + SqliteException.ThrowExceptionForRC(rc, handle); + } - private bool ShouldTruncate(int length) - => size.HasValue - && length > size.Value - && size.Value != -1; + protected override void BindText(string value) + { + var rc = sqlite3_bind_text( + stmt, + index, + ShouldTruncate(value.Length) + ? value.Substring(0, size!.Value) + : value); + + SqliteException.ThrowExceptionForRC(rc, handle); } + + private bool ShouldTruncate(int length) + => size.HasValue + && length > size.Value + && size.Value != -1; } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteParameterCollection.cs b/src/Microsoft.Data.Sqlite.Core/SqliteParameterCollection.cs index c4503c163a2..58b4c4fe342 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteParameterCollection.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteParameterCollection.cs @@ -9,345 +9,344 @@ using Microsoft.Data.Sqlite.Properties; using SQLitePCL; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Represents a collection of SQLite parameters. +/// +/// Parameters +public class SqliteParameterCollection : DbParameterCollection { + private readonly List _parameters = []; + /// - /// Represents a collection of SQLite parameters. + /// Initializes a new instance of the class. /// - /// Parameters - public class SqliteParameterCollection : DbParameterCollection + protected internal SqliteParameterCollection() { - private readonly List _parameters = []; + } - /// - /// Initializes a new instance of the class. - /// - protected internal SqliteParameterCollection() - { - } + /// + /// Gets the number of items in the collection. + /// + /// The number of items in the collection. + public override int Count + => _parameters.Count; - /// - /// Gets the number of items in the collection. - /// - /// The number of items in the collection. - public override int Count - => _parameters.Count; - - /// - /// Gets the object used to synchronize access to the collection. - /// - /// The object used to synchronize access to the collection. - public override object SyncRoot - => ((ICollection)_parameters).SyncRoot; - - /// - /// Gets or sets the parameter at the specified index. - /// - /// The zero-based index of the parameter. - /// The parameter. - public new virtual SqliteParameter this[int index] + /// + /// Gets the object used to synchronize access to the collection. + /// + /// The object used to synchronize access to the collection. + public override object SyncRoot + => ((ICollection)_parameters).SyncRoot; + + /// + /// Gets or sets the parameter at the specified index. + /// + /// The zero-based index of the parameter. + /// The parameter. + public new virtual SqliteParameter this[int index] + { + get => _parameters[index]; + set { - get => _parameters[index]; - set + if (_parameters[index] == value) { - if (_parameters[index] == value) - { - return; - } - - _parameters[index] = value; + return; } - } - /// - /// Gets or sets the parameter with the specified name. - /// - /// The name of the parameter. - /// The parameter. - public new virtual SqliteParameter this[string parameterName] - { - get => this[IndexOfChecked(parameterName)]; - set => this[IndexOfChecked(parameterName)] = value; + _parameters[index] = value; } + } - /// - /// Adds a parameter to the collection. - /// - /// The parameter to add. Must be a . - /// The zero-based index of the parameter that was added. - /// Parameters - public override int Add(object value) - { - _parameters.Add((SqliteParameter)value); + /// + /// Gets or sets the parameter with the specified name. + /// + /// The name of the parameter. + /// The parameter. + public new virtual SqliteParameter this[string parameterName] + { + get => this[IndexOfChecked(parameterName)]; + set => this[IndexOfChecked(parameterName)] = value; + } - return Count - 1; - } + /// + /// Adds a parameter to the collection. + /// + /// The parameter to add. Must be a . + /// The zero-based index of the parameter that was added. + /// Parameters + public override int Add(object value) + { + _parameters.Add((SqliteParameter)value); - /// - /// Adds a parameter to the collection. - /// - /// The parameter to add. - /// The parameter that was added. - /// Parameters - public virtual SqliteParameter Add(SqliteParameter value) - { - _parameters.Add(value); + return Count - 1; + } - return value; - } + /// + /// Adds a parameter to the collection. + /// + /// The parameter to add. + /// The parameter that was added. + /// Parameters + public virtual SqliteParameter Add(SqliteParameter value) + { + _parameters.Add(value); - /// - /// Adds a parameter to the collection. - /// - /// The name of the parameter. - /// The SQLite type of the parameter. - /// The parameter that was added. - /// Parameters - public virtual SqliteParameter Add(string? parameterName, SqliteType type) - => Add(new SqliteParameter(parameterName, type)); - - /// - /// Adds a parameter to the collection. - /// - /// The name of the parameter. - /// The SQLite type of the parameter. - /// The maximum size, in bytes, of the parameter. - /// The parameter that was added. - /// Parameters - public virtual SqliteParameter Add(string? parameterName, SqliteType type, int size) - => Add(new SqliteParameter(parameterName, type, size)); - - /// - /// Adds a parameter to the collection. - /// - /// The name of the parameter. - /// The SQLite type of the parameter. - /// The maximum size, in bytes, of the parameter. - /// - /// The source column used for loading the value of the parameter. Can be null. - /// - /// The parameter that was added. - /// Parameters - public virtual SqliteParameter Add(string? parameterName, SqliteType type, int size, string? sourceColumn) - => Add(new SqliteParameter(parameterName, type, size, sourceColumn)); - - /// - /// Adds multiple parameters to the collection. - /// - /// - /// An array of parameters to add. They must be objects. - /// - /// Parameters - public override void AddRange(Array values) - => AddRange(values.Cast()); - - /// - /// Adds multiple parameters to the collection. - /// - /// The parameters to add. - /// Parameters - public virtual void AddRange(IEnumerable values) - => _parameters.AddRange(values); - - /// - /// Adds a parameter to the collection. - /// - /// The name of the parameter. - /// The value of the parameter. Can be null. - /// The parameter that was added. - /// Parameters - /// Data Types - public virtual SqliteParameter AddWithValue(string? parameterName, object? value) - => Add(new SqliteParameter(parameterName, value)); - - /// - /// Removes all parameters from the collection. - /// - public override void Clear() - => _parameters.Clear(); - - /// - /// Gets a value indicating whether the collection contains the specified parameter. - /// - /// The parameter to look for. Must be a . - /// if the collection contains the parameter; otherwise, . - public override bool Contains(object value) - => Contains((SqliteParameter)value); - - /// - /// Gets a value indicating whether the collection contains the specified parameter. - /// - /// The parameter to look for. - /// if the collection contains the parameter; otherwise, . - public virtual bool Contains(SqliteParameter value) - => _parameters.Contains(value); - - /// - /// Gets a value indicating whether the collection contains a parameter with the specified name. - /// - /// The name of the parameter. - /// if the collection contains the parameter; otherwise, . - public override bool Contains(string value) - => IndexOf(value) != -1; - - /// - /// Copies the collection to an array of parameters. - /// - /// - /// The array into which the parameters are copied. Must be an array of objects. - /// - /// The zero-based index to which the parameters are copied. - public override void CopyTo(Array array, int index) - => CopyTo((SqliteParameter[])array, index); - - /// - /// Copies the collection to an array of parameters. - /// - /// The array into which the parameters are copied. - /// The zero-based index to which the parameters are copied. - public virtual void CopyTo(SqliteParameter[] array, int index) - => _parameters.CopyTo(array, index); - - /// - /// Gets an enumerator that iterates through the collection. - /// - /// The enumerator. - public override IEnumerator GetEnumerator() - => _parameters.GetEnumerator(); - - /// - /// Gets a parameter at the specified index. - /// - /// The zero-based index of the parameter. - /// The parameter. - protected override DbParameter GetParameter(int index) - => this[index]; - - /// - /// Gets a parameter with the specified name. - /// - /// The name of the parameter. - /// The parameter. - protected override DbParameter GetParameter(string parameterName) - => GetParameter(IndexOfChecked(parameterName)); - - /// - /// Gets the index of the specified parameter. - /// - /// The parameter. Must be a . - /// The zero-based index of the parameter. - public override int IndexOf(object value) - => IndexOf((SqliteParameter)value); - - /// - /// Gets the index of the specified parameter. - /// - /// The parameter. - /// The zero-based index of the parameter. - public virtual int IndexOf(SqliteParameter value) - => _parameters.IndexOf(value); - - /// - /// Gets the index of the parameter with the specified name. - /// - /// The name of the parameter. - /// The zero-based index of the parameter or -1 if not found. - public override int IndexOf(string parameterName) - { - for (var index = 0; index < _parameters.Count; index++) - { - if (_parameters[index].ParameterName == parameterName) - { - return index; - } - } + return value; + } - return -1; - } + /// + /// Adds a parameter to the collection. + /// + /// The name of the parameter. + /// The SQLite type of the parameter. + /// The parameter that was added. + /// Parameters + public virtual SqliteParameter Add(string? parameterName, SqliteType type) + => Add(new SqliteParameter(parameterName, type)); + + /// + /// Adds a parameter to the collection. + /// + /// The name of the parameter. + /// The SQLite type of the parameter. + /// The maximum size, in bytes, of the parameter. + /// The parameter that was added. + /// Parameters + public virtual SqliteParameter Add(string? parameterName, SqliteType type, int size) + => Add(new SqliteParameter(parameterName, type, size)); + + /// + /// Adds a parameter to the collection. + /// + /// The name of the parameter. + /// The SQLite type of the parameter. + /// The maximum size, in bytes, of the parameter. + /// + /// The source column used for loading the value of the parameter. Can be null. + /// + /// The parameter that was added. + /// Parameters + public virtual SqliteParameter Add(string? parameterName, SqliteType type, int size, string? sourceColumn) + => Add(new SqliteParameter(parameterName, type, size, sourceColumn)); - /// - /// Inserts a parameter into the collection at the specified index. - /// - /// The zero-based index at which the parameter should be inserted. - /// The parameter to insert. Must be a . - public override void Insert(int index, object value) - => Insert(index, (SqliteParameter)value); - - /// - /// Inserts a parameter into the collection at the specified index. - /// - /// The zero-based index at which the parameter should be inserted. - /// The parameter to insert. - public virtual void Insert(int index, SqliteParameter value) - => _parameters.Insert(index, value); - - /// - /// Removes a parameter from the collection. - /// - /// The parameter to remove. Must be a . - public override void Remove(object value) - => Remove((SqliteParameter)value); - - /// - /// Removes a parameter from the collection. - /// - /// The parameter to remove. - public virtual void Remove(SqliteParameter value) - => _parameters.Remove(value); - - /// - /// Removes a parameter from the collection at the specified index. - /// - /// The zero-based index of the parameter to remove. - public override void RemoveAt(int index) - => _parameters.RemoveAt(index); - - /// - /// Removes a parameter with the specified name from the collection. - /// - /// The name of the parameter to remove. - public override void RemoveAt(string parameterName) - => RemoveAt(IndexOfChecked(parameterName)); - - /// - /// Sets the parameter at the specified index. - /// - /// The zero-based index of the parameter to set. - /// The parameter. Must be a . - protected override void SetParameter(int index, DbParameter value) - => this[index] = (SqliteParameter)value; - - /// - /// Sets the parameter with the specified name. - /// - /// The name of the parameter to set. - /// The parameter. Must be a . - protected override void SetParameter(string parameterName, DbParameter value) - => SetParameter(IndexOfChecked(parameterName), value); - - internal int Bind(sqlite3_stmt stmt, sqlite3 handle) + /// + /// Adds multiple parameters to the collection. + /// + /// + /// An array of parameters to add. They must be objects. + /// + /// Parameters + public override void AddRange(Array values) + => AddRange(values.Cast()); + + /// + /// Adds multiple parameters to the collection. + /// + /// The parameters to add. + /// Parameters + public virtual void AddRange(IEnumerable values) + => _parameters.AddRange(values); + + /// + /// Adds a parameter to the collection. + /// + /// The name of the parameter. + /// The value of the parameter. Can be null. + /// The parameter that was added. + /// Parameters + /// Data Types + public virtual SqliteParameter AddWithValue(string? parameterName, object? value) + => Add(new SqliteParameter(parameterName, value)); + + /// + /// Removes all parameters from the collection. + /// + public override void Clear() + => _parameters.Clear(); + + /// + /// Gets a value indicating whether the collection contains the specified parameter. + /// + /// The parameter to look for. Must be a . + /// if the collection contains the parameter; otherwise, . + public override bool Contains(object value) + => Contains((SqliteParameter)value); + + /// + /// Gets a value indicating whether the collection contains the specified parameter. + /// + /// The parameter to look for. + /// if the collection contains the parameter; otherwise, . + public virtual bool Contains(SqliteParameter value) + => _parameters.Contains(value); + + /// + /// Gets a value indicating whether the collection contains a parameter with the specified name. + /// + /// The name of the parameter. + /// if the collection contains the parameter; otherwise, . + public override bool Contains(string value) + => IndexOf(value) != -1; + + /// + /// Copies the collection to an array of parameters. + /// + /// + /// The array into which the parameters are copied. Must be an array of objects. + /// + /// The zero-based index to which the parameters are copied. + public override void CopyTo(Array array, int index) + => CopyTo((SqliteParameter[])array, index); + + /// + /// Copies the collection to an array of parameters. + /// + /// The array into which the parameters are copied. + /// The zero-based index to which the parameters are copied. + public virtual void CopyTo(SqliteParameter[] array, int index) + => _parameters.CopyTo(array, index); + + /// + /// Gets an enumerator that iterates through the collection. + /// + /// The enumerator. + public override IEnumerator GetEnumerator() + => _parameters.GetEnumerator(); + + /// + /// Gets a parameter at the specified index. + /// + /// The zero-based index of the parameter. + /// The parameter. + protected override DbParameter GetParameter(int index) + => this[index]; + + /// + /// Gets a parameter with the specified name. + /// + /// The name of the parameter. + /// The parameter. + protected override DbParameter GetParameter(string parameterName) + => GetParameter(IndexOfChecked(parameterName)); + + /// + /// Gets the index of the specified parameter. + /// + /// The parameter. Must be a . + /// The zero-based index of the parameter. + public override int IndexOf(object value) + => IndexOf((SqliteParameter)value); + + /// + /// Gets the index of the specified parameter. + /// + /// The parameter. + /// The zero-based index of the parameter. + public virtual int IndexOf(SqliteParameter value) + => _parameters.IndexOf(value); + + /// + /// Gets the index of the parameter with the specified name. + /// + /// The name of the parameter. + /// The zero-based index of the parameter or -1 if not found. + public override int IndexOf(string parameterName) + { + for (var index = 0; index < _parameters.Count; index++) { - var bound = 0; - foreach (var parameter in _parameters) + if (_parameters[index].ParameterName == parameterName) { - if (parameter.Bind(stmt, handle)) - { - bound++; - } + return index; } - - return bound; } - private int IndexOfChecked(string parameterName) + return -1; + } + + /// + /// Inserts a parameter into the collection at the specified index. + /// + /// The zero-based index at which the parameter should be inserted. + /// The parameter to insert. Must be a . + public override void Insert(int index, object value) + => Insert(index, (SqliteParameter)value); + + /// + /// Inserts a parameter into the collection at the specified index. + /// + /// The zero-based index at which the parameter should be inserted. + /// The parameter to insert. + public virtual void Insert(int index, SqliteParameter value) + => _parameters.Insert(index, value); + + /// + /// Removes a parameter from the collection. + /// + /// The parameter to remove. Must be a . + public override void Remove(object value) + => Remove((SqliteParameter)value); + + /// + /// Removes a parameter from the collection. + /// + /// The parameter to remove. + public virtual void Remove(SqliteParameter value) + => _parameters.Remove(value); + + /// + /// Removes a parameter from the collection at the specified index. + /// + /// The zero-based index of the parameter to remove. + public override void RemoveAt(int index) + => _parameters.RemoveAt(index); + + /// + /// Removes a parameter with the specified name from the collection. + /// + /// The name of the parameter to remove. + public override void RemoveAt(string parameterName) + => RemoveAt(IndexOfChecked(parameterName)); + + /// + /// Sets the parameter at the specified index. + /// + /// The zero-based index of the parameter to set. + /// The parameter. Must be a . + protected override void SetParameter(int index, DbParameter value) + => this[index] = (SqliteParameter)value; + + /// + /// Sets the parameter with the specified name. + /// + /// The name of the parameter to set. + /// The parameter. Must be a . + protected override void SetParameter(string parameterName, DbParameter value) + => SetParameter(IndexOfChecked(parameterName), value); + + internal int Bind(sqlite3_stmt stmt, sqlite3 handle) + { + var bound = 0; + foreach (var parameter in _parameters) { - var index = IndexOf(parameterName); - if (index == -1) + if (parameter.Bind(stmt, handle)) { - throw new IndexOutOfRangeException(Resources.ParameterNotFound(parameterName)); + bound++; } + } + + return bound; + } - return index; + private int IndexOfChecked(string parameterName) + { + var index = IndexOf(parameterName); + if (index == -1) + { + throw new IndexOutOfRangeException(Resources.ParameterNotFound(parameterName)); } + + return index; } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteParameterReader.cs b/src/Microsoft.Data.Sqlite.Core/SqliteParameterReader.cs index 55639bfae6b..7a15a1b77e4 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteParameterReader.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteParameterReader.cs @@ -5,29 +5,28 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +internal class SqliteParameterReader(string function, sqlite3_value[] values) : SqliteValueReader { - internal class SqliteParameterReader(string function, sqlite3_value[] values) : SqliteValueReader - { - public override int FieldCount - => values.Length; + public override int FieldCount + => values.Length; - protected override string GetOnNullErrorMsg(int ordinal) - => Resources.UDFCalledWithNull(function, ordinal); + protected override string GetOnNullErrorMsg(int ordinal) + => Resources.UDFCalledWithNull(function, ordinal); - protected override double GetDoubleCore(int ordinal) - => sqlite3_value_double(values[ordinal]); + protected override double GetDoubleCore(int ordinal) + => sqlite3_value_double(values[ordinal]); - protected override long GetInt64Core(int ordinal) - => sqlite3_value_int64(values[ordinal]); + protected override long GetInt64Core(int ordinal) + => sqlite3_value_int64(values[ordinal]); - protected override string GetStringCore(int ordinal) - => sqlite3_value_text(values[ordinal]).utf8_to_string(); + protected override string GetStringCore(int ordinal) + => sqlite3_value_text(values[ordinal]).utf8_to_string(); - protected override byte[] GetBlobCore(int ordinal) - => sqlite3_value_blob(values[ordinal]).ToArray(); + protected override byte[] GetBlobCore(int ordinal) + => sqlite3_value_blob(values[ordinal]).ToArray(); - protected override int GetSqliteType(int ordinal) - => sqlite3_value_type(values[ordinal]); - } + protected override int GetSqliteType(int ordinal) + => sqlite3_value_type(values[ordinal]); } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteResultBinder.cs b/src/Microsoft.Data.Sqlite.Core/SqliteResultBinder.cs index 076261b5953..48be075f3f7 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteResultBinder.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteResultBinder.cs @@ -4,23 +4,22 @@ using SQLitePCL; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +internal class SqliteResultBinder(sqlite3_context ctx, object? value) : SqliteValueBinder(value) { - internal class SqliteResultBinder(sqlite3_context ctx, object? value) : SqliteValueBinder(value) - { - protected override void BindBlob(byte[] value) - => sqlite3_result_blob(ctx, value); + protected override void BindBlob(byte[] value) + => sqlite3_result_blob(ctx, value); - protected override void BindDoubleCore(double value) - => sqlite3_result_double(ctx, value); + protected override void BindDoubleCore(double value) + => sqlite3_result_double(ctx, value); - protected override void BindInt64(long value) - => sqlite3_result_int64(ctx, value); + protected override void BindInt64(long value) + => sqlite3_result_int64(ctx, value); - protected override void BindNull() - => sqlite3_result_null(ctx); + protected override void BindNull() + => sqlite3_result_null(ctx); - protected override void BindText(string value) - => sqlite3_result_text(ctx, value); - } + protected override void BindText(string value) + => sqlite3_result_text(ctx, value); } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteTransaction.cs b/src/Microsoft.Data.Sqlite.Core/SqliteTransaction.cs index 44ccb66dc42..4bff6484727 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteTransaction.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteTransaction.cs @@ -8,247 +8,246 @@ using Microsoft.Data.Sqlite.Properties; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Represents a transaction made against a SQLite database. +/// +/// Transactions +public class SqliteTransaction : DbTransaction { - /// - /// Represents a transaction made against a SQLite database. - /// - /// Transactions - public class SqliteTransaction : DbTransaction + private SqliteConnection? _connection; + private bool _completed; + + internal SqliteTransaction(SqliteConnection connection, IsolationLevel isolationLevel, bool deferred) { - private SqliteConnection? _connection; - private bool _completed; + if ((isolationLevel == IsolationLevel.ReadUncommitted + && ((connection.ConnectionOptions!.Cache != SqliteCacheMode.Shared) || !deferred)) + || isolationLevel == IsolationLevel.ReadCommitted + || isolationLevel == IsolationLevel.RepeatableRead + || isolationLevel == IsolationLevel.Unspecified) + { + isolationLevel = IsolationLevel.Serializable; + } + + _connection = connection; + IsolationLevel = isolationLevel; - internal SqliteTransaction(SqliteConnection connection, IsolationLevel isolationLevel, bool deferred) + if (isolationLevel == IsolationLevel.ReadUncommitted) { - if ((isolationLevel == IsolationLevel.ReadUncommitted - && ((connection.ConnectionOptions!.Cache != SqliteCacheMode.Shared) || !deferred)) - || isolationLevel == IsolationLevel.ReadCommitted - || isolationLevel == IsolationLevel.RepeatableRead - || isolationLevel == IsolationLevel.Unspecified) - { - isolationLevel = IsolationLevel.Serializable; - } + connection.ExecuteNonQuery("PRAGMA read_uncommitted = 1;"); + } + else if (isolationLevel != IsolationLevel.Serializable) + { + throw new ArgumentException(Resources.InvalidIsolationLevel(isolationLevel)); + } - _connection = connection; - IsolationLevel = isolationLevel; + connection.ExecuteNonQuery( + IsolationLevel == IsolationLevel.Serializable && !deferred + ? "BEGIN IMMEDIATE;" + : "BEGIN;"); + sqlite3_rollback_hook(connection.Handle, RollbackExternal, null); + } - if (isolationLevel == IsolationLevel.ReadUncommitted) - { - connection.ExecuteNonQuery("PRAGMA read_uncommitted = 1;"); - } - else if (isolationLevel != IsolationLevel.Serializable) - { - throw new ArgumentException(Resources.InvalidIsolationLevel(isolationLevel)); - } + /// + /// Gets the connection associated with the transaction. + /// + /// The connection associated with the transaction. + public new virtual SqliteConnection? Connection + => _connection; - connection.ExecuteNonQuery( - IsolationLevel == IsolationLevel.Serializable && !deferred - ? "BEGIN IMMEDIATE;" - : "BEGIN;"); - sqlite3_rollback_hook(connection.Handle, RollbackExternal, null); - } + /// + /// Gets the connection associated with the transaction. + /// + /// The connection associated with the transaction. + protected override DbConnection? DbConnection + => Connection; - /// - /// Gets the connection associated with the transaction. - /// - /// The connection associated with the transaction. - public new virtual SqliteConnection? Connection - => _connection; - - /// - /// Gets the connection associated with the transaction. - /// - /// The connection associated with the transaction. - protected override DbConnection? DbConnection - => Connection; - - internal bool ExternalRollback { get; private set; } - - /// - /// Gets the isolation level for the transaction. - /// - /// The isolation level for the transaction. - public override IsolationLevel IsolationLevel { get; } - - /// - /// Applies the changes made in the transaction. - /// - public override void Commit() - { - if (ExternalRollback - || _completed - || _connection!.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.TransactionCompleted); - } + internal bool ExternalRollback { get; private set; } - sqlite3_rollback_hook(_connection.Handle, null, null); - _connection.ExecuteNonQuery("COMMIT;"); - Complete(); - } + /// + /// Gets the isolation level for the transaction. + /// + /// The isolation level for the transaction. + public override IsolationLevel IsolationLevel { get; } - /// - /// Reverts the changes made in the transaction. - /// - public override void Rollback() + /// + /// Applies the changes made in the transaction. + /// + public override void Commit() + { + if (ExternalRollback + || _completed + || _connection!.State != ConnectionState.Open) { - if (_completed || _connection!.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.TransactionCompleted); - } + throw new InvalidOperationException(Resources.TransactionCompleted); + } - RollbackInternal(); + sqlite3_rollback_hook(_connection.Handle, null, null); + _connection.ExecuteNonQuery("COMMIT;"); + Complete(); + } + + /// + /// Reverts the changes made in the transaction. + /// + public override void Rollback() + { + if (_completed || _connection!.State != ConnectionState.Open) + { + throw new InvalidOperationException(Resources.TransactionCompleted); } + RollbackInternal(); + } + #if NET5_0_OR_GREATER - /// - public override bool SupportsSavepoints => true; + /// + public override bool SupportsSavepoints + => true; #endif - /// - /// Creates a savepoint in the transaction. This allows all commands that are executed after the savepoint was - /// established to be rolled back, restoring the transaction state to what it was at the time of the savepoint. - /// - /// The name of the savepoint to be created. + /// + /// Creates a savepoint in the transaction. This allows all commands that are executed after the savepoint was + /// established to be rolled back, restoring the transaction state to what it was at the time of the savepoint. + /// + /// The name of the savepoint to be created. #if NET5_0_OR_GREATER - public override void Save(string savepointName) + public override void Save(string savepointName) #else public virtual void Save(string savepointName) #endif + { + if (savepointName is null) { - if (savepointName is null) - { - throw new ArgumentNullException(nameof(savepointName)); - } - - if (_completed || _connection!.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.TransactionCompleted); - } + throw new ArgumentNullException(nameof(savepointName)); + } - _connection.ExecuteNonQuery( - new StringBuilder() - .Append("SAVEPOINT \"") - .Append(savepointName.Replace("\"", "\"\"")) - .Append("\";") - .ToString()); + if (_completed || _connection!.State != ConnectionState.Open) + { + throw new InvalidOperationException(Resources.TransactionCompleted); } - /// - /// Rolls back all commands that were executed after the specified savepoint was established. - /// - /// The name of the savepoint to roll back to. + _connection.ExecuteNonQuery( + new StringBuilder() + .Append("SAVEPOINT \"") + .Append(savepointName.Replace("\"", "\"\"")) + .Append("\";") + .ToString()); + } + + /// + /// Rolls back all commands that were executed after the specified savepoint was established. + /// + /// The name of the savepoint to roll back to. #if NET5_0_OR_GREATER - public override void Rollback(string savepointName) + public override void Rollback(string savepointName) #else public virtual void Rollback(string savepointName) #endif + { + if (savepointName is null) { - if (savepointName is null) - { - throw new ArgumentNullException(nameof(savepointName)); - } - - if (_completed || _connection!.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.TransactionCompleted); - } + throw new ArgumentNullException(nameof(savepointName)); + } - _connection.ExecuteNonQuery( - new StringBuilder() - .Append("ROLLBACK TO SAVEPOINT \"") - .Append(savepointName.Replace("\"", "\"\"")) - .Append("\";") - .ToString()); + if (_completed || _connection!.State != ConnectionState.Open) + { + throw new InvalidOperationException(Resources.TransactionCompleted); } - /// - /// Destroys a savepoint previously defined in the current transaction. This allows the system to - /// reclaim some resources before the transaction ends. - /// - /// The name of the savepoint to release. + _connection.ExecuteNonQuery( + new StringBuilder() + .Append("ROLLBACK TO SAVEPOINT \"") + .Append(savepointName.Replace("\"", "\"\"")) + .Append("\";") + .ToString()); + } + + /// + /// Destroys a savepoint previously defined in the current transaction. This allows the system to + /// reclaim some resources before the transaction ends. + /// + /// The name of the savepoint to release. #if NET5_0_OR_GREATER - public override void Release(string savepointName) + public override void Release(string savepointName) #else public virtual void Release(string savepointName) #endif + { + if (savepointName is null) { - if (savepointName is null) - { - throw new ArgumentNullException(nameof(savepointName)); - } - - if (_completed || _connection!.State != ConnectionState.Open) - { - throw new InvalidOperationException(Resources.TransactionCompleted); - } - - _connection.ExecuteNonQuery( - new StringBuilder() - .Append("RELEASE SAVEPOINT \"") - .Append(savepointName.Replace("\"", "\"\"")) - .Append("\";") - .ToString()); + throw new ArgumentNullException(nameof(savepointName)); } - /// - /// Releases any resources used by the transaction and rolls it back. - /// - /// - /// to release managed and unmanaged resources; - /// to release only unmanaged resources. - /// - protected override void Dispose(bool disposing) + if (_completed || _connection!.State != ConnectionState.Open) { - if (disposing - && !_completed - && _connection!.State == ConnectionState.Open) - { - RollbackInternal(); - } + throw new InvalidOperationException(Resources.TransactionCompleted); } - private void Complete() - { - if (IsolationLevel == IsolationLevel.ReadUncommitted) - { - try - { - _connection!.ExecuteNonQuery("PRAGMA read_uncommitted = 0;"); - } - catch - { - // Ignore failure attempting to clean up. - } - } + _connection.ExecuteNonQuery( + new StringBuilder() + .Append("RELEASE SAVEPOINT \"") + .Append(savepointName.Replace("\"", "\"\"")) + .Append("\";") + .ToString()); + } - _connection!.Transaction = null; - _connection = null; - _completed = true; + /// + /// Releases any resources used by the transaction and rolls it back. + /// + /// + /// to release managed and unmanaged resources; + /// to release only unmanaged resources. + /// + protected override void Dispose(bool disposing) + { + if (disposing + && !_completed + && _connection!.State == ConnectionState.Open) + { + RollbackInternal(); } + } - private void RollbackInternal() + private void Complete() + { + if (IsolationLevel == IsolationLevel.ReadUncommitted) { try { - if (!ExternalRollback) - { - sqlite3_rollback_hook(_connection!.Handle, null, null); - _connection.ExecuteNonQuery("ROLLBACK;"); - } + _connection!.ExecuteNonQuery("PRAGMA read_uncommitted = 0;"); } - finally + catch { - Complete(); + // Ignore failure attempting to clean up. } - } - private void RollbackExternal(object userData) + _connection!.Transaction = null; + _connection = null; + _completed = true; + } + + private void RollbackInternal() + { + try + { + if (!ExternalRollback) + { + sqlite3_rollback_hook(_connection!.Handle, null, null); + _connection.ExecuteNonQuery("ROLLBACK;"); + } + } + finally { - sqlite3_rollback_hook(_connection!.Handle, null, null); - ExternalRollback = true; + Complete(); } } + + private void RollbackExternal(object userData) + { + sqlite3_rollback_hook(_connection!.Handle, null, null); + ExternalRollback = true; + } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteType.cs b/src/Microsoft.Data.Sqlite.Core/SqliteType.cs index 043b82fa7ea..43768b0c59d 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteType.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteType.cs @@ -3,32 +3,31 @@ using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +/// +/// Represents the type affinities used by columns in SQLite tables. +/// +/// Data Types +public enum SqliteType { /// - /// Represents the type affinities used by columns in SQLite tables. + /// A signed integer. /// - /// Data Types - public enum SqliteType - { - /// - /// A signed integer. - /// - Integer = SQLITE_INTEGER, + Integer = SQLITE_INTEGER, - /// - /// A floating point value. - /// - Real = SQLITE_FLOAT, + /// + /// A floating point value. + /// + Real = SQLITE_FLOAT, - /// - /// A text string. - /// - Text = SQLITE_TEXT, + /// + /// A text string. + /// + Text = SQLITE_TEXT, - /// - /// A blob of data. - /// - Blob = SQLITE_BLOB - } + /// + /// A blob of data. + /// + Blob = SQLITE_BLOB } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteValueBinder.cs b/src/Microsoft.Data.Sqlite.Core/SqliteValueBinder.cs index 7b398e5cc5c..35fca9e4a44 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteValueBinder.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteValueBinder.cs @@ -6,312 +6,311 @@ using System.Globalization; using Microsoft.Data.Sqlite.Properties; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +// TODO: Make generic +internal abstract class SqliteValueBinder(object? value, SqliteType? sqliteType) { - // TODO: Make generic - internal abstract class SqliteValueBinder(object? value, SqliteType? sqliteType) - { - private static readonly bool Pre10TimeZoneHandling = - AppContext.TryGetSwitch("Microsoft.Data.Sqlite.Pre10TimeZoneHandling", out var enabled) && enabled; + private static readonly bool Pre10TimeZoneHandling = + AppContext.TryGetSwitch("Microsoft.Data.Sqlite.Pre10TimeZoneHandling", out var enabled) && enabled; - protected SqliteValueBinder(object? value) - : this(value, null) - { - } + protected SqliteValueBinder(object? value) + : this(value, null) + { + } - protected abstract void BindInt64(long value); + protected abstract void BindInt64(long value); - protected virtual void BindDouble(double value) + protected virtual void BindDouble(double value) + { + if (double.IsNaN(value)) { - if (double.IsNaN(value)) - { - throw new InvalidOperationException(Resources.CannotStoreNaN); - } - - BindDoubleCore(value); + throw new InvalidOperationException(Resources.CannotStoreNaN); } - protected abstract void BindDoubleCore(double value); + BindDoubleCore(value); + } + + protected abstract void BindDoubleCore(double value); - protected abstract void BindText(string value); + protected abstract void BindText(string value); - protected abstract void BindBlob(byte[] value); + protected abstract void BindBlob(byte[] value); - protected abstract void BindNull(); + protected abstract void BindNull(); - public virtual void Bind() + public virtual void Bind() + { + if (value == null) { - if (value == null) - { - BindNull(); + BindNull(); - return; - } + return; + } - var type = value.GetType().UnwrapNullableType().UnwrapEnumType(); - if (type == typeof(bool)) + var type = value.GetType().UnwrapNullableType().UnwrapEnumType(); + if (type == typeof(bool)) + { + var value1 = (bool)value ? 1L : 0; + BindInt64(value1); + } + else if (type == typeof(byte)) + { + var value1 = (long)(byte)value; + BindInt64(value1); + } + else if (type == typeof(byte[])) + { + var value1 = (byte[])value; + BindBlob(value1); + } + else if (type == typeof(char)) + { + var chr = (char)value; + if (sqliteType != SqliteType.Integer) { - var value1 = (bool)value ? 1L : 0; - BindInt64(value1); + var value = new string(chr, 1); + BindText(value); } - else if (type == typeof(byte)) + else { - var value1 = (long)(byte)value; - BindInt64(value1); + var value = (long)chr; + BindInt64(value); } - else if (type == typeof(byte[])) + } + else if (type == typeof(DateTime)) + { + var dateTime = (DateTime)value; + if (sqliteType == SqliteType.Real) { - var value1 = (byte[])value; - BindBlob(value1); + var value = ToJulianDate(dateTime); + BindDouble(value); } - else if (type == typeof(char)) + else { - var chr = (char)value; - if (sqliteType != SqliteType.Integer) - { - var value = new string(chr, 1); - BindText(value); - } - else - { - var value = (long)chr; - BindInt64(value); - } + var value = dateTime.ToString(@"yyyy\-MM\-dd HH\:mm\:ss.FFFFFFF", CultureInfo.InvariantCulture); + BindText(value); } - else if (type == typeof(DateTime)) + } + else if (type == typeof(DateTimeOffset)) + { + var dateTimeOffset = (DateTimeOffset)value; + if (sqliteType == SqliteType.Real) { - 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); - } + // Before .NET 10, handling DateTimeOffset ignored offset and wrote incorrect value into database. + var value = Pre10TimeZoneHandling + ? ToJulianDate(dateTimeOffset.DateTime) + : ToJulianDate(dateTimeOffset.ToUniversalTime().DateTime); + BindDouble(value); } - else if (type == typeof(DateTimeOffset)) + else { - var dateTimeOffset = (DateTimeOffset)value; - if (sqliteType == SqliteType.Real) - { - // Before .NET 10, handling DateTimeOffset ignored offset and wrote incorrect value into database. - var value = Pre10TimeZoneHandling - ? ToJulianDate(dateTimeOffset.DateTime) - : ToJulianDate(dateTimeOffset.ToUniversalTime().DateTime); - BindDouble(value); - } - else - { - var value = dateTimeOffset.ToString(@"yyyy\-MM\-dd HH\:mm\:ss.FFFFFFFzzz", CultureInfo.InvariantCulture); - BindText(value); - } + var value = dateTimeOffset.ToString(@"yyyy\-MM\-dd HH\:mm\:ss.FFFFFFFzzz", CultureInfo.InvariantCulture); + BindText(value); } + } #if NET6_0_OR_GREATER - else if (type == typeof(DateOnly)) - { - var dateOnly = (DateOnly)value; - if (sqliteType == SqliteType.Real) - { - var value = ToJulianDate(dateOnly.Year, dateOnly.Month, dateOnly.Day, 0, 0, 0, 0); - BindDouble(value); - } - else - { - var value = dateOnly.ToString(@"yyyy\-MM\-dd", CultureInfo.InvariantCulture); - BindText(value); - } - } - else if (type == typeof(TimeOnly)) - { - var timeOnly = (TimeOnly)value; - if (sqliteType == SqliteType.Real) - { - var value = GetTotalDays(timeOnly.Hour, timeOnly.Minute, timeOnly.Second, timeOnly.Millisecond); - BindDouble(value); - } - else - { - var value = timeOnly.Ticks % 10000000 == 0 - ? timeOnly.ToString(@"HH:mm:ss", CultureInfo.InvariantCulture) - : timeOnly.ToString(@"HH:mm:ss.fffffff", CultureInfo.InvariantCulture); - BindText(value); - } - } -#endif - else if (type == typeof(DBNull)) - { - BindNull(); - } - else if (type == typeof(decimal)) - { - var value1 = ((decimal)value).ToString("0.0###########################", CultureInfo.InvariantCulture); - BindText(value1); - } - else if (type == typeof(double)) - { - var value1 = (double)value; - BindDouble(value1); - } - else if (type == typeof(float)) - { - var value1 = (double)(float)value; - BindDouble(value1); - } - else if (type == typeof(Guid)) - { - var guid = (Guid)value; - if (sqliteType != SqliteType.Blob) - { - var value = guid.ToString().ToUpperInvariant(); - BindText(value); - } - else - { - var value = guid.ToByteArray(); - BindBlob(value); - } - } - else if (type == typeof(int)) - { - var value1 = (long)(int)value; - BindInt64(value1); - } - else if (type == typeof(long)) - { - var value1 = (long)value; - BindInt64(value1); - } - else if (type == typeof(sbyte)) + else if (type == typeof(DateOnly)) + { + var dateOnly = (DateOnly)value; + if (sqliteType == SqliteType.Real) { - var value1 = (long)(sbyte)value; - BindInt64(value1); + var value = ToJulianDate(dateOnly.Year, dateOnly.Month, dateOnly.Day, 0, 0, 0, 0); + BindDouble(value); } - else if (type == typeof(short)) + else { - var value1 = (long)(short)value; - BindInt64(value1); + var value = dateOnly.ToString(@"yyyy\-MM\-dd", CultureInfo.InvariantCulture); + BindText(value); } - else if (type == typeof(string)) + } + else if (type == typeof(TimeOnly)) + { + var timeOnly = (TimeOnly)value; + if (sqliteType == SqliteType.Real) { - var value1 = (string)value; - BindText(value1); + var value = GetTotalDays(timeOnly.Hour, timeOnly.Minute, timeOnly.Second, timeOnly.Millisecond); + BindDouble(value); } - else if (type == typeof(TimeSpan)) + else { - var timeSpan = (TimeSpan)value; - if (sqliteType == SqliteType.Real) - { - var value = timeSpan.TotalDays; - BindDouble(value); - } - else - { - var value = timeSpan.ToString("c"); - BindText(value); - } + var value = timeOnly.Ticks % 10000000 == 0 + ? timeOnly.ToString(@"HH:mm:ss", CultureInfo.InvariantCulture) + : timeOnly.ToString(@"HH:mm:ss.fffffff", CultureInfo.InvariantCulture); + BindText(value); } - else if (type == typeof(uint)) + } +#endif + else if (type == typeof(DBNull)) + { + BindNull(); + } + else if (type == typeof(decimal)) + { + var value1 = ((decimal)value).ToString("0.0###########################", CultureInfo.InvariantCulture); + BindText(value1); + } + else if (type == typeof(double)) + { + var value1 = (double)value; + BindDouble(value1); + } + else if (type == typeof(float)) + { + var value1 = (double)(float)value; + BindDouble(value1); + } + else if (type == typeof(Guid)) + { + var guid = (Guid)value; + if (sqliteType != SqliteType.Blob) { - var value1 = (long)(uint)value; - BindInt64(value1); + var value = guid.ToString().ToUpperInvariant(); + BindText(value); } - else if (type == typeof(ulong)) + else { - var value1 = (long)(ulong)value; - BindInt64(value1); + var value = guid.ToByteArray(); + BindBlob(value); } - else if (type == typeof(ushort)) + } + else if (type == typeof(int)) + { + var value1 = (long)(int)value; + BindInt64(value1); + } + else if (type == typeof(long)) + { + var value1 = (long)value; + BindInt64(value1); + } + else if (type == typeof(sbyte)) + { + var value1 = (long)(sbyte)value; + BindInt64(value1); + } + else if (type == typeof(short)) + { + var value1 = (long)(short)value; + BindInt64(value1); + } + else if (type == typeof(string)) + { + var value1 = (string)value; + BindText(value1); + } + else if (type == typeof(TimeSpan)) + { + var timeSpan = (TimeSpan)value; + if (sqliteType == SqliteType.Real) { - var value1 = (long)(ushort)value; - BindInt64(value1); + var value = timeSpan.TotalDays; + BindDouble(value); } else { - throw new InvalidOperationException(Resources.UnknownDataType(type)); + var value = timeSpan.ToString("c"); + BindText(value); } } + else if (type == typeof(uint)) + { + var value1 = (long)(uint)value; + BindInt64(value1); + } + else if (type == typeof(ulong)) + { + var value1 = (long)(ulong)value; + BindInt64(value1); + } + else if (type == typeof(ushort)) + { + var value1 = (long)(ushort)value; + BindInt64(value1); + } + else + { + throw new InvalidOperationException(Resources.UnknownDataType(type)); + } + } - private static readonly Dictionary _sqliteTypeMapping = - new() - { - { typeof(bool), SqliteType.Integer }, - { typeof(byte), SqliteType.Integer }, - { typeof(byte[]), SqliteType.Blob }, - { typeof(char), SqliteType.Text }, - { typeof(DateTime), SqliteType.Text }, - { typeof(DateTimeOffset), SqliteType.Text }, + private static readonly Dictionary _sqliteTypeMapping = + new() + { + { typeof(bool), SqliteType.Integer }, + { typeof(byte), SqliteType.Integer }, + { typeof(byte[]), SqliteType.Blob }, + { typeof(char), SqliteType.Text }, + { typeof(DateTime), SqliteType.Text }, + { typeof(DateTimeOffset), SqliteType.Text }, #if NET6_0_OR_GREATER - { typeof(DateOnly), SqliteType.Text }, - { typeof(TimeOnly), SqliteType.Text }, + { typeof(DateOnly), SqliteType.Text }, + { typeof(TimeOnly), SqliteType.Text }, #endif - { typeof(DBNull), SqliteType.Text }, - { typeof(decimal), SqliteType.Text }, - { typeof(double), SqliteType.Real }, - { typeof(float), SqliteType.Real }, - { typeof(Guid), SqliteType.Text }, - { typeof(int), SqliteType.Integer }, - { typeof(long), SqliteType.Integer }, - { typeof(sbyte), SqliteType.Integer }, - { typeof(short), SqliteType.Integer }, - { typeof(string), SqliteType.Text }, - { typeof(TimeSpan), SqliteType.Text }, - { typeof(uint), SqliteType.Integer }, - { typeof(ulong), SqliteType.Integer }, - { typeof(ushort), SqliteType.Integer } - }; + { typeof(DBNull), SqliteType.Text }, + { typeof(decimal), SqliteType.Text }, + { typeof(double), SqliteType.Real }, + { typeof(float), SqliteType.Real }, + { typeof(Guid), SqliteType.Text }, + { typeof(int), SqliteType.Integer }, + { typeof(long), SqliteType.Integer }, + { typeof(sbyte), SqliteType.Integer }, + { typeof(short), SqliteType.Integer }, + { typeof(string), SqliteType.Text }, + { typeof(TimeSpan), SqliteType.Text }, + { typeof(uint), SqliteType.Integer }, + { typeof(ulong), SqliteType.Integer }, + { typeof(ushort), SqliteType.Integer } + }; - internal static SqliteType GetSqliteType(object? value) + internal static SqliteType GetSqliteType(object? value) + { + if (value == null) { - if (value == null) - { - return SqliteType.Text; - } - - var type = value.GetType().UnwrapNullableType().UnwrapEnumType(); - if (_sqliteTypeMapping.TryGetValue(type, out var sqliteType)) - { - return sqliteType; - } - - throw new InvalidOperationException(Resources.UnknownDataType(type)); + return SqliteType.Text; } - private static double ToJulianDate(DateTime dateTime) - => ToJulianDate( - dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond); - - private static double ToJulianDate(int year, int month, int day, int hour, int minute, int second, int millisecond) + var type = value.GetType().UnwrapNullableType().UnwrapEnumType(); + if (_sqliteTypeMapping.TryGetValue(type, out var sqliteType)) { - // computeJD - var Y = year; - var M = month; - var D = day; + return sqliteType; + } - if (M <= 2) - { - Y--; - M += 12; - } + throw new InvalidOperationException(Resources.UnknownDataType(type)); + } - 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); + private static double ToJulianDate(DateTime dateTime) + => ToJulianDate( + dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond); - iJD += hour * 3600000 + minute * 60000 + (long)((second + millisecond / 1000.0) * 1000); + private static double ToJulianDate(int year, int month, int day, int hour, int minute, int second, int millisecond) + { + // computeJD + var Y = year; + var M = month; + var D = day; - return iJD / 86400000.0; + if (M <= 2) + { + Y--; + M += 12; } - private static double GetTotalDays(int hour, int minute, int second, int millisecond) - { - var iJD = hour * 3600000 + minute * 60000 + (long)((second + millisecond / 1000.0) * 1000); + 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); - return iJD / 86400000.0; - } + iJD += hour * 3600000 + minute * 60000 + (long)((second + millisecond / 1000.0) * 1000); + + return iJD / 86400000.0; + } + + private static double GetTotalDays(int hour, int minute, int second, int millisecond) + { + var iJD = hour * 3600000 + minute * 60000 + (long)((second + millisecond / 1000.0) * 1000); + + return iJD / 86400000.0; } } diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteValueReader.cs b/src/Microsoft.Data.Sqlite.Core/SqliteValueReader.cs index 585cabc0dbf..f8a6ea29378 100644 --- a/src/Microsoft.Data.Sqlite.Core/SqliteValueReader.cs +++ b/src/Microsoft.Data.Sqlite.Core/SqliteValueReader.cs @@ -7,462 +7,461 @@ using Microsoft.Data.Sqlite.Properties; using static SQLitePCL.raw; -namespace Microsoft.Data.Sqlite +namespace Microsoft.Data.Sqlite; + +internal abstract class SqliteValueReader { - internal abstract class SqliteValueReader - { - private static readonly bool Pre10TimeZoneHandling = - AppContext.TryGetSwitch("Microsoft.Data.Sqlite.Pre10TimeZoneHandling", out var enabled) && enabled; + private static readonly bool Pre10TimeZoneHandling = + AppContext.TryGetSwitch("Microsoft.Data.Sqlite.Pre10TimeZoneHandling", out var enabled) && enabled; - public abstract int FieldCount { get; } + public abstract int FieldCount { get; } - protected abstract int GetSqliteType(int ordinal); + protected abstract int GetSqliteType(int ordinal); - public virtual bool IsDBNull(int ordinal) - => GetSqliteType(ordinal) == SQLITE_NULL; + public virtual bool IsDBNull(int ordinal) + => GetSqliteType(ordinal) == SQLITE_NULL; - public virtual bool GetBoolean(int ordinal) - => GetInt64(ordinal) != 0; + public virtual bool GetBoolean(int ordinal) + => GetInt64(ordinal) != 0; - public virtual byte GetByte(int ordinal) - => checked((byte)GetInt64(ordinal)); + public virtual byte GetByte(int ordinal) + => checked((byte)GetInt64(ordinal)); - public virtual char GetChar(int ordinal) + public virtual char GetChar(int ordinal) + { + var sqliteType = GetSqliteType(ordinal); + if (sqliteType == SQLITE_TEXT) { - var sqliteType = GetSqliteType(ordinal); - if (sqliteType == SQLITE_TEXT) + var val = GetString(ordinal); + if (val.Length == 1) { - var val = GetString(ordinal); - if (val.Length == 1) - { - return val[0]; - } + return val[0]; } - - return checked((char)GetInt64(ordinal)); } - public virtual DateTime GetDateTime(int ordinal) + return checked((char)GetInt64(ordinal)); + } + + public virtual DateTime GetDateTime(int ordinal) + { + var sqliteType = GetSqliteType(ordinal); + switch (sqliteType) { - var sqliteType = GetSqliteType(ordinal); - switch (sqliteType) - { - case SQLITE_FLOAT: - case SQLITE_INTEGER: - return FromJulianDate(GetDouble(ordinal)); - - default: - { - var value = DateTime.Parse(GetString(ordinal), CultureInfo.InvariantCulture); - return Pre10TimeZoneHandling - ? value - // For .NET 10 and later, when parsing DateTime with offset, Local Kind is set. - // We convert it to Universal, for consistency. - : value.Kind switch - { - DateTimeKind.Local => value.ToUniversalTime(), - _ => value, - }; - } + case SQLITE_FLOAT: + case SQLITE_INTEGER: + return FromJulianDate(GetDouble(ordinal)); + + default: + { + var value = DateTime.Parse(GetString(ordinal), CultureInfo.InvariantCulture); + return Pre10TimeZoneHandling + ? value + // For .NET 10 and later, when parsing DateTime with offset, Local Kind is set. + // We convert it to Universal, for consistency. + : value.Kind switch + { + DateTimeKind.Local => value.ToUniversalTime(), + _ => value, + }; } } + } - public virtual DateTimeOffset GetDateTimeOffset(int ordinal) + public virtual DateTimeOffset GetDateTimeOffset(int ordinal) + { + var sqliteType = GetSqliteType(ordinal); + switch (sqliteType) { - var sqliteType = GetSqliteType(ordinal); - switch (sqliteType) + case SQLITE_FLOAT: + case SQLITE_INTEGER: + { + var value = FromJulianDate(GetDouble(ordinal)); + // Before .NET 10, for DateTimeOffset the offset was set incorrectly. + return Pre10TimeZoneHandling + ? new DateTimeOffset(value) + : new DateTimeOffset(value, TimeSpan.Zero); + } + + default: { - case SQLITE_FLOAT: - case SQLITE_INTEGER: - { - var value = FromJulianDate(GetDouble(ordinal)); - // Before .NET 10, for DateTimeOffset the offset was set incorrectly. - return Pre10TimeZoneHandling - ? new DateTimeOffset(value) - : new DateTimeOffset(value, TimeSpan.Zero); - } - - default: - { - var value = GetString(ordinal); - // Before .NET 10, DateTimeOffset, when without offset, incorrectly did not assume UTC, - // which is what it is for SQLite. - return Pre10TimeZoneHandling - ? DateTimeOffset.Parse(value, CultureInfo.InvariantCulture) - : DateTimeOffset.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); - } + var value = GetString(ordinal); + // Before .NET 10, DateTimeOffset, when without offset, incorrectly did not assume UTC, + // which is what it is for SQLite. + return Pre10TimeZoneHandling + ? DateTimeOffset.Parse(value, CultureInfo.InvariantCulture) + : DateTimeOffset.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); } } + } #if NET6_0_OR_GREATER - public virtual DateOnly GetDateOnly(int ordinal) + public virtual DateOnly GetDateOnly(int ordinal) + { + var sqliteType = GetSqliteType(ordinal); + switch (sqliteType) { - var sqliteType = GetSqliteType(ordinal); - switch (sqliteType) - { - case SQLITE_FLOAT: - case SQLITE_INTEGER: - return DateOnly.FromDateTime(FromJulianDate(GetDouble(ordinal))); + case SQLITE_FLOAT: + case SQLITE_INTEGER: + return DateOnly.FromDateTime(FromJulianDate(GetDouble(ordinal))); - default: - return DateOnly.Parse(GetString(ordinal), CultureInfo.InvariantCulture); - } + default: + return DateOnly.Parse(GetString(ordinal), CultureInfo.InvariantCulture); } + } - public virtual TimeOnly GetTimeOnly(int ordinal) - => TimeOnly.Parse(GetString(ordinal), CultureInfo.InvariantCulture); + public virtual TimeOnly GetTimeOnly(int ordinal) + => TimeOnly.Parse(GetString(ordinal), CultureInfo.InvariantCulture); #endif - public virtual decimal GetDecimal(int ordinal) - => decimal.Parse(GetString(ordinal), NumberStyles.Number | NumberStyles.AllowExponent, 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); + public virtual double GetDouble(int ordinal) + => IsDBNull(ordinal) + ? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal)) + : GetDoubleCore(ordinal); - protected abstract double GetDoubleCore(int ordinal); + protected abstract double GetDoubleCore(int ordinal); - public virtual float GetFloat(int ordinal) - => (float)GetDouble(ordinal); + public virtual float GetFloat(int ordinal) + => (float)GetDouble(ordinal); - public virtual Guid GetGuid(int ordinal) + public virtual Guid GetGuid(int ordinal) + { + var sqliteType = GetSqliteType(ordinal); + switch (sqliteType) { - var sqliteType = GetSqliteType(ordinal); - switch (sqliteType) - { - case 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)); - } + case 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) + public virtual TimeSpan GetTimeSpan(int ordinal) + { + var sqliteType = GetSqliteType(ordinal); + switch (sqliteType) { - var sqliteType = GetSqliteType(ordinal); - switch (sqliteType) - { - case SQLITE_FLOAT: - case SQLITE_INTEGER: - return TimeSpan.FromDays(GetDouble(ordinal)); - default: - return TimeSpan.Parse(GetString(ordinal)); - } + case SQLITE_FLOAT: + case SQLITE_INTEGER: + return TimeSpan.FromDays(GetDouble(ordinal)); + default: + return TimeSpan.Parse(GetString(ordinal)); } + } - public virtual short GetInt16(int ordinal) - => checked((short)GetInt64(ordinal)); + public virtual short GetInt16(int ordinal) + => checked((short)GetInt64(ordinal)); - public virtual int GetInt32(int ordinal) - => checked((int)GetInt64(ordinal)); + public virtual int GetInt32(int ordinal) + => checked((int)GetInt64(ordinal)); - public virtual long GetInt64(int ordinal) - => IsDBNull(ordinal) - ? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal)) - : GetInt64Core(ordinal); + public virtual long GetInt64(int ordinal) + => IsDBNull(ordinal) + ? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal)) + : GetInt64Core(ordinal); - protected abstract long GetInt64Core(int ordinal); + protected abstract long GetInt64Core(int ordinal); - public virtual string GetString(int ordinal) - => IsDBNull(ordinal) - ? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal)) - : GetStringCore(ordinal); + public virtual string GetString(int ordinal) + => IsDBNull(ordinal) + ? throw new InvalidOperationException(GetOnNullErrorMsg(ordinal)) + : GetStringCore(ordinal); - protected abstract string GetStringCore(int ordinal); + protected abstract string GetStringCore(int ordinal); - public virtual T? GetFieldValue(int ordinal) + public virtual T? GetFieldValue(int ordinal) + { + // First do checks for value types of T; the JIT recognizes these and elides the rest of the code. + if (typeof(T) == typeof(bool)) { - // First do checks for value types of T; the JIT recognizes these and elides the rest of the code. - if (typeof(T) == typeof(bool)) - { - return (T)(object)GetBoolean(ordinal); - } + return (T)(object)GetBoolean(ordinal); + } - if (typeof(T) == typeof(byte)) - { - return (T)(object)GetByte(ordinal); - } + if (typeof(T) == typeof(byte)) + { + return (T)(object)GetByte(ordinal); + } - if (typeof(T) == typeof(char)) - { - return (T)(object)GetChar(ordinal); - } + if (typeof(T) == typeof(char)) + { + return (T)(object)GetChar(ordinal); + } - if (typeof(T) == typeof(DateTime)) - { - return (T)(object)GetDateTime(ordinal); - } + if (typeof(T) == typeof(DateTime)) + { + return (T)(object)GetDateTime(ordinal); + } - if (typeof(T) == typeof(DateTimeOffset)) - { - return (T)(object)GetDateTimeOffset(ordinal); - } + if (typeof(T) == typeof(DateTimeOffset)) + { + return (T)(object)GetDateTimeOffset(ordinal); + } #if NET6_0_OR_GREATER - if (typeof(T) == typeof(DateOnly)) - { - return (T)(object)GetDateOnly(ordinal); - } + if (typeof(T) == typeof(DateOnly)) + { + return (T)(object)GetDateOnly(ordinal); + } - if (typeof(T) == typeof(TimeOnly)) - { - return (T)(object)GetTimeOnly(ordinal); - } + if (typeof(T) == typeof(TimeOnly)) + { + return (T)(object)GetTimeOnly(ordinal); + } #endif - if (typeof(T) == typeof(decimal)) - { - return (T)(object)GetDecimal(ordinal); - } + if (typeof(T) == typeof(decimal)) + { + return (T)(object)GetDecimal(ordinal); + } - if (typeof(T) == typeof(double)) - { - return (T)(object)GetDouble(ordinal); - } + if (typeof(T) == typeof(double)) + { + return (T)(object)GetDouble(ordinal); + } - if (typeof(T) == typeof(float)) - { - return (T)(object)GetFloat(ordinal); - } + if (typeof(T) == typeof(float)) + { + return (T)(object)GetFloat(ordinal); + } - if (typeof(T) == typeof(Guid)) - { - return (T)(object)GetGuid(ordinal); - } + if (typeof(T) == typeof(Guid)) + { + return (T)(object)GetGuid(ordinal); + } - if (typeof(T) == typeof(int)) - { - return (T)(object)GetInt32(ordinal); - } + if (typeof(T) == typeof(int)) + { + return (T)(object)GetInt32(ordinal); + } - if (typeof(T) == typeof(long)) - { - return (T)(object)GetInt64(ordinal); - } + if (typeof(T) == typeof(long)) + { + return (T)(object)GetInt64(ordinal); + } - if (typeof(T) == typeof(sbyte)) - { - return (T)(object)checked((sbyte)GetInt64(ordinal)); - } + if (typeof(T) == typeof(sbyte)) + { + return (T)(object)checked((sbyte)GetInt64(ordinal)); + } - if (typeof(T) == typeof(short)) - { - return (T)(object)GetInt16(ordinal); - } + if (typeof(T) == typeof(short)) + { + return (T)(object)GetInt16(ordinal); + } - if (typeof(T) == typeof(TimeSpan)) - { - return (T)(object)GetTimeSpan(ordinal); - } + if (typeof(T) == typeof(TimeSpan)) + { + return (T)(object)GetTimeSpan(ordinal); + } - if (typeof(T) == typeof(uint)) - { - return (T)(object)checked((uint)GetInt64(ordinal)); - } + if (typeof(T) == typeof(uint)) + { + return (T)(object)checked((uint)GetInt64(ordinal)); + } - if (typeof(T) == typeof(ulong)) - { - return (T)(object)((ulong)GetInt64(ordinal)); - } + if (typeof(T) == typeof(ulong)) + { + return (T)(object)((ulong)GetInt64(ordinal)); + } - if (typeof(T) == typeof(ushort)) - { - return (T)(object)checked((ushort)GetInt64(ordinal)); - } + if (typeof(T) == typeof(ushort)) + { + return (T)(object)checked((ushort)GetInt64(ordinal)); + } - // None of the JIT-optimized value-type checks above succeeded. - // Go into the "slow" path - from here the JIT actually emits code for the entire function. - // Start with null and string as common cases, then handle nullable/enum types. + // None of the JIT-optimized value-type checks above succeeded. + // Go into the "slow" path - from here the JIT actually emits code for the entire function. + // Start with null and string as common cases, then handle nullable/enum types. - if (IsDBNull(ordinal)) - { - return default(T) is null ? GetNull(ordinal) : throw new InvalidCastException(); - } + if (IsDBNull(ordinal)) + { + return default(T) is null ? GetNull(ordinal) : throw new InvalidCastException(); + } - if (typeof(T) == typeof(string)) - { - return (T)(object)GetString(ordinal); - } + if (typeof(T) == typeof(string)) + { + return (T)(object)GetString(ordinal); + } - var type = typeof(T).UnwrapNullableType().UnwrapEnumType(); - if (type == typeof(bool)) - { - return (T)(object)GetBoolean(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)GetByte(ordinal); + } - if (type == typeof(byte[])) - { - return (T)(object)GetBlob(ordinal)!; - } + if (type == typeof(byte[])) + { + return (T)(object)GetBlob(ordinal)!; + } - if (type == typeof(char)) - { - return (T)(object)GetChar(ordinal); - } + if (type == typeof(char)) + { + return (T)(object)GetChar(ordinal); + } - if (type == typeof(DateTime)) - { - return (T)(object)GetDateTime(ordinal); - } + if (type == typeof(DateTime)) + { + return (T)(object)GetDateTime(ordinal); + } - if (type == typeof(DateTimeOffset)) - { - return (T)(object)GetDateTimeOffset(ordinal); - } + if (type == typeof(DateTimeOffset)) + { + return (T)(object)GetDateTimeOffset(ordinal); + } #if NET6_0_OR_GREATER - if (type == typeof(DateOnly)) - { - return (T)(object)GetDateOnly(ordinal); - } + if (type == typeof(DateOnly)) + { + return (T)(object)GetDateOnly(ordinal); + } - if (type == typeof(TimeOnly)) - { - return (T)(object)GetTimeOnly(ordinal); - } + if (type == typeof(TimeOnly)) + { + return (T)(object)GetTimeOnly(ordinal); + } #endif - 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(decimal)) + { + return (T)(object)GetDecimal(ordinal); + } - if (type == typeof(Guid)) - { - return (T)(object)GetGuid(ordinal); - } + if (type == typeof(double)) + { + return (T)(object)GetDouble(ordinal); + } - if (type == typeof(int)) - { - return (T)(object)GetInt32(ordinal); - } + if (type == typeof(float)) + { + return (T)(object)GetFloat(ordinal); + } - if (type == typeof(long)) - { - return (T)(object)GetInt64(ordinal); - } + if (type == typeof(Guid)) + { + return (T)(object)GetGuid(ordinal); + } - if (type == typeof(sbyte)) - { - return (T)(object)checked((sbyte)GetInt64(ordinal)); - } + if (type == typeof(int)) + { + return (T)(object)GetInt32(ordinal); + } - if (type == typeof(short)) - { - return (T)(object)GetInt16(ordinal); - } + if (type == typeof(long)) + { + return (T)(object)GetInt64(ordinal); + } - if (type == typeof(TimeSpan)) - { - return (T)(object)GetTimeSpan(ordinal); - } + if (type == typeof(sbyte)) + { + return (T)(object)checked((sbyte)GetInt64(ordinal)); + } - if (type == typeof(uint)) - { - return (T)(object)checked((uint)GetInt64(ordinal)); - } + if (type == typeof(short)) + { + return (T)(object)GetInt16(ordinal); + } - if (type == typeof(ulong)) - { - return (T)(object)((ulong)GetInt64(ordinal)); - } + if (type == typeof(TimeSpan)) + { + return (T)(object)GetTimeSpan(ordinal); + } - if (type == typeof(ushort)) - { - return (T)(object)checked((ushort)GetInt64(ordinal)); - } + if (type == typeof(uint)) + { + return (T)(object)checked((uint)GetInt64(ordinal)); + } - return (T)GetValue(ordinal)!; + if (type == typeof(ulong)) + { + return (T)(object)((ulong)GetInt64(ordinal)); } - public virtual object? GetValue(int ordinal) - => GetSqliteType(ordinal) switch - { - SQLITE_INTEGER => GetInt64(ordinal), - SQLITE_FLOAT => GetDouble(ordinal), - SQLITE_TEXT => GetString(ordinal), - SQLITE_NULL => GetNull(ordinal), - SQLITE_BLOB => GetBlob(ordinal), + if (type == typeof(ushort)) + { + return (T)(object)checked((ushort)GetInt64(ordinal)); + } - _ => throw new ArgumentOutOfRangeException("Unexpected column type: " + GetSqliteType(ordinal)) - }; + return (T)GetValue(ordinal)!; + } - public virtual int GetValues(object?[] values) + public virtual object? GetValue(int ordinal) + => GetSqliteType(ordinal) switch { - int i; - for (i = 0; i < FieldCount; i++) - { - values[i] = GetValue(i); - } + SQLITE_INTEGER => GetInt64(ordinal), + SQLITE_FLOAT => GetDouble(ordinal), + SQLITE_TEXT => GetString(ordinal), + SQLITE_NULL => GetNull(ordinal), + SQLITE_BLOB => GetBlob(ordinal), - return i; - } - - protected virtual byte[]? GetBlob(int ordinal) - => IsDBNull(ordinal) - ? GetNull(ordinal) - : GetBlobCore(ordinal) ?? []; + _ => throw new ArgumentOutOfRangeException("Unexpected column type: " + GetSqliteType(ordinal)) + }; - protected abstract byte[] GetBlobCore(int ordinal); + public virtual int GetValues(object?[] values) + { + int i; + for (i = 0; i < FieldCount; i++) + { + values[i] = GetValue(i); + } - protected virtual T? GetNull(int ordinal) - => typeof(T) == typeof(DBNull) - ? (T)(object)DBNull.Value - : default; + return i; + } - protected virtual string GetOnNullErrorMsg(int ordinal) - => Resources.CalledOnNullValue(ordinal); + protected virtual byte[]? GetBlob(int ordinal) + => IsDBNull(ordinal) + ? GetNull(ordinal) + : GetBlobCore(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; + protected abstract byte[] GetBlobCore(int ordinal); - // 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; + protected virtual T? GetNull(int ordinal) + => typeof(T) == typeof(DBNull) + ? (T)(object)DBNull.Value + : default; - var second = (int)fracSecond; - var millisecond = (int)Math.Round((fracSecond - second) * 1000.0); + protected virtual string GetOnNullErrorMsg(int ordinal) + => Resources.CalledOnNullValue(ordinal); - return new DateTime(year, month, day, hour, minute, second, millisecond); - } + 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); } } diff --git a/src/Microsoft.Data.Sqlite.Core/Utilities/AllowNullAttribute.cs b/src/Microsoft.Data.Sqlite.Core/Utilities/AllowNullAttribute.cs index b99e58fb844..8bcfa0fbde7 100644 --- a/src/Microsoft.Data.Sqlite.Core/Utilities/AllowNullAttribute.cs +++ b/src/Microsoft.Data.Sqlite.Core/Utilities/AllowNullAttribute.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. #if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER) - namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] diff --git a/src/Microsoft.Data.Sqlite.Core/Utilities/MemberNotNullAttribute.cs b/src/Microsoft.Data.Sqlite.Core/Utilities/MemberNotNullAttribute.cs index 6b4f96fc4ee..5de368fd34b 100644 --- a/src/Microsoft.Data.Sqlite.Core/Utilities/MemberNotNullAttribute.cs +++ b/src/Microsoft.Data.Sqlite.Core/Utilities/MemberNotNullAttribute.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. #if !NET5_0_OR_GREATER - namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] diff --git a/src/Microsoft.Data.Sqlite.Core/Utilities/SharedStopwatch.cs b/src/Microsoft.Data.Sqlite.Core/Utilities/SharedStopwatch.cs index 26d769e1eed..0b9c0513638 100644 --- a/src/Microsoft.Data.Sqlite.Core/Utilities/SharedStopwatch.cs +++ b/src/Microsoft.Data.Sqlite.Core/Utilities/SharedStopwatch.cs @@ -14,11 +14,10 @@ internal readonly struct SharedStopwatch private readonly TimeSpan _started; private SharedStopwatch(TimeSpan started) - { - _started = started; - } + => _started = started; - public TimeSpan Elapsed => Stopwatch.Elapsed - _started; + public TimeSpan Elapsed + => Stopwatch.Elapsed - _started; public static SharedStopwatch StartNew() { @@ -37,5 +36,5 @@ public static SharedStopwatch StartNew() } private static SharedStopwatch StartNewCore() - => new SharedStopwatch(Stopwatch.Elapsed); + => new(Stopwatch.Elapsed); } diff --git a/src/Shared/DictionaryExtensions.cs b/src/Shared/DictionaryExtensions.cs index 0f18964b843..78c1c4ce1c5 100644 --- a/src/Shared/DictionaryExtensions.cs +++ b/src/Shared/DictionaryExtensions.cs @@ -32,7 +32,7 @@ public static TValue GetOrAddNew( public static bool TryGetAndRemove( this IDictionary source, TKey key, - [NotNullWhen(true)] out TReturn value) + [NotNullWhen(true)] out TReturn? value) { if (source.TryGetValue(key, out var item) && item != null) @@ -42,7 +42,7 @@ public static bool TryGetAndRemove( return true; } - value = default!; + value = default; return false; } diff --git a/src/dotnet-ef/Project.cs b/src/dotnet-ef/Project.cs index f176c26e635..68e0203665e 100644 --- a/src/dotnet-ef/Project.cs +++ b/src/dotnet-ef/Project.cs @@ -51,10 +51,7 @@ public static Project FromFile( { Debug.Assert(!string.IsNullOrEmpty(file), "file is null or empty."); - var args = new List - { - "msbuild", - }; + var args = new List { "msbuild", }; if (framework != null) { diff --git a/src/dotnet-ef/dotnet-ef.csproj b/src/dotnet-ef/dotnet-ef.csproj index 9b7776d36eb..41659c087b8 100644 --- a/src/dotnet-ef/dotnet-ef.csproj +++ b/src/dotnet-ef/dotnet-ef.csproj @@ -1,16 +1,17 @@  - Entity Framework Core Tools for the .NET Command-Line Interface. + + Entity Framework Core Tools for the .NET Command-Line Interface. -Enables these commonly used dotnet-ef commands: -dotnet ef migrations add -dotnet ef migrations list -dotnet ef migrations script -dotnet ef dbcontext info -dotnet ef dbcontext scaffold -dotnet ef database drop -dotnet ef database update + Enables these commonly used dotnet-ef commands: + dotnet ef migrations add + dotnet ef migrations list + dotnet ef migrations script + dotnet ef dbcontext info + dotnet ef dbcontext scaffold + dotnet ef database drop + dotnet ef database update $(DefaultNetCoreTargetFramework) Exe @@ -91,4 +92,4 @@ dotnet ef database update - + \ No newline at end of file diff --git a/src/dotnet-ef/dotnet-ef.nuspec b/src/dotnet-ef/dotnet-ef.nuspec index 636741941be..4e908612135 100644 --- a/src/dotnet-ef/dotnet-ef.nuspec +++ b/src/dotnet-ef/dotnet-ef.nuspec @@ -1,4 +1,5 @@ + $CommonMetadataElements$ @@ -23,4 +24,4 @@ - + \ No newline at end of file diff --git a/src/ef/AppDomainOperationExecutor.cs b/src/ef/AppDomainOperationExecutor.cs index 4d08e787863..1b6506a75d8 100644 --- a/src/ef/AppDomainOperationExecutor.cs +++ b/src/ef/AppDomainOperationExecutor.cs @@ -31,7 +31,9 @@ public AppDomainOperationExecutor( bool nullable, string[] remainingArguments, IOperationReportHandler reportHandler) - : base(assembly, startupAssembly, designAssembly, project, projectDir, rootNamespace, language, nullable, remainingArguments, reportHandler) + : base( + assembly, startupAssembly, designAssembly, project, projectDir, rootNamespace, language, nullable, remainingArguments, + reportHandler) { var info = new AppDomainSetup { ApplicationBase = AppBasePath }; @@ -68,7 +70,7 @@ public AppDomainOperationExecutor( if (DesignAssemblyPath != null) { - _domain.AssemblyResolve += (object? sender, ResolveEventArgs args) => + _domain.AssemblyResolve += (sender, args) => { var assemblyPath = Path.Combine(Path.GetDirectoryName(DesignAssemblyPath)!, args.Name + ".dll"); return File.Exists(assemblyPath) ? Assembly.LoadFrom(assemblyPath) : null; @@ -111,7 +113,7 @@ public override string? EFCoreVersion var designAssembly = _domain.GetAssemblies().Single(assembly => assembly.GetName().Name == DesignAssemblyName); _efcoreVersion = designAssembly.GetCustomAttribute() - ?.InformationalVersion; + ?.InformationalVersion; return _efcoreVersion; } } diff --git a/src/ef/CommandException.cs b/src/ef/CommandException.cs index a471c0db778..6c5a05bd5e8 100644 --- a/src/ef/CommandException.cs +++ b/src/ef/CommandException.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; - namespace Microsoft.EntityFrameworkCore.Tools; internal class CommandException : Exception diff --git a/src/ef/CommandLineUtils/CommandArgument.cs b/src/ef/CommandLineUtils/CommandArgument.cs index ad629e7802b..592e53ce19e 100644 --- a/src/ef/CommandLineUtils/CommandArgument.cs +++ b/src/ef/CommandLineUtils/CommandArgument.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. + namespace Microsoft.DotNet.Cli.CommandLine; -using System.Linq; internal class CommandArgument { diff --git a/src/ef/CommandLineUtils/CommandLineApplication.cs b/src/ef/CommandLineUtils/CommandLineApplication.cs index f71a0611e0b..00d83a184db 100644 --- a/src/ef/CommandLineUtils/CommandLineApplication.cs +++ b/src/ef/CommandLineUtils/CommandLineApplication.cs @@ -176,15 +176,12 @@ private static ParseOptionResult ParseOption( if (isLongOption) { - option = command.Options.SingleOrDefault( - opt => string.Equals(opt.LongName, optionName, StringComparison.Ordinal)); + option = command.Options.SingleOrDefault(opt => string.Equals(opt.LongName, optionName, StringComparison.Ordinal)); } else { - option = command.Options.SingleOrDefault( - opt => string.Equals(opt.ShortName, optionName, StringComparison.Ordinal)) - ?? command.Options.SingleOrDefault( - opt => string.Equals(opt.SymbolName, optionName, StringComparison.Ordinal)); + option = command.Options.SingleOrDefault(opt => string.Equals(opt.ShortName, optionName, StringComparison.Ordinal)) + ?? command.Options.SingleOrDefault(opt => string.Equals(opt.SymbolName, optionName, StringComparison.Ordinal)); } if (option == null) diff --git a/src/ef/Commands/CommandBase.cs b/src/ef/Commands/CommandBase.cs index d43ea01a4e9..e0868c05507 100644 --- a/src/ef/Commands/CommandBase.cs +++ b/src/ef/Commands/CommandBase.cs @@ -16,17 +16,16 @@ public virtual void Configure(CommandLineApplication command) command.HandleResponseFiles = true; - command.OnExecute( - args => - { - Reporter.IsVerbose = verbose.HasValue(); - Reporter.NoColor = noColor.HasValue(); - Reporter.PrefixOutput = prefixOutput.HasValue(); + command.OnExecute(args => + { + Reporter.IsVerbose = verbose.HasValue(); + Reporter.NoColor = noColor.HasValue(); + Reporter.PrefixOutput = prefixOutput.HasValue(); - Validate(); + Validate(); - return Execute(args); - }); + return Execute(args); + }); } protected virtual void Validate() diff --git a/src/ef/Commands/ProjectCommandBase.cs b/src/ef/Commands/ProjectCommandBase.cs index 1ee22436bf5..0c926a488ba 100644 --- a/src/ef/Commands/ProjectCommandBase.cs +++ b/src/ef/Commands/ProjectCommandBase.cs @@ -1,128 +1,89 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; -using Microsoft.DotNet.Cli.CommandLine; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.EntityFrameworkCore.Tools.Properties; #if NET using System.Runtime.Loader; #else using System.Configuration; #endif +using System.Reflection; +using Microsoft.DotNet.Cli.CommandLine; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.EntityFrameworkCore.Tools.Properties; + +namespace Microsoft.EntityFrameworkCore.Tools.Commands; -namespace Microsoft.EntityFrameworkCore.Tools.Commands +internal abstract class ProjectCommandBase : EFCommandBase { - internal abstract class ProjectCommandBase : EFCommandBase - { - private CommandOption? _dataDir; - private CommandOption? _projectDir; - private CommandOption? _rootNamespace; - private CommandOption? _language; - private CommandOption? _nullable; - private CommandOption? _designAssembly; + private CommandOption? _dataDir; + private CommandOption? _projectDir; + private CommandOption? _rootNamespace; + private CommandOption? _language; + private CommandOption? _nullable; + private CommandOption? _designAssembly; - protected CommandOption? Assembly { get; private set; } - protected CommandOption? Project { get; private set; } - protected CommandOption? StartupAssembly { get; private set; } - protected CommandOption? StartupProject { get; private set; } - protected CommandOption? WorkingDir { get; private set; } - protected CommandOption? Framework { get; private set; } - protected CommandOption? Configuration { get; private set; } + protected CommandOption? Assembly { get; private set; } + protected CommandOption? Project { get; private set; } + protected CommandOption? StartupAssembly { get; private set; } + protected CommandOption? StartupProject { get; private set; } + protected CommandOption? WorkingDir { get; private set; } + protected CommandOption? Framework { get; private set; } + protected CommandOption? Configuration { get; private set; } + public override void Configure(CommandLineApplication command) + { + command.AllowArgumentSeparator = true; - public override void Configure(CommandLineApplication command) - { - command.AllowArgumentSeparator = true; + Assembly = command.Option("-a|--assembly ", Resources.AssemblyDescription); + Project = command.Option("--project ", Resources.ProjectDescription); + StartupAssembly = command.Option("-s|--startup-assembly ", Resources.StartupAssemblyDescription); + StartupProject = command.Option("--startup-project ", Resources.StartupProjectDescription); + _dataDir = command.Option("--data-dir ", Resources.DataDirDescription); + _projectDir = command.Option("--project-dir ", Resources.ProjectDirDescription); + _rootNamespace = command.Option("--root-namespace ", Resources.RootNamespaceDescription); + _language = command.Option("--language ", Resources.LanguageDescription); + _nullable = command.Option("--nullable", Resources.NullableDescription); + WorkingDir = command.Option("--working-dir ", Resources.WorkingDirDescription); + Framework = command.Option("--framework ", Resources.FrameworkDescription); + Configuration = command.Option("--configuration ", Resources.ConfigurationDescription); + _designAssembly = command.Option("--design-assembly ", Resources.DesignAssemblyDescription); - Assembly = command.Option("-a|--assembly ", Resources.AssemblyDescription); - Project = command.Option("--project ", Resources.ProjectDescription); - StartupAssembly = command.Option("-s|--startup-assembly ", Resources.StartupAssemblyDescription); - StartupProject = command.Option("--startup-project ", Resources.StartupProjectDescription); - _dataDir = command.Option("--data-dir ", Resources.DataDirDescription); - _projectDir = command.Option("--project-dir ", Resources.ProjectDirDescription); - _rootNamespace = command.Option("--root-namespace ", Resources.RootNamespaceDescription); - _language = command.Option("--language ", Resources.LanguageDescription); - _nullable = command.Option("--nullable", Resources.NullableDescription); - WorkingDir = command.Option("--working-dir ", Resources.WorkingDirDescription); - Framework = command.Option("--framework ", Resources.FrameworkDescription); - Configuration = command.Option("--configuration ", Resources.ConfigurationDescription); - _designAssembly = command.Option("--design-assembly ", Resources.DesignAssemblyDescription); + base.Configure(command); + } - base.Configure(command); - } + protected override void Validate() + { + base.Validate(); - protected override void Validate() + if (!Assembly!.HasValue()) { - base.Validate(); - - if (!Assembly!.HasValue()) - { - throw new CommandException(Resources.MissingOption(Assembly.LongName)); - } + throw new CommandException(Resources.MissingOption(Assembly.LongName)); + } - if (!File.Exists(Assembly.Value())) - { - throw new CommandException(Resources.FileNotFound(Assembly.Value())); - } + if (!File.Exists(Assembly.Value())) + { + throw new CommandException(Resources.FileNotFound(Assembly.Value())); + } - if (StartupAssembly!.HasValue() && !File.Exists(StartupAssembly.Value())) - { - throw new CommandException(Resources.FileNotFound(StartupAssembly.Value())); - } + if (StartupAssembly!.HasValue() && !File.Exists(StartupAssembly.Value())) + { + throw new CommandException(Resources.FileNotFound(StartupAssembly.Value())); } + } - protected IOperationExecutor CreateExecutor(string[] remainingArguments) + protected IOperationExecutor CreateExecutor(string[] remainingArguments) + { + try { + var reportHandler = new OperationReportHandler( + Reporter.WriteError, + Reporter.WriteWarning, + Reporter.WriteInformation, + Reporter.WriteVerbose); +#if !NET try { - var reportHandler = new OperationReportHandler( - Reporter.WriteError, - Reporter.WriteWarning, - Reporter.WriteInformation, - Reporter.WriteVerbose); -#if !NET - try - { - return new AppDomainOperationExecutor( - Assembly!.Value()!, - StartupAssembly!.Value(), - _designAssembly!.Value(), - Project!.Value(), - _projectDir!.Value(), - _dataDir!.Value(), - _rootNamespace!.Value(), - _language!.Value(), - _nullable!.HasValue(), - remainingArguments, - reportHandler); - } - catch (MissingMethodException) // NB: Thrown with EF Core 3.1 - { - var configurationFile = (StartupAssembly!.Value() ?? Assembly!.Value()!) + ".config"; - if (File.Exists(configurationFile)) - { - AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configurationFile); - try - { - typeof(ConfigurationManager) - .GetField("s_initState", BindingFlags.Static | BindingFlags.NonPublic) - .SetValue(null, 0); - typeof(ConfigurationManager) - .GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic) - .SetValue(null, null); - typeof(ConfigurationManager).Assembly - .GetType("System.Configuration.ClientConfigPaths") - .GetField("s_current", BindingFlags.Static | BindingFlags.NonPublic) - .SetValue(null, null); - } - catch - { - } - } - } -#endif - return new ReflectionOperationExecutor( + return new AppDomainOperationExecutor( Assembly!.Value()!, StartupAssembly!.Value(), _designAssembly!.Value(), @@ -135,16 +96,53 @@ protected IOperationExecutor CreateExecutor(string[] remainingArguments) remainingArguments, reportHandler); } - catch (FileNotFoundException ex) - when (ex.FileName != null - && new AssemblyName(ex.FileName).Name == OperationExecutorBase.DesignAssemblyName) + catch (MissingMethodException) // NB: Thrown with EF Core 3.1 { - throw new CommandException( - Resources.DesignNotFound( - Path.GetFileNameWithoutExtension( - StartupAssembly!.HasValue() ? StartupAssembly.Value() : Assembly!.Value())), - ex); + var configurationFile = (StartupAssembly!.Value() ?? Assembly!.Value()!) + ".config"; + if (File.Exists(configurationFile)) + { + AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configurationFile); + try + { + typeof(ConfigurationManager) + .GetField("s_initState", BindingFlags.Static | BindingFlags.NonPublic) + .SetValue(null, 0); + typeof(ConfigurationManager) + .GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic) + .SetValue(null, null); + typeof(ConfigurationManager).Assembly + .GetType("System.Configuration.ClientConfigPaths") + .GetField("s_current", BindingFlags.Static | BindingFlags.NonPublic) + .SetValue(null, null); + } + catch + { + } + } } +#endif + return new ReflectionOperationExecutor( + Assembly!.Value()!, + StartupAssembly!.Value(), + _designAssembly!.Value(), + Project!.Value(), + _projectDir!.Value(), + _dataDir!.Value(), + _rootNamespace!.Value(), + _language!.Value(), + _nullable!.HasValue(), + remainingArguments, + reportHandler); + } + catch (FileNotFoundException ex) + when (ex.FileName != null + && new AssemblyName(ex.FileName).Name == OperationExecutorBase.DesignAssemblyName) + { + throw new CommandException( + Resources.DesignNotFound( + Path.GetFileNameWithoutExtension( + StartupAssembly!.HasValue() ? StartupAssembly.Value() : Assembly!.Value())), + ex); } } } diff --git a/src/ef/IOperationExecutor.cs b/src/ef/IOperationExecutor.cs index 42fd73882b2..9304f0b2d4a 100644 --- a/src/ef/IOperationExecutor.cs +++ b/src/ef/IOperationExecutor.cs @@ -16,6 +16,7 @@ internal interface IOperationExecutor : IDisposable IDictionary GetContextInfo(string? name); void UpdateDatabase(string? migration, string? connectionString, string? contextType); IEnumerable GetContextTypes(); + IEnumerable OptimizeContext( string? outputDir, string? modelNamespace, diff --git a/src/ef/NotNullIfNotNullAttribute.cs b/src/ef/NotNullIfNotNullAttribute.cs index 49ee73d01b5..ea0aa9f878e 100644 --- a/src/ef/NotNullIfNotNullAttribute.cs +++ b/src/ef/NotNullIfNotNullAttribute.cs @@ -9,9 +9,7 @@ namespace System.Diagnostics.CodeAnalysis internal sealed class NotNullIfNotNullAttribute : Attribute { public NotNullIfNotNullAttribute(string parameterName) - { - ParameterName = parameterName; - } + => ParameterName = parameterName; public string ParameterName { get; } } diff --git a/src/ef/OperationExecutorBase.cs b/src/ef/OperationExecutorBase.cs index f007f9cf654..807acaf036e 100644 --- a/src/ef/OperationExecutorBase.cs +++ b/src/ef/OperationExecutorBase.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; -using Microsoft.EntityFrameworkCore.Tools.Properties; using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Design.Internal; +using Microsoft.EntityFrameworkCore.Tools.Properties; namespace Microsoft.EntityFrameworkCore.Tools; diff --git a/src/ef/Program.cs b/src/ef/Program.cs index 8b584c0c808..dc5a5deda48 100644 --- a/src/ef/Program.cs +++ b/src/ef/Program.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Text; using Microsoft.DotNet.Cli.CommandLine; using Microsoft.EntityFrameworkCore.Tools.Commands; diff --git a/src/ef/ReflectionOperationExecutor.cs b/src/ef/ReflectionOperationExecutor.cs index 9e56991ce02..ca4997884ce 100644 --- a/src/ef/ReflectionOperationExecutor.cs +++ b/src/ef/ReflectionOperationExecutor.cs @@ -3,13 +3,13 @@ using System.Collections; using System.Reflection; -#if NET -using System.Runtime.Loader; -#endif using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Design.Internal; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Tools.Properties; +#if NET +using System.Runtime.Loader; +#endif namespace Microsoft.EntityFrameworkCore.Tools; @@ -37,7 +37,9 @@ public ReflectionOperationExecutor( bool nullable, string[] remainingArguments, IOperationReportHandler reportHandler) - : base(assembly, startupAssembly, designAssembly, project, projectDir, rootNamespace, language, nullable, remainingArguments, reportHandler) + : base( + assembly, startupAssembly, designAssembly, project, projectDir, rootNamespace, language, nullable, remainingArguments, + reportHandler) { var reporter = new OperationReporter(reportHandler); var configurationFile = (startupAssembly ?? assembly) + ".config"; @@ -148,7 +150,7 @@ public override string? EFCoreVersion } #endif _efcoreVersion = assembly.GetCustomAttribute() - ?.InformationalVersion; + ?.InformationalVersion; return _efcoreVersion; } } diff --git a/test/EFCore.Design.Tests/Migrations/Design/SnapshotModelProcessorTest.cs b/test/EFCore.Design.Tests/Migrations/Design/SnapshotModelProcessorTest.cs index c7070dcc763..f61baa67fc2 100644 --- a/test/EFCore.Design.Tests/Migrations/Design/SnapshotModelProcessorTest.cs +++ b/test/EFCore.Design.Tests/Migrations/Design/SnapshotModelProcessorTest.cs @@ -273,7 +273,7 @@ private static IModel PreprocessModel(ModelSnapshot snapshot) property.SetValueGenerationStrategy(null); } } - else if (property.GetValueGenerationStrategy() is SqlServerValueGenerationStrategy strategy + else if (property.GetValueGenerationStrategy() is var strategy && strategy != SqlServerValueGenerationStrategy.None) { property.SetValueGenerationStrategy(strategy); diff --git a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs index 2d40977dd48..09b9e77288b 100644 --- a/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs +++ b/test/EFCore.Relational.Tests/Infrastructure/RelationalModelValidatorTest.cs @@ -3183,7 +3183,6 @@ public virtual void Detects_generated_properties_mapped_to_result_and_parameter( .HasParameter(a => a.Name, p => p.IsInputOutput()) .HasResultColumn(a => a.Name)) .Property(a => a.Name).ValueGeneratedOnUpdate().Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save); - ; VerifyError( RelationalStrings.StoredProcedureResultColumnParameterConflict(nameof(Animal), nameof(Animal.Name), "Animal_Update"), @@ -3396,7 +3395,6 @@ public virtual void Passes_on_derived_entity_type_not_mapped_to_a_stored_procedu .HasParameter("FavoritePersonId") .HasResultColumn(a => a.Name)) .Property(a => a.Name).ValueGeneratedOnUpdate().Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save); - ; modelBuilder.Entity(); Validate(modelBuilder); @@ -3415,7 +3413,6 @@ public virtual void Detects_missing_generated_stored_procedure_parameters_in_TPT .HasParameter("FavoritePersonId") .HasResultColumn(a => a.Name)) .Property(a => a.Name).ValueGeneratedOnUpdate().Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save); - ; modelBuilder.Entity() .UpdateUsingStoredProcedure(s => s.HasParameter(c => c.Breed)); diff --git a/test/EFCore.SqlServer.FunctionalTests/ModelBuilding/SqlServerModelBuilderTestBase.cs b/test/EFCore.SqlServer.FunctionalTests/ModelBuilding/SqlServerModelBuilderTestBase.cs index 1338945675d..55fa6b9dbee 100644 --- a/test/EFCore.SqlServer.FunctionalTests/ModelBuilding/SqlServerModelBuilderTestBase.cs +++ b/test/EFCore.SqlServer.FunctionalTests/ModelBuilding/SqlServerModelBuilderTestBase.cs @@ -208,9 +208,7 @@ public virtual void Can_set_store_type_for_primitive_collection() b.PrimitiveCollection("Charm").HasColumnType("nvarchar(25)"); b.PrimitiveCollection("Strange").HasColumnType("text"); b.PrimitiveCollection>("Top").HasColumnType("char(100)"); - ; b.PrimitiveCollection?>("Bottom").HasColumnType("varchar(max)"); - ; }); var model = modelBuilder.FinalizeModel(); diff --git a/test/EFCore.SqlServer.FunctionalTests/StoreGeneratedSentinelSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/StoreGeneratedSentinelSqlServerTest.cs index 03aaa9ddb21..75107fa3c75 100644 --- a/test/EFCore.SqlServer.FunctionalTests/StoreGeneratedSentinelSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/StoreGeneratedSentinelSqlServerTest.cs @@ -318,9 +318,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con }); modelBuilder.Entity().Property(e => e.Id).HasSentinel(UriSentinel); - ; modelBuilder.Entity().Property(e => e.Id).HasSentinel(KeyEnumSentinel); - ; modelBuilder.Entity().Property(e => e.Id).HasSentinel(GuidAsStringSentinel); modelBuilder.Entity().Property(e => e.Id).HasSentinel(StringAsGuidSentinel); }