From d1fd30f1d9f74f5ed9c736815e8ca0246d205263 Mon Sep 17 00:00:00 2001 From: MaceWindu Date: Sat, 12 Nov 2022 18:13:38 +0100 Subject: [PATCH] ef.core 7 support (#263) * efcore 7 support * fix connection strings * suppress dependency errors * disable C# 11 features temporary * there will be no API-breaking changes in this area within major version --- .gitignore | 44 +--- Build/linq2db.Default.props | 5 +- Build/linq2db.Tests.props | 4 +- Directory.Packages.props | 26 +- NuGet/linq2db.EntityFrameworkCore.nuspec | 6 +- .../EFConnectionInfo.cs | 2 +- .../EFCoreMetadataReader.cs | 40 +-- .../EFProviderInfo.cs | 2 +- .../ILinqToDBForEFTools.cs | 1 - .../Internal/LinqToDBForEFQueryProvider.cs | 2 +- .../LinqToDBExtensionsAdapter.cs | 10 +- .../LinqToDBForEFExtensions.Async.EF.cs | 8 +- .../LinqToDBForEFTools.Mapping.cs | 3 +- .../LinqToDBForEFTools.cs | 8 +- .../LinqToDBForEFToolsDataConnection.cs | 13 +- .../LinqToDBForEFToolsDataContext.cs | 1 - .../LinqToDBForEFToolsException.cs | 2 +- .../LinqToDBForEFToolsImplDefault.cs | 121 +++++---- .../LinqToDBProviderInfo.cs | 2 +- .../Properties/JetBrains.Annotations.cs | 1 - .../linq2db.EntityFrameworkCore.csproj | 1 - .../ForMappingTestsBase.cs | 6 +- .../Logging/NullExternalScopeProvider.cs | 6 +- .../Logging/NullScope.cs | 2 +- .../Logging/TestLogger.cs | 41 ++- .../Logging/TestLoggerProvider.cs | 2 +- .../Models/Northwind/NorthwindData.cs | 6 +- .../ForMappingTests.cs | 6 +- ...tityFrameworkCore.PomeloMySql.Tests.csproj | 10 +- .../Models/Northwind.Mapping/EmployeesMap.cs | 2 +- .../Models/Northwind.Mapping/OrderMap.cs | 6 +- .../Models/Northwind.Mapping/ProductsMap.cs | 4 +- .../PomeloMySqlTests.cs | 6 +- .../ForMappingTests.cs | 1 + .../Models/ForMapping/ForMappingContext.cs | 2 - .../Models/NpgSqlEntities/EntityWithXmin.cs | 3 +- .../Models/NpgSqlEntities/Event.cs | 4 +- .../NpgSqlEntities/NpgSqlEnititesContext.cs | 2 +- .../NpgSqlTests.cs | 1 + .../SampleTests/AAA.cs | 240 +++++++++--------- .../SampleTests/DataContextExtensions.cs | 18 +- .../SampleTests/Entity2Item.cs | 16 +- .../SampleTests/IHasId.cs | 14 +- .../SampleTests/Id.cs | 2 +- .../SampleTests/IdTests.cs | 11 +- .../SampleTests/ModelBuilderExtensions.cs | 20 +- .../SampleTests/StringExtensions.cs | 31 ++- .../Models/ForMapping/ForMappingContext.cs | 2 - .../Models/Northwind.Mapping/CategoriesMap.cs | 1 - .../CustomerCustomerDemoMap.cs | 48 ++-- .../CustomerDemographicsMap.cs | 24 +- .../Models/Northwind.Mapping/CustomersMap.cs | 78 +++--- .../EmployeeTerritoriesMap.cs | 42 +-- .../Models/Northwind.Mapping/EmployeesMap.cs | 2 +- .../Northwind.Mapping/OrderDetailsMap.cs | 52 ++-- .../Models/Northwind.Mapping/OrderMap.cs | 89 ++++--- .../Models/Northwind.Mapping/ProductsMap.cs | 4 +- .../Models/Northwind.Mapping/RegionMap.cs | 26 +- .../Models/Northwind/NorthwindContext.cs | 1 - .../SQLiteTests.cs | 1 - .../ForMappingTests.cs | 2 +- .../IssueTests.cs | 10 +- .../JsonConverTests.cs | 10 +- .../Models/ForMapping/ForMappingContext.cs | 2 - .../Models/Inheritance/InheritanceContext.cs | 4 +- .../Models/IssueModel/Issue73Entity.cs | 3 +- .../Models/IssueModel/IssueContext.cs | 7 +- .../CustomerCustomerDemoMap.cs | 52 ++-- .../CustomerDemographicsMap.cs | 28 +- .../Models/Northwind.Mapping/CustomersMap.cs | 81 +++--- .../EmployeeTerritoriesMap.cs | 46 ++-- .../Models/Northwind.Mapping/EmployeesMap.cs | 2 +- .../Models/Northwind.Mapping/OrderMap.cs | 6 +- .../Models/Northwind.Mapping/ProductsMap.cs | 4 +- .../Models/Northwind.Mapping/RegionMap.cs | 30 +-- .../Northwind.Mapping/TerritoriesMap.cs | 44 ++-- .../Models/Northwind/NorthwindContext.cs | 3 +- .../QueryableExtensions.cs | 60 ++++- .../ToolsTests.cs | 128 ++-------- .../ValueConversion/ConvertorTests.cs | 4 +- .../ValueConversion/IEntity`1.cs | 1 - azure-pipelines.yml | 10 +- linq2db.EFCore.sln | 3 +- 83 files changed, 784 insertions(+), 890 deletions(-) diff --git a/.gitignore b/.gitignore index 294ef64..13d177b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,46 +1,8 @@ -#ignore thumbnails created by windows -Thumbs.db -#Ignore files build by Visual Studio -*.obj -*.pdb +#Ignore files build by IDE *.user -*.aps -*.pch -*.vspscc -*_i.c -*_p.c -*.ncb -*.suo -*.tlb -*.tlh -*.bak -*.cache -*.ilk -*.log -*.cs.ide -[Bb]in -[Dd]ebug*/ -*.lib -*.sbr +bin/ obj/ -[Rr]elease*/ _ReSharper*/ -[Tt]est[Rr]esult* -linq2db.sln.docstates -Tests/**/UserDataProviders*.* -NuGet/*.nupkg -!*.dll -!*.exe -!*.pdb -linq2db.sln.ide/graph -linq2db.sln.ide/ -!Redist/** -/packages /.vs/* -*.lock.json -/api -/linq2db.github.io -#cake -/tools -/.tools +/.tools/ /.idea/ diff --git a/Build/linq2db.Default.props b/Build/linq2db.Default.props index ff55ad8..abc983e 100644 --- a/Build/linq2db.Default.props +++ b/Build/linq2db.Default.props @@ -1,6 +1,6 @@  - 5.13.0 + 7.0.0 Svyatoslav Danyliv, Igor Tkachev, Dmitry Lukashenko, Ilya Chudin Linq to DB @@ -27,8 +27,11 @@ true true false + true true + + net6.0 diff --git a/Build/linq2db.Tests.props b/Build/linq2db.Tests.props index 30b663f..08bda71 100644 --- a/Build/linq2db.Tests.props +++ b/Build/linq2db.Tests.props @@ -2,9 +2,9 @@ - net5.0 + net7.0 - + diff --git a/Directory.Packages.props b/Directory.Packages.props index 0c9abf9..a3d3fae 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,27 +1,27 @@  - - + + - + - - + + - - + + - - - - + + + + - - + + diff --git a/NuGet/linq2db.EntityFrameworkCore.nuspec b/NuGet/linq2db.EntityFrameworkCore.nuspec index 3ecdfec..a4f62e4 100644 --- a/NuGet/linq2db.EntityFrameworkCore.nuspec +++ b/NuGet/linq2db.EntityFrameworkCore.nuspec @@ -5,7 +5,7 @@ Linq to DB (linq2db) extensions for Entity Framework Core Igor Tkachev, Ilya Chudin, Svyatoslav Danyliv, Dmitry Lukashenko Igor Tkachev, Ilya Chudin, Svyatoslav Danyliv, Dmitry Lukashenko - Copyright © 2020-2021 Igor Tkachev, Ilya Chudin, Svyatoslav Danyliv, Dmitry Lukashenko + Copyright © 2020-2022 Igor Tkachev, Ilya Chudin, Svyatoslav Danyliv, Dmitry Lukashenko Allows to execute Linq to DB (linq2db) queries in Entity Framework Core DbContext. linq linq2db LinqToDB ORM database entity-framework-core EntityFrameworkCore EFCore DB SQL SqlServer SqlCe SqlServerCe MySql Firebird SQLite Oracle ODP PostgreSQL DB2 @@ -14,8 +14,8 @@ https://github.com/linq2db/linq2db.EntityFrameworkCore MIT-LICENSE.txt - - + + diff --git a/Source/LinqToDB.EntityFrameworkCore/EFConnectionInfo.cs b/Source/LinqToDB.EntityFrameworkCore/EFConnectionInfo.cs index 97a5ad8..352223e 100644 --- a/Source/LinqToDB.EntityFrameworkCore/EFConnectionInfo.cs +++ b/Source/LinqToDB.EntityFrameworkCore/EFConnectionInfo.cs @@ -5,7 +5,7 @@ namespace LinqToDB.EntityFrameworkCore /// /// Contains database connectivity information, extracted from EF.Core. /// - public class EFConnectionInfo + public sealed class EFConnectionInfo { /// /// Gets or sets database connection instance. diff --git a/Source/LinqToDB.EntityFrameworkCore/EFCoreMetadataReader.cs b/Source/LinqToDB.EntityFrameworkCore/EFCoreMetadataReader.cs index e579092..c41ebfa 100644 --- a/Source/LinqToDB.EntityFrameworkCore/EFCoreMetadataReader.cs +++ b/Source/LinqToDB.EntityFrameworkCore/EFCoreMetadataReader.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Data; @@ -31,7 +30,7 @@ namespace LinqToDB.EntityFrameworkCore /// /// LINQ To DB metadata reader for EF.Core model. /// - internal class EFCoreMetadataReader : IMetadataReader + internal sealed class EFCoreMetadataReader : IMetadataReader { readonly IModel? _model; private readonly RelationalSqlTranslatingExpressionVisitorDependencies? _dependencies; @@ -40,8 +39,7 @@ internal class EFCoreMetadataReader : IMetadataReader private readonly ConcurrentDictionary _calculatedExtensions = new(); private readonly IDiagnosticsLogger? _logger; - public EFCoreMetadataReader( - IModel? model, IInfrastructure? accessor) + public EFCoreMetadataReader(IModel? model, IInfrastructure? accessor) { _model = model; if (accessor != null) @@ -61,7 +59,7 @@ public T[] GetAttributes(Type type, bool inherit = true) where T : Attribute if (typeof(T) == typeof(TableAttribute)) { var storeObjectId = GetStoreObjectIdentifier(et); - return new[] { (T)(Attribute)new TableAttribute(storeObjectId!.Value.Name) { Schema = storeObjectId!.Value.Schema } }; + return new[] { (T)(Attribute)new TableAttribute() { Schema = storeObjectId?.Schema, Name = storeObjectId?.Name } }; } if (typeof(T) == typeof(QueryFilterAttribute)) { @@ -208,7 +206,7 @@ public T[] GetAttributes(Type type, MemberInfo memberInfo, bool inherit = tru if (prop != null) { - var discriminator = et.GetDiscriminatorProperty(); + var discriminator = et.FindDiscriminatorProperty(); var isPrimaryKey = prop.IsPrimaryKey(); var primaryKeyOrder = 0; @@ -225,14 +223,14 @@ public T[] GetAttributes(Type type, MemberInfo memberInfo, bool inherit = tru if (_annotationProvider != null && storeObjectId != null) { if (prop.FindColumn(storeObjectId.Value) is IColumn column) - annotations = annotations.Concat(_annotationProvider.For(column)); + annotations = annotations.Concat(_annotationProvider.For(column, false)); } var isIdentity = annotations .Any(a => { if (a.Name.EndsWith(":ValueGenerationStrategy")) - return a.Value?.ToString()!.Contains("Identity") == true; + return a.Value?.ToString()?.Contains("Identity") == true; if (a.Name.EndsWith(":Autoincrement")) return a.Value is bool b && b; @@ -242,7 +240,7 @@ public T[] GetAttributes(Type type, MemberInfo memberInfo, bool inherit = tru { if (a.Value is string str) { - return str.ToLower().Contains("nextval"); + return str.ToLowerInvariant().Contains("nextval"); } } @@ -259,7 +257,8 @@ public T[] GetAttributes(Type type, MemberInfo memberInfo, bool inherit = tru } else { - dataType = SqlDataType.GetDataType(typeMapping.ClrType).Type.DataType; + var ms = _model != null ? LinqToDBForEFTools.GetMappingSchema(_model, null) : MappingSchema.Default; + dataType = ms.GetDataType(typeMapping.ClrType).Type.DataType; } } @@ -278,7 +277,7 @@ public T[] GetAttributes(Type type, MemberInfo memberInfo, bool inherit = tru { (T)(Attribute)new ColumnAttribute { - Name = prop.GetColumnName(storeObjectId!.Value), + Name = storeObjectId != null ? prop.GetColumnName(storeObjectId.Value) : null, Length = prop.GetMaxLength() ?? 0, CanBeNull = prop.IsNullable, DbType = prop.GetColumnType(), @@ -408,7 +407,7 @@ public T[] GetAttributes(Type type, MemberInfo memberInfo, bool inherit = tru return Array.Empty(); } - class ValueConverter : IValueConverter + sealed class ValueConverter : IValueConverter { public ValueConverter( LambdaExpression convertToProviderExpression, @@ -425,7 +424,7 @@ public ValueConverter( } - class SqlTransparentExpression : SqlExpression + sealed class SqlTransparentExpression : SqlExpression { public Expression Expression { get; } @@ -439,7 +438,7 @@ protected override void Print(ExpressionPrinter expressionPrinter) expressionPrinter.Print(Expression); } - protected bool Equals(SqlTransparentExpression other) + private bool Equals(SqlTransparentExpression other) { return ReferenceEquals(this, other); } @@ -596,23 +595,24 @@ string PrepareExpressionText(Expression? expr) return text; } + // https://github.com/npgsql/efcore.pg/blob/main/src/EFCore.PG/Query/Expressions/Internal/PostgresBinaryExpression.cs if (newExpression.GetType().Name == "PostgresBinaryExpression") { // Handling NpgSql's PostgresBinaryExpression - var left = newExpression.GetType().GetProperty("Left")?.GetValue(newExpression) as Expression; - var right = newExpression.GetType().GetProperty("Right")?.GetValue(newExpression) as Expression; + var left = (Expression)newExpression.GetType().GetProperty("Left")!.GetValue(newExpression)!; + var right = (Expression)newExpression.GetType().GetProperty("Right")!.GetValue(newExpression)!; - var operand = newExpression.GetType().GetProperty("OperatorType")?.GetValue(newExpression)!.ToString(); + var operand = newExpression.GetType().GetProperty("OperatorType")!.GetValue(newExpression)!.ToString()!; var operandExpr = operand switch { "Contains" - when left!.Type.Name == "NpgsqlInetTypeMapping" || + when left.Type.Name == "NpgsqlInetTypeMapping" || left.Type.Name == "NpgsqlCidrTypeMapping" => ">>", "ContainedBy" - when left!.Type.Name == "NpgsqlInetTypeMapping" || + when left.Type.Name == "NpgsqlInetTypeMapping" || left.Type.Name == "NpgsqlCidrTypeMapping" => "<<", "Contains" => "@>", @@ -674,7 +674,7 @@ private static Expression UnwrapConverted(Expression expr) if (expr is SqlFunctionExpression func) { if (string.Equals(func.Name, "COALESCE", StringComparison.InvariantCultureIgnoreCase) && - func.Arguments!.Count == 2 && func.Arguments[1].NodeType == ExpressionType.Extension) + func.Arguments?.Count == 2 && func.Arguments[1].NodeType == ExpressionType.Extension) return UnwrapConverted(func.Arguments[0]); } diff --git a/Source/LinqToDB.EntityFrameworkCore/EFProviderInfo.cs b/Source/LinqToDB.EntityFrameworkCore/EFProviderInfo.cs index ebddde5..46c82bf 100644 --- a/Source/LinqToDB.EntityFrameworkCore/EFProviderInfo.cs +++ b/Source/LinqToDB.EntityFrameworkCore/EFProviderInfo.cs @@ -8,7 +8,7 @@ namespace LinqToDB.EntityFrameworkCore /// /// Required integration information about underlying database provider, extracted from EF.Core. /// - public class EFProviderInfo + public sealed class EFProviderInfo { /// /// Gets or sets database connection instance. diff --git a/Source/LinqToDB.EntityFrameworkCore/ILinqToDBForEFTools.cs b/Source/LinqToDB.EntityFrameworkCore/ILinqToDBForEFTools.cs index 0f051df..7178e83 100644 --- a/Source/LinqToDB.EntityFrameworkCore/ILinqToDBForEFTools.cs +++ b/Source/LinqToDB.EntityFrameworkCore/ILinqToDBForEFTools.cs @@ -119,6 +119,5 @@ public interface ILinqToDBForEFTools /// Entities will be attached only if AsNoTracking() is not used in query and DbContext is configured to track entities. /// bool EnableChangeTracker { get; set; } - } } diff --git a/Source/LinqToDB.EntityFrameworkCore/Internal/LinqToDBForEFQueryProvider.cs b/Source/LinqToDB.EntityFrameworkCore/Internal/LinqToDBForEFQueryProvider.cs index c7aa7fb..a3ce653 100644 --- a/Source/LinqToDB.EntityFrameworkCore/Internal/LinqToDBForEFQueryProvider.cs +++ b/Source/LinqToDB.EntityFrameworkCore/Internal/LinqToDBForEFQueryProvider.cs @@ -108,7 +108,7 @@ TResult IAsyncQueryProvider.ExecuteAsync(Expression expression, Cancell { var item = typeof(TResult).GetGenericArguments()[0]; var method = _executeAsyncMethodInfo.MakeGenericMethod(item); - return (TResult) method.Invoke(QueryProvider, new object[] { expression, cancellationToken })!; + return (TResult)method.Invoke(QueryProvider, new object[] { expression, cancellationToken })!; } /// diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBExtensionsAdapter.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBExtensionsAdapter.cs index b835712..aa238fb 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBExtensionsAdapter.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBExtensionsAdapter.cs @@ -12,7 +12,7 @@ namespace LinqToDB.EntityFrameworkCore /// /// LINQ To DB async extensions adapter to call EF.Core functionality instead of default implementation. /// - public class LinqToDBExtensionsAdapter : IExtensionsAdapter + public sealed class LinqToDBExtensionsAdapter : IExtensionsAdapter { /// public IAsyncEnumerable AsAsyncEnumerable(IQueryable source) @@ -90,18 +90,14 @@ public Task FirstAsync( public Task FirstOrDefaultAsync( IQueryable source, CancellationToken token) -#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. => EntityFrameworkQueryableExtensions.FirstOrDefaultAsync(source, token); -#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. /// public Task FirstOrDefaultAsync( IQueryable source, Expression> predicate, CancellationToken token) -#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. => EntityFrameworkQueryableExtensions.FirstOrDefaultAsync(source, predicate, token); -#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. /// public Task SingleAsync( @@ -120,18 +116,14 @@ public Task SingleAsync( public Task SingleOrDefaultAsync( IQueryable source, CancellationToken token) -#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. => EntityFrameworkQueryableExtensions.SingleOrDefaultAsync(source, token); -#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. /// public Task SingleOrDefaultAsync( IQueryable source, Expression> predicate, CancellationToken token) -#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. => EntityFrameworkQueryableExtensions.SingleOrDefaultAsync(source, predicate, token); -#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. /// public Task ContainsAsync( diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFExtensions.Async.EF.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFExtensions.Async.EF.cs index f07a960..824b412 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFExtensions.Async.EF.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFExtensions.Async.EF.cs @@ -75,13 +75,13 @@ public static Task FirstAsyncEF( => EntityFrameworkQueryableExtensions.FirstAsync(source, predicate, cancellationToken); /// - public static Task FirstOrDefaultAsyncEF( + public static Task FirstOrDefaultAsyncEF( this IQueryable source, CancellationToken cancellationToken = default) => EntityFrameworkQueryableExtensions.FirstOrDefaultAsync(source, cancellationToken); /// - public static Task FirstOrDefaultAsyncEF( + public static Task FirstOrDefaultAsyncEF( this IQueryable source, Expression> predicate, CancellationToken cancellationToken = default) @@ -101,13 +101,13 @@ public static Task SingleAsyncEF( => EntityFrameworkQueryableExtensions.SingleAsync(source, predicate, cancellationToken); /// - public static Task SingleOrDefaultAsyncEF( + public static Task SingleOrDefaultAsyncEF( this IQueryable source, CancellationToken cancellationToken = default) => EntityFrameworkQueryableExtensions.SingleOrDefaultAsync(source, cancellationToken); /// - public static Task SingleOrDefaultAsyncEF( + public static Task SingleOrDefaultAsyncEF( this IQueryable source, Expression> predicate, CancellationToken cancellationToken = default) diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.Mapping.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.Mapping.cs index 672929f..29f4465 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.Mapping.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.Mapping.cs @@ -12,7 +12,6 @@ namespace LinqToDB.EntityFrameworkCore public partial class LinqToDBForEFTools { - static void InitializeMapping() { Linq.Expressions.MapMember( @@ -59,7 +58,7 @@ static void InitializeSqlServerMapping() var dateDiffStr = "DateDiff"; var dateDiffMethods = sqlServerMethods.Where(m => m.Name.StartsWith(dateDiffStr)).ToArray(); - var dateDiffMethod = MemberHelper.MethodOf(() => Sql.DateDiff(Sql.DateParts.Day, null, null)); + var dateDiffMethod = MemberHelper.MethodOf(() => Sql.DateDiff(Sql.DateParts.Day, (DateTime?)null, null)); foreach (var method in dateDiffMethods) { diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.cs index 42c8560..0df9213 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.cs @@ -25,6 +25,7 @@ namespace LinqToDB.EntityFrameworkCore using Expressions; using Internal; + using System.Diagnostics.CodeAnalysis; /// /// EF Core extensions to call LINQ To DB functionality. @@ -65,7 +66,7 @@ static bool InitializeInternal() var newExpression = queryable.Expression; var result = (IQueryable)instantiator.MakeGenericMethod(queryable.ElementType) - .Invoke(null, new object[] { dc, newExpression }); + .Invoke(null, new object[] { dc, newExpression })!; if (prev != null) result = prev(result); @@ -78,7 +79,7 @@ static bool InitializeInternal() return true; } - static ILinqToDBForEFTools _implementation = null!; + static ILinqToDBForEFTools _implementation; /// /// Gets or sets EF Core to LINQ To DB integration bridge implementation. @@ -86,6 +87,7 @@ static bool InitializeInternal() public static ILinqToDBForEFTools Implementation { get => _implementation; + [MemberNotNull(nameof(_implementation), nameof(_defaultMetadataReader))] set { _implementation = value ?? throw new ArgumentNullException(nameof(value)); @@ -96,7 +98,7 @@ public static ILinqToDBForEFTools Implementation static readonly ConcurrentDictionary _metadataReaders = new(); - static Lazy _defaultMetadataReader = null!; + static Lazy _defaultMetadataReader; /// /// Clears internal caches diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataConnection.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataConnection.cs index fed8bf5..e56171f 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataConnection.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataConnection.cs @@ -131,7 +131,7 @@ public Expression ProcessExpression(Expression expression) return _transformFunc(expression, this, Context, _model); } - private class TypeKey + private sealed class TypeKey { public TypeKey(IEntityType entityType, IModel? model) { @@ -142,7 +142,7 @@ public TypeKey(IEntityType entityType, IModel? model) public IEntityType EntityType { get; } public IModel? Model { get; } - protected bool Equals(TypeKey other) + private bool Equals(TypeKey other) { return EntityType.Equals(other.EntityType) && Equals(Model, other.Model); } @@ -205,9 +205,7 @@ object IEntityServiceInterceptor.EntityCreated(EntityCreatedEventData eventData, if (eventData.TableName != _lastEntityType.GetTableName()) return entity; - if (_stateManager == null) - _stateManager = Context.GetService(); - + _stateManager ??= Context.GetService(); // It is a real pain to register entity in change tracker // @@ -226,10 +224,7 @@ object IEntityServiceInterceptor.EntityCreated(EntityCreatedEventData eventData, entry = retrievalFunc(_stateManager, entity); - if (entry == null) - { - entry = _stateManager.StartTrackingFromQuery(_lastEntityType, entity, ValueBuffer.Empty); - } + entry ??= _stateManager.StartTrackingFromQuery(_lastEntityType, entity, ValueBuffer.Empty); return entry.Entity; } diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataContext.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataContext.cs index 2ceea07..54f08ca 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataContext.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsDataContext.cs @@ -50,6 +50,5 @@ public Expression ProcessExpression(Expression expression) return expression; return _transformFunc(expression, this, _context, _model); } - } } diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsException.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsException.cs index e0c4efa..5e6866a 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsException.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsException.cs @@ -5,7 +5,7 @@ namespace LinqToDB.EntityFrameworkCore /// /// Exception class for EF.Core to LINQ To DB integration issues. /// - public class LinqToDBForEFToolsException : Exception + public sealed class LinqToDBForEFToolsException : Exception { /// /// Creates new instance of exception. diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs index 1d47fbf..b469ab7 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs @@ -46,7 +46,7 @@ namespace LinqToDB.EntityFrameworkCore [PublicAPI] public class LinqToDBForEFToolsImplDefault : ILinqToDBForEFTools { - class ProviderKey + sealed class ProviderKey { public ProviderKey(string? providerName, string? connectionString) { @@ -59,7 +59,7 @@ public ProviderKey(string? providerName, string? connectionString) #region Equality members - protected bool Equals(ProviderKey other) + private bool Equals(ProviderKey other) { return string.Equals(ProviderName, other.ProviderName) && string.Equals(ConnectionString, other.ConnectionString); } @@ -163,31 +163,44 @@ protected virtual IDataProvider CreateLinqToDbDataProvider(EFProviderInfo provid switch (provInfo.ProviderName) { - case ProviderName.SqlServer: - return CreateSqlServerProvider(SqlServerDefaultVersion, connectionInfo.ConnectionString); - case ProviderName.MySql: - case ProviderName.MySqlConnector: - return MySqlTools.GetDataProvider(provInfo.ProviderName); - case ProviderName.PostgreSQL: - return CreatePostgreSqlProvider(PostgreSqlDefaultVersion, connectionInfo.ConnectionString); - case ProviderName.SQLite: - return SQLiteTools.GetDataProvider(provInfo.ProviderName); - case ProviderName.Firebird: - return FirebirdTools.GetDataProvider(); - case ProviderName.DB2: - case ProviderName.DB2LUW: - return DB2Tools.GetDataProvider(DB2Version.LUW); - case ProviderName.DB2zOS: + case ProviderName.SqlServer: + return CreateSqlServerProvider(SqlServerDefaultVersion, connectionInfo.ConnectionString); + case ProviderName.MySql: + case ProviderName.MySqlConnector: + return MySqlTools.GetDataProvider(provInfo.ProviderName); + case ProviderName.PostgreSQL: + return CreatePostgreSqlProvider(PostgreSqlDefaultVersion, connectionInfo.ConnectionString); + case ProviderName.SQLite: + return SQLiteTools.GetDataProvider(provInfo.ProviderName); + case ProviderName.Firebird: + return FirebirdTools.GetDataProvider(); + case ProviderName.DB2: + case ProviderName.DB2LUW: + return DB2Tools.GetDataProvider(DB2Version.LUW); + case ProviderName.DB2zOS: return DB2Tools.GetDataProvider(DB2Version.zOS); - case ProviderName.Oracle: - return OracleTools.GetDataProvider(provInfo.ProviderName, version: OracleVersion.v11); - case ProviderName.SqlCe: - return SqlCeTools.GetDataProvider(); - //case ProviderName.Access: - // return new AccessDataProvider(); - - default: - throw new LinqToDBForEFToolsException($"Can not instantiate data provider '{provInfo.ProviderName}'."); + + case ProviderName.Oracle11Native: + return OracleTools.GetDataProvider(OracleVersion.v11, OracleProvider.Native); + case ProviderName.OracleNative: + return OracleTools.GetDataProvider(OracleVersion.v12, OracleProvider.Native); + case ProviderName.Oracle11Managed: + return OracleTools.GetDataProvider(OracleVersion.v11, OracleProvider.Managed); + case ProviderName.Oracle: + case ProviderName.OracleManaged: + return OracleTools.GetDataProvider(OracleVersion.v12, OracleProvider.Managed); + case ProviderName.Oracle11Devart: + return OracleTools.GetDataProvider(OracleVersion.v11, OracleProvider.Devart); + case ProviderName.OracleDevart: + return OracleTools.GetDataProvider( OracleVersion.v12, OracleProvider.Devart); + + case ProviderName.SqlCe: + return SqlCeTools.GetDataProvider(); + //case ProviderName.Access: + // return new AccessDataProvider(); + + default: + throw new LinqToDBForEFToolsException($"Can not instantiate data provider '{provInfo.ProviderName}'."); } } @@ -323,9 +336,6 @@ protected virtual IDataProvider CreateLinqToDbDataProvider(EFProviderInfo provid /// linq2db SQL Server provider instance. protected virtual IDataProvider CreateSqlServerProvider(SqlServerVersion version, string? connectionString) { - if (!string.IsNullOrEmpty(connectionString)) - return DataConnection.GetDataProvider("Microsoft.Data.SqlClient", connectionString)!; - return DataProvider.SqlServer.SqlServerTools.GetDataProvider(version, SqlServerProvider.MicrosoftDataSqlClient); } @@ -337,9 +347,6 @@ protected virtual IDataProvider CreateSqlServerProvider(SqlServerVersion version /// linq2db PostgreSQL provider instance. protected virtual IDataProvider CreatePostgreSqlProvider(PostgreSQLVersion version, string? connectionString) { - if (!string.IsNullOrEmpty(connectionString)) - return DataConnection.GetDataProvider(ProviderName.PostgreSQL, connectionString)!; - return PostgreSQLTools.GetDataProvider(version); } @@ -493,7 +500,7 @@ public virtual MappingSchema GetMappingSchema( { e.SlidingExpiration = TimeSpan.FromHours(1); return CreateMappingSchema(model, metadataReader, convertorSelector); - }); + })!; return result; } @@ -515,36 +522,27 @@ public virtual MappingSchema GetMappingSchema( static readonly MethodInfo IncludeMethodInfoString = MemberHelper.MethodOfGeneric>(q => q.Include(string.Empty)); static readonly MethodInfo ThenIncludeMethodInfo = - MemberHelper.MethodOfGeneric>(q => q.ThenInclude(null)); + MemberHelper.MethodOfGeneric>(q => q.ThenInclude(null!)); static readonly MethodInfo TagWithMethodInfo = MemberHelper.MethodOfGeneric>(q => q.TagWith(string.Empty)); static readonly MethodInfo ThenIncludeEnumerableMethodInfo = - MemberHelper.MethodOfGeneric>>(q => q.ThenInclude(null)); + MemberHelper.MethodOfGeneric>>(q => q.ThenInclude(null!)); static readonly MethodInfo AsNoTrackingMethodInfo = MemberHelper.MethodOfGeneric>(q => q.AsNoTracking()); static readonly MethodInfo EFProperty = MemberHelper.MethodOfGeneric(() => EF.Property(1, "")); - static readonly MethodInfo - L2DBProperty = typeof(Sql).GetMethod(nameof(Sql.Property)).GetGenericMethodDefinition(); - static readonly MethodInfo L2DBFromSqlMethodInfo = MemberHelper.MethodOfGeneric(dc => dc.FromSql(new Common.RawSqlString())); - static readonly MethodInfo L2DBRemoveOrderByMethodInfo = - MemberHelper.MethodOfGeneric>(q => q.RemoveOrderBy()); - static readonly ConstructorInfo RawSqlStringConstructor = MemberHelper.ConstructorOf(() => new Common.RawSqlString("")); static readonly ConstructorInfo DataParameterConstructor = MemberHelper.ConstructorOf(() => new DataParameter("", "", DataType.Undefined, "")); static readonly MethodInfo ToSql = MemberHelper.MethodOfGeneric(() => Sql.ToSql(1)); - static readonly MethodInfo TagQueryMethodInfo = - MemberHelper.MethodOfGeneric>(q => q.TagQuery(string.Empty)); - /// /// Removes conversions from expression. /// @@ -842,7 +840,7 @@ TransformInfo LocalTransform(Expression e) return new TransformInfo(Expression.Call(method, methodCall.Arguments.Select(a => a.Transform(l => LocalTransform(l))) .ToArray()), false, true); } - else if (generic == L2DBRemoveOrderByMethodInfo) + else if (generic == Methods.LinqToDB.RemoveOrderBy) { // This is workaround. EagerLoading runs query again with RemoveOrderBy method. // it is only one possible way now how to detect nested query. @@ -850,8 +848,7 @@ TransformInfo LocalTransform(Expression e) } else if (generic == TagWithMethodInfo) { - var method = - TagQueryMethodInfo.MakeGenericMethod(methodCall.Method.GetGenericArguments()); + var method = Methods.LinqToDB.TagQuery.MakeGenericMethod(methodCall.Method.GetGenericArguments()); return new TransformInfo(Expression.Call(method, methodCall.Arguments.Select(a => a.Transform(l => LocalTransform(l))) .ToArray()), false, true); @@ -893,7 +890,7 @@ TransformInfo LocalTransform(Expression e) if (generic == EFProperty) { - var prop = Expression.Call(null, L2DBProperty.MakeGenericMethod(methodCall.Method.GetGenericArguments()[0]), + var prop = Expression.Call(null, Methods.LinqToDB.SqlExt.Property.MakeGenericMethod(methodCall.Method.GetGenericArguments()[0]), methodCall.Arguments[0], methodCall.Arguments[1]); return new TransformInfo(prop, false, true); } @@ -919,16 +916,13 @@ TransformInfo LocalTransform(Expression e) .FirstOrDefault(); if (notParametrized != null) { - if (newArguments == null) - { - newArguments = new List(methodCall.Arguments.Take(i)); - } + newArguments ??= new List(methodCall.Arguments.Take(i)); newArguments.Add(Expression.Call(ToSql.MakeGenericMethod(arg.Type), arg)); continue; } - } - + } + newArguments?.Add(methodCall.Arguments[i]); } @@ -949,13 +943,12 @@ TransformInfo LocalTransform(Expression e) Expression.New(RawSqlStringConstructor, Expression.Constant(fromSqlQueryRoot.Sql)), fromSqlQueryRoot.Argument)); } - else if (dc != null && e is QueryRootExpression queryRoot) + else if (dc != null && e is EntityQueryRootExpression queryRoot) { var newExpr = Expression.Call(null, Methods.LinqToDB.GetTable.MakeGenericMethod(queryRoot.EntityType.ClrType), Expression.Constant(dc)); return new TransformInfo(newExpr); } - break; } @@ -964,7 +957,7 @@ TransformInfo LocalTransform(Expression e) return new TransformInfo(e); } - var newExpression = expression.Transform(e => LocalTransform(e)); + var newExpression = expression.Transform(LocalTransform); if (!ignoreTracking && dc is LinqToDBForEFToolsDataConnection dataConnection) { @@ -997,7 +990,7 @@ static Type GetEnumerableElementType(Type type, MappingSchema mappingSchema) if (!IsEnumerableType(type, mappingSchema)) return type; if (type.IsArray) - return type.GetElementType(); + return type.GetElementType()!; if (typeof(IGrouping<,>).IsSameOrParentOf(type)) return type.GetGenericArguments()[1]; return type.GetGenericArguments()[0]; @@ -1020,8 +1013,8 @@ static bool IsEnumerableType(Type type, MappingSchema mappingSchema) /// Current instance. public virtual DbContext? GetCurrentContext(IQueryable query) { - var compilerField = typeof (EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); - var compiler = (QueryCompiler) compilerField.GetValue(query.Provider); + var compilerField = typeof (EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance)!; + var compiler = (QueryCompiler)compilerField.GetValue(query.Provider)!; var queryContextFactoryField = compiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); @@ -1031,12 +1024,12 @@ static bool IsEnumerableType(Type type, MappingSchema mappingSchema) if (queryContextFactoryField.GetValue(compiler) is not RelationalQueryContextFactory queryContextFactory) throw new LinqToDBForEFToolsException("LinqToDB Tools for EFCore support only Relational Databases."); - var dependenciesProperty = typeof(RelationalQueryContextFactory).GetField("_dependencies", BindingFlags.NonPublic | BindingFlags.Instance); + var dependenciesProperty = typeof(RelationalQueryContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); if (dependenciesProperty == null) - throw new LinqToDBForEFToolsException($"Can not find private property '{nameof(RelationalQueryContextFactory)}._dependencies' in current EFCore Version."); + throw new LinqToDBForEFToolsException($"Can not find protected property '{nameof(RelationalQueryContextFactory)}.Dependencies' in current EFCore Version."); - var dependencies = (QueryContextDependencies) dependenciesProperty.GetValue(queryContextFactory); + var dependencies = (QueryContextDependencies)dependenciesProperty.GetValue(queryContextFactory)!; return dependencies.CurrentContext?.Context; } @@ -1074,7 +1067,6 @@ public virtual EFConnectionInfo ExtractConnectionInfo(IDbContextOptions? options /// Logger instance. public virtual void LogConnectionTrace(TraceInfo info, ILogger logger) { -#pragma warning disable CA1848 // Use the LoggerMessage delegates var logLevel = info.TraceLevel switch { TraceLevel.Off => LogLevel.None, @@ -1085,6 +1077,7 @@ public virtual void LogConnectionTrace(TraceInfo info, ILogger logger) _ => LogLevel.Trace, }; +#pragma warning disable CA1848 // Use the LoggerMessage delegates using var _ = logger.BeginScope("TraceInfoStep: {TraceInfoStep}, IsAsync: {IsAsync}", info.TraceInfoStep, info.IsAsync); switch (info.TraceInfoStep) diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBProviderInfo.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBProviderInfo.cs index f3711c7..744171b 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBProviderInfo.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBProviderInfo.cs @@ -3,7 +3,7 @@ /// /// Stores LINQ To DB database provider information. /// - public class LinqToDBProviderInfo + public sealed class LinqToDBProviderInfo { /// /// Server version. Currently is not used. diff --git a/Source/LinqToDB.EntityFrameworkCore/Properties/JetBrains.Annotations.cs b/Source/LinqToDB.EntityFrameworkCore/Properties/JetBrains.Annotations.cs index 578e991..3f59131 100644 --- a/Source/LinqToDB.EntityFrameworkCore/Properties/JetBrains.Annotations.cs +++ b/Source/LinqToDB.EntityFrameworkCore/Properties/JetBrains.Annotations.cs @@ -1,6 +1,5 @@ using System; -#pragma warning disable 1591 // ReSharper disable UnusedMember.Global // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global diff --git a/Source/LinqToDB.EntityFrameworkCore/linq2db.EntityFrameworkCore.csproj b/Source/LinqToDB.EntityFrameworkCore/linq2db.EntityFrameworkCore.csproj index 87178fc..798e898 100644 --- a/Source/LinqToDB.EntityFrameworkCore/linq2db.EntityFrameworkCore.csproj +++ b/Source/LinqToDB.EntityFrameworkCore/linq2db.EntityFrameworkCore.csproj @@ -7,7 +7,6 @@ Linq to DB (linq2db) extensions for Entity Framework Core $(Title) - netstandard2.1 LinqToDB.EntityFrameworkCore bin\$(Configuration)\$(TargetFramework)\linq2db.EntityFrameworkCore.xml diff --git a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/ForMappingTestsBase.cs b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/ForMappingTestsBase.cs index b66fca8..a3700d8 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/ForMappingTestsBase.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/ForMappingTestsBase.cs @@ -109,12 +109,12 @@ public virtual async Task TestUIntTable() } [Test] - public virtual async Task TestAmbiguousProperties() + public virtual void TestAmbiguousProperties() { using var context = CreateContext(); - await FluentActions.Awaiting(() => context.WithDuplicateProperties.Where(x => x.Value == 1) - .ToArrayAsyncLinqToDB()).Should().NotThrowAsync(); + FluentActions.Invoking(() => context.WithDuplicateProperties.Where(x => x.Value == 1) + .ToArray()).Should().NotThrow(); } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/NullExternalScopeProvider.cs b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/NullExternalScopeProvider.cs index 1fab1df..a31a7ca 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/NullExternalScopeProvider.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/NullExternalScopeProvider.cs @@ -6,7 +6,7 @@ namespace LinqToDB.EntityFrameworkCore.BaseTests.Logging /// /// Scope provider that does nothing. /// - internal class NullExternalScopeProvider : IExternalScopeProvider + internal sealed class NullExternalScopeProvider : IExternalScopeProvider { private NullExternalScopeProvider() { @@ -18,12 +18,12 @@ private NullExternalScopeProvider() public static IExternalScopeProvider Instance { get; } = new NullExternalScopeProvider(); /// - void IExternalScopeProvider.ForEachScope(Action callback, TState state) + void IExternalScopeProvider.ForEachScope(Action callback, TState state) { } /// - IDisposable IExternalScopeProvider.Push(object state) + IDisposable IExternalScopeProvider.Push(object? state) { return NullScope.Instance; } diff --git a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/NullScope.cs b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/NullScope.cs index e2f3fb3..f77c41a 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/NullScope.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/NullScope.cs @@ -2,7 +2,7 @@ namespace LinqToDB.EntityFrameworkCore.BaseTests.Logging { - internal class NullScope : IDisposable + internal sealed class NullScope : IDisposable { public static NullScope Instance { get; } = new NullScope(); diff --git a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLogger.cs b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLogger.cs index 39a8f48..adc4a33 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLogger.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLogger.cs @@ -6,16 +6,13 @@ namespace LinqToDB.EntityFrameworkCore.BaseTests.Logging { - internal class TestLogger : ILogger + internal sealed class TestLogger : ILogger { private static readonly string _loglevelPadding = ": "; private static readonly string _messagePadding; private static readonly string _newLineWithMessagePadding; - // ConsoleColor does not have a value to specify the 'Default' color -#pragma warning disable 649 - private readonly ConsoleColor? DefaultConsoleColor; -#pragma warning restore 649 + private readonly ConsoleColor DefaultConsoleColor = ConsoleColor.Black; private readonly string _name; @@ -38,7 +35,7 @@ internal TestLogger(string name) internal ConsoleLoggerOptions? Options { get; set; } - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { if (!IsEnabled(logLevel)) { @@ -58,18 +55,15 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except } } - public virtual void WriteMessage(LogLevel logLevel, string logName, int eventId, string message, Exception exception) + public void WriteMessage(LogLevel logLevel, string logName, int eventId, string message, Exception? exception) { - var format = Options!.FormatterName; + var format = Options?.FormatterName; Debug.Assert(format is ConsoleFormatterNames.Simple or ConsoleFormatterNames.Systemd); var logBuilder = _logBuilder; _logBuilder = null; - if (logBuilder == null) - { - logBuilder = new StringBuilder(); - } + logBuilder ??= new StringBuilder(); LogMessageEntry entry; if (format == ConsoleFormatterNames.Simple) @@ -99,7 +93,7 @@ private void EnqueueMessage(LogMessageEntry entry) WriteMessage(entry); } - internal virtual void WriteMessage(LogMessageEntry message) + internal void WriteMessage(LogMessageEntry message) { if (message.TimeStamp != null) { @@ -114,7 +108,7 @@ internal virtual void WriteMessage(LogMessageEntry message) Console.WriteLine(message.Message); } - private LogMessageEntry CreateDefaultLogMessage(StringBuilder logBuilder, LogLevel logLevel, string logName, int eventId, string message, Exception exception) + private LogMessageEntry CreateDefaultLogMessage(StringBuilder logBuilder, LogLevel logLevel, string logName, int eventId, string message, Exception? exception) { // Example: // INFO: ConsoleApp.Program[10] @@ -152,7 +146,7 @@ private LogMessageEntry CreateDefaultLogMessage(StringBuilder logBuilder, LogLev } #pragma warning disable CS0618 // Type or member is obsolete - var timestampFormat = Options!.TimestampFormat; + var timestampFormat = Options?.TimestampFormat; #pragma warning restore CS0618 // Type or member is obsolete return new LogMessageEntry( @@ -162,11 +156,11 @@ private LogMessageEntry CreateDefaultLogMessage(StringBuilder logBuilder, LogLev levelBackground: logLevelColors.Background, levelForeground: logLevelColors.Foreground, messageColor: DefaultConsoleColor, - logAsError: logLevel >= Options!.LogToStandardErrorThreshold + logAsError: logLevel >= Options?.LogToStandardErrorThreshold ); } - private LogMessageEntry CreateSystemdLogMessage(StringBuilder logBuilder, LogLevel logLevel, string logName, int eventId, string message, Exception exception) + private LogMessageEntry CreateSystemdLogMessage(StringBuilder logBuilder, LogLevel logLevel, string logName, int eventId, string message, Exception? exception) { // systemd reads messages from standard out line-by-line in a 'message' format. // newline characters are treated as message delimiters, so we must replace them. @@ -180,7 +174,7 @@ private LogMessageEntry CreateSystemdLogMessage(StringBuilder logBuilder, LogLev // timestamp #pragma warning disable CS0618 // Type or member is obsolete - var timestampFormat = Options!.TimestampFormat; + var timestampFormat = Options?.TimestampFormat; #pragma warning restore CS0618 // Type or member is obsolete if (timestampFormat != null) { @@ -217,7 +211,7 @@ private LogMessageEntry CreateSystemdLogMessage(StringBuilder logBuilder, LogLev return new LogMessageEntry( message: logBuilder.ToString(), - logAsError: logLevel >= Options.LogToStandardErrorThreshold + logAsError: logLevel >= Options?.LogToStandardErrorThreshold ); static void AppendAndReplaceNewLine(StringBuilder sb, string message) @@ -233,7 +227,9 @@ public bool IsEnabled(LogLevel logLevel) return logLevel != LogLevel.None; } - public IDisposable BeginScope(TState state) => ScopeProvider?.Push(state) ?? NullScope.Instance; + public IDisposable BeginScope(TState state) + where TState : notnull + => ScopeProvider?.Push(state) ?? NullScope.Instance; private static string GetLogLevelString(LogLevel logLevel) { @@ -280,7 +276,7 @@ private static string GetSyslogSeverityString(LogLevel logLevel) private ConsoleColors GetLogLevelConsoleColors(LogLevel logLevel) { #pragma warning disable CS0618 // Type or member is obsolete - if (Options!.DisableColors) + if (Options?.DisableColors == true) #pragma warning restore CS0618 // Type or member is obsolete { return new ConsoleColors(null, null); @@ -311,7 +307,7 @@ private void GetScopeInformation(StringBuilder stringBuilder, bool multiLine) { var scopeProvider = ScopeProvider; #pragma warning disable CS0618 // Type or member is obsolete - if (Options!.IncludeScopes && scopeProvider != null) + if (Options?.IncludeScopes == true && scopeProvider != null) #pragma warning restore CS0618 // Type or member is obsolete { var initialLength = stringBuilder.Length; @@ -352,5 +348,4 @@ public ConsoleColors(ConsoleColor? foreground, ConsoleColor? background) public ConsoleColor? Background { get; } } } - } diff --git a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLoggerProvider.cs b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLoggerProvider.cs index ce4bc2f..9266a37 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLoggerProvider.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLoggerProvider.cs @@ -15,7 +15,7 @@ public class TestLoggerProvider : ILoggerProvider, ISupportExternalScope private readonly IOptionsMonitor _options; private readonly ConcurrentDictionary _loggers; - private readonly IDisposable _optionsReloadToken; + private readonly IDisposable? _optionsReloadToken; private IExternalScopeProvider _scopeProvider = NullExternalScopeProvider.Instance; /// diff --git a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Models/Northwind/NorthwindData.cs b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Models/Northwind/NorthwindData.cs index 3464243..ebb7e20 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Models/Northwind/NorthwindData.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Models/Northwind/NorthwindData.cs @@ -130,7 +130,7 @@ private static void AddEntities(DbContext context) { context.Set().AddRange(CreateCustomers()); - var titleProperty = context.Model.FindEntityType(typeof(Employee)).FindProperty("Title"); + var titleProperty = context.Model.FindEntityType(typeof(Employee))!.FindProperty("Title")!; foreach (var employee in CreateEmployees()) { context.Set().Add(employee); @@ -147,7 +147,7 @@ private static void AddEntities(DbContext context) context.Set().AddRange(CreateOrderDetails()); } - private class AsyncEnumerable : IAsyncQueryProvider, IOrderedQueryable + private sealed class AsyncEnumerable : IAsyncQueryProvider, IOrderedQueryable { private readonly EnumerableQuery _enumerableQuery; @@ -178,7 +178,7 @@ public TResult Execute(Expression expression) private static Expression RewriteShadowPropertyAccess(Expression expression) => new ShadowStateAccessRewriter().Visit(expression); - private class ShadowStateAccessRewriter : ExpressionVisitor + private sealed class ShadowStateAccessRewriter : ExpressionVisitor { [return: NotNullIfNotNull("expr")] static Expression? RemoveConvert(Expression? expr) diff --git a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/ForMappingTests.cs b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/ForMappingTests.cs index d1b8e17..edf73f5 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/ForMappingTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/ForMappingTests.cs @@ -12,9 +12,9 @@ public class ForMappingTests : ForMappingTestsBase public override ForMappingContextBase CreateContext() { var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseMySql( - "Server=DBHost;Port=3306;Database=TestData;Uid=TestUser;Pwd=TestPassword;charset=utf8;", - ServerVersion.AutoDetect("Server=DBHost;Port=3306;Database=TestData;Uid=TestUser;Pwd=TestPassword;charset=utf8;")); + var connectionString = "Server=DBHost;Port=3306;Database=TestData;Uid=TestUser;Pwd=TestPassword;charset=utf8;"; + //var connectionString = "Server=localhost;Port=3316;Database=TestData;Uid=root;Pwd=root;charset=utf8;"; + optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); optionsBuilder.UseLoggerFactory(TestUtils.LoggerFactory); var options = optionsBuilder.Options; diff --git a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests.csproj b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests.csproj index b3af97d..a21057d 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests.csproj +++ b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests.csproj @@ -3,13 +3,17 @@ - - - + + + + + + NU1107;NU1608 + diff --git a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/EmployeesMap.cs b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/EmployeesMap.cs index ef549e9..d4d2860 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/EmployeesMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/EmployeesMap.cs @@ -56,7 +56,7 @@ public void Configure(EntityTypeBuilder builder) builder.Property(e => e.TitleOfCourtesy).HasMaxLength(25); builder.HasOne(d => d.ReportsToNavigation) - .WithMany(p => p!.InverseReportsToNavigation) + .WithMany(p => p.InverseReportsToNavigation) .HasForeignKey(d => d.ReportsTo) .HasConstraintName("FK_Employees_Employees"); } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/OrderMap.cs b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/OrderMap.cs index df8ff76..21af69d 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/OrderMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/OrderMap.cs @@ -61,17 +61,17 @@ public void Configure(EntityTypeBuilder builder) builder.Property(e => e.ShippedDate).HasColumnType("datetime"); builder.HasOne(d => d.Customer) - .WithMany(p => p!.Orders) + .WithMany(p => p.Orders) .HasForeignKey(d => d.CustomerId) .HasConstraintName("FK_Orders_Customers"); builder.HasOne(d => d.Employee) - .WithMany(p => p!.Orders) + .WithMany(p => p.Orders) .HasForeignKey(d => d.EmployeeId) .HasConstraintName("FK_Orders_Employees"); builder.HasOne(d => d.ShipViaNavigation) - .WithMany(p => p!.Orders) + .WithMany(p => p.Orders) .HasForeignKey(d => d.ShipVia) .HasConstraintName("FK_Orders_Shippers"); } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/ProductsMap.cs b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/ProductsMap.cs index de296a8..b6ad934 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/ProductsMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/Models/Northwind.Mapping/ProductsMap.cs @@ -43,12 +43,12 @@ public void Configure(EntityTypeBuilder builder) builder.Property(e => e.UnitsOnOrder).HasDefaultValue((short)0); builder.HasOne(d => d.Category) - .WithMany(p => p!.Products) + .WithMany(p => p.Products) .HasForeignKey(d => d.CategoryId) .HasConstraintName("FK_Products_Categories"); builder.HasOne(d => d.Supplier) - .WithMany(p => p!.Products) + .WithMany(p => p.Products) .HasForeignKey(d => d.SupplierId) .HasConstraintName("FK_Products_Suppliers"); } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/PomeloMySqlTests.cs b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/PomeloMySqlTests.cs index bf3600b..e9d1b5f 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/PomeloMySqlTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PomeloMySql.Tests/PomeloMySqlTests.cs @@ -22,9 +22,9 @@ public PomeloMySqlTests() var optionsBuilder = new DbContextOptionsBuilder(); //new SqlServerDbContextOptionsBuilder(optionsBuilder); - optionsBuilder.UseMySql( - "Server=DBHost;Port=3306;Database=TestData;Uid=TestUser;Pwd=TestPassword;charset=utf8;", - ServerVersion.AutoDetect("Server=DBHost;Port=3306;Database=TestData;Uid=TestUser;Pwd=TestPassword;charset=utf8;")); + var connectionString = "Server=DBHost;Port=3306;Database=TestData;Uid=TestUser;Pwd=TestPassword;charset=utf8;"; + //var connectionString = "Server=localhost;Port=3316;Database=TestData;Uid=root;Pwd=root;charset=utf8;"; + optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); optionsBuilder.UseLoggerFactory(TestUtils.LoggerFactory); diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/ForMappingTests.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/ForMappingTests.cs index 948843b..f338d51 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/ForMappingTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/ForMappingTests.cs @@ -15,6 +15,7 @@ public override ForMappingContextBase CreateContext() { var optionsBuilder = new DbContextOptionsBuilder(); optionsBuilder.UseNpgsql("Server=DBHost;Port=5432;Database=ForMapping;User Id=postgres;Password=TestPassword;Pooling=true;MinPoolSize=10;MaxPoolSize=100;"); + //optionsBuilder.UseNpgsql("Server=localhost;Port=5415;Database=ForMapping;User Id=postgres;Password=Password12!;Pooling=true;MinPoolSize=10;MaxPoolSize=100;"); optionsBuilder.UseLoggerFactory(TestUtils.LoggerFactory); var options = optionsBuilder.Options; diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/ForMapping/ForMappingContext.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/ForMapping/ForMappingContext.cs index 4d1b487..266e70b 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/ForMapping/ForMappingContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/ForMapping/ForMappingContext.cs @@ -5,10 +5,8 @@ namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.Models.ForMapping { public class ForMappingContext : ForMappingContextBase { - public ForMappingContext(DbContextOptions options) : base(options) { - } protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/EntityWithXmin.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/EntityWithXmin.cs index 6a70a51..8d243f3 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/EntityWithXmin.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/EntityWithXmin.cs @@ -1,5 +1,4 @@ -using System; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.Models.NpgSqlEntities { diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/Event.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/Event.cs index f448e23..77e28a5 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/Event.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/Event.cs @@ -5,8 +5,8 @@ namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.Models.NpgSqlEntities { public class Event { - public int Id { get; set; } - public string Name { get; set; } = null!; + public int Id { get; set; } + public string Name { get; set; } = null!; public NpgsqlRange Duration { get; set; } } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/NpgSqlEnititesContext.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/NpgSqlEnititesContext.cs index d221559..83c3897 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/NpgSqlEnititesContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/NpgSqlEnititesContext.cs @@ -27,7 +27,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(entity => { - entity.UseXminAsConcurrencyToken(); + entity.Property(nameof(NpgSqlEntities.EntityWithXmin.xmin)).IsRowVersion(); }); } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/NpgSqlTests.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/NpgSqlTests.cs index 12239a6..6524e09 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/NpgSqlTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/NpgSqlTests.cs @@ -26,6 +26,7 @@ public NpgSqlTests() //new SqlServerDbContextOptionsBuilder(optionsBuilder); optionsBuilder.UseNpgsql("Server=DBHost;Port=5432;Database=TestData;User Id=postgres;Password=TestPassword;Pooling=true;MinPoolSize=10;MaxPoolSize=100;"); + //optionsBuilder.UseNpgsql("Server=localhost;Port=5415;Database=TestData;User Id=postgres;Password=Password12!;Pooling=true;MinPoolSize=10;MaxPoolSize=100;"); optionsBuilder.UseLoggerFactory(TestUtils.LoggerFactory); _options = optionsBuilder.Options; diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/AAA.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/AAA.cs index b840517..12db9ba 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/AAA.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/AAA.cs @@ -1,123 +1,119 @@ -using System; -using System.Threading.Tasks; - -#pragma warning disable 8604 -#pragma warning disable CS8625 - -namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.SampleTests -{ - public class Unit - { - - } - - public static class ExceptionExtensions - { - public static Unit Throw(this Exception e) => throw e; - } - - public static class AAA - { - public static ArrangeResult Arrange(this T @object, Action action) - { - action(@object); - return new ArrangeResult(@object, default); - } - - public static ArrangeResult Arrange(T @object) - => new(@object, default); - - public static ArrangeResult Arrange(this TMock mock, Func @object) - where TMock: notnull - => new(@object(mock), mock); - - public static ActResult Act(this ArrangeResult arrange, Action act) - where T : notnull - where TMock : notnull - { - try - { - act(arrange.Object); - return new ActResult(arrange.Object, arrange.Mock, default); - } - catch (Exception e) - { - return new ActResult(arrange.Object, arrange.Mock, e); - } - } - - public static ActResult Act(this ArrangeResult arrange, Func act) - where TResult : notnull - where TMock : notnull - { - try - { - return new ActResult(act(arrange.Object), arrange.Mock, default); - } - catch (Exception e) - { - return new ActResult(default, arrange.Mock, e); - } - } - - public static void Assert(this ActResult act, Action assert) - where T : notnull - where TMock : notnull - { - act.Exception?.Throw(); - assert(act.Object); - } - - public static void Assert(this ActResult act, Action assert) - where T : notnull - where TMock : notnull - { - act.Exception?.Throw(); - assert(act.Object, act.Mock); - } - - public static Task> ArrangeAsync(T @object) - => Task.FromResult(new ArrangeResult(@object, default)); - - public static async Task> Act(this Task> arrange, Func> act) - where TMock : notnull - where TResult : notnull - { - var a = await arrange; - try - { - return new ActResult(await act(a.Object), a.Mock, default); - } - catch (Exception e) - { - return new ActResult(default, a.Mock, e); - } - } - - public static async Task Assert(this Task> act, Func assert) - where T : notnull - where TMock : notnull - { - var result = await act; - await assert(result.Object); - } - - public readonly struct ArrangeResult - where TMock : notnull - { - internal ArrangeResult(T @object, TMock mock) => (Object, Mock) = (@object, mock); - internal T Object { get; } - internal TMock Mock { get; } - } - - public readonly struct ActResult - where T: notnull - { - internal ActResult(T @object, TMock mock, Exception? exception) - => (Object, Mock, Exception) = (@object, mock, exception); - internal T Object { get; } - internal TMock Mock { get; } - internal Exception? Exception { get; } - } +using System; +using System.Threading.Tasks; + +namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.SampleTests +{ + public class Unit + { } -} + + public static class ExceptionExtensions + { + public static Unit Throw(this Exception e) => throw e; + } + + public static class AAA + { + public static ArrangeResult Arrange(this T @object, Action action) + { + action(@object); + return new ArrangeResult(@object, default); + } + + public static ArrangeResult Arrange(T @object) + => new(@object, default); + + public static ArrangeResult Arrange(this TMock mock, Func @object) + where TMock: notnull + => new(@object(mock), mock); + + public static ActResult Act(this ArrangeResult arrange, Action act) + where T : notnull + where TMock : notnull + { + try + { + act(arrange.Object); + return new ActResult(arrange.Object, arrange.Mock, default); + } + catch (Exception e) + { + return new ActResult(arrange.Object, arrange.Mock, e); + } + } + + public static ActResult Act(this ArrangeResult arrange, Func act) + where TResult : notnull + where TMock : notnull + { + try + { + return new ActResult(act(arrange.Object), arrange.Mock, default); + } + catch (Exception e) + { + return new ActResult(default, arrange.Mock, e); + } + } + + public static void Assert(this ActResult act, Action assert) + where T : notnull + where TMock : notnull + { + act.Exception?.Throw(); + assert(act.Object); + } + + public static void Assert(this ActResult act, Action assert) + where T : notnull + where TMock : notnull + { + act.Exception?.Throw(); + assert(act.Object, act.Mock); + } + + public static Task> ArrangeAsync(T @object) + => Task.FromResult(new ArrangeResult(@object, default)); + + public static async Task> Act(this Task> arrange, Func> act) + where TMock : notnull + where TResult : notnull + { + var a = await arrange; + try + { + return new ActResult(await act(a.Object), a.Mock, default); + } + catch (Exception e) + { + return new ActResult(default, a.Mock, e); + } + } + + public static async Task Assert(this Task> act, Func assert) + where T : notnull + where TMock : notnull + { + var result = await act; + await assert(result.Object); + } + + public readonly struct ArrangeResult + where TMock : notnull + { + internal ArrangeResult(T @object, TMock? mock) => (Object, Mock) = (@object, mock); + internal T Object { get; } + internal TMock? Mock { get; } + } + + public readonly struct ActResult + where T: notnull + { + internal ActResult(T? @object, TMock? mock, Exception? exception) + => (Object, Mock, Exception) = (@object, mock, exception); + internal T? Object { get; } + internal TMock? Mock { get; } + internal Exception? Exception { get; } + } + } +} diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/DataContextExtensions.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/DataContextExtensions.cs index a3e9b78..4253c25 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/DataContextExtensions.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/DataContextExtensions.cs @@ -1,12 +1,12 @@ namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.SampleTests { - public static class DataContextExtensions - { - public static Id Insert(this IDataContext context, T item) - where T : IHasWriteableId - { - item.Id = context.InsertWithInt64Identity(item).AsId(); - return item.Id; - } - } + public static class DataContextExtensions + { + public static Id Insert(this IDataContext context, T item) + where T : IHasWriteableId + { + item.Id = context.InsertWithInt64Identity(item).AsId(); + return item.Id; + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/Entity2Item.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/Entity2Item.cs index 397df90..f86dea2 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/Entity2Item.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/Entity2Item.cs @@ -1,15 +1,15 @@ namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.SampleTests { - public sealed class Entity2Item - { - public Id EntityId { get; set; } - public Entity Entity { get; set; } = null!; + public sealed class Entity2Item + { + public Id EntityId { get; set; } + public Entity Entity { get; set; } = null!; public Id ItemId { get; set; } - public Entity2Item() - { - } + public Entity2Item() + { + } - public Item Item { get; set; } = null!; + public Item Item { get; set; } = null!; } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/IHasId.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/IHasId.cs index d3808f4..a7ec6b4 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/IHasId.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/IHasId.cs @@ -1,16 +1,16 @@ namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.SampleTests { - public interface IHasId + public interface IHasId where T: IHasId where TId : notnull { - Id Id { get; } - } - - public interface IHasWriteableId : IHasId + Id Id { get; } + } + + public interface IHasWriteableId : IHasId where T: IHasWriteableId where TId : notnull { - new Id Id { get; set; } - } + new Id Id { get; set; } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/Id.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/Id.cs index 9596164..a4b6052 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/Id.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/Id.cs @@ -9,7 +9,7 @@ public static class Id public static Id AsId(this TId id) where T : IHasId where TId : notnull - => new Id(id); + => new(id); } public readonly struct Id diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/IdTests.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/IdTests.cs index 03192b7..c3fa9e1 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/IdTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/IdTests.cs @@ -21,6 +21,7 @@ public IdTests() .UseLoggerFactory(TestUtils.LoggerFactory) .EnableSensitiveDataLogging() .UseNpgsql("Server=DBHost;Port=5432;Database=IdTests;User Id=postgres;Password=TestPassword;Pooling=true;MinPoolSize=10;MaxPoolSize=100;") + //.UseNpgsql("Server=localhost;Port=5415;Database=IdTests;User Id=postgres;Password=Password12!;Pooling=true;MinPoolSize=10;MaxPoolSize=100;") .Options); _efContext.Database.EnsureDeleted(); _efContext.Database.EnsureCreated(); @@ -39,7 +40,7 @@ IDataContext CreateLinqToDbContext(TestContext testContext) [Ignore("Incomplete.")] public void TestInsertWithoutTracker([Values("test insert")] string name) => _efContext - .Arrange(c => CreateLinqToDbContext(c)) + .Arrange(CreateLinqToDbContext) .Act(c => c.Insert(new Entity { Name = name })) .Assert(id => _efContext.Entitites.Single(e => e.Id == id).Name.Should().Be(name)); @@ -73,7 +74,7 @@ public void TestIncludeDetails([Values] bool l2db, [Values] bool tracking) .AsLinqToDb(l2db) .AsTracking(tracking) .ToArray()) - .Assert(e => e.First().Details.First().Details.Count().Should().Be(2)); + .Assert(e => e?.First().Details.First().Details.Count().Should().Be(2)); [Test] public void TestManyToManyIncludeTrackerPoison([Values] bool l2db) @@ -102,7 +103,7 @@ public void TestManyToManyInclude([Values] bool l2db, [Values] bool tracking) .AsLinqToDb(l2db) .AsTracking(tracking) .ToArray()) - .Assert(m => m[0].Items.First().Item.Should().BeSameAs(m[1].Items.First().Item)); + .Assert(m => m?[0].Items.First().Item.Should().BeSameAs(m[1].Items.First().Item)); [Test] [Ignore("Incomplete.")] @@ -115,7 +116,7 @@ public void TestMasterInclude([Values] bool l2db, [Values] bool tracking) .AsLinqToDb(l2db) .AsTracking(tracking) .ToArray()) - .Assert(m => m[0].Master.Should().BeSameAs(m[1].Master)); + .Assert(m => m?[0].Master.Should().BeSameAs(m[1].Master)); [Test] [Ignore("Incomplete.")] @@ -128,7 +129,7 @@ public void TestMasterInclude2([Values] bool l2db, [Values] bool tracking) .AsTracking(tracking) .AsLinqToDb(l2db) .ToArray()) - .Assert(m => m[0].Master.Should().BeSameAs(m[1].Master)); + .Assert(m => m?[0].Master.Should().BeSameAs(m[1].Master)); void InsertDefaults(IDataContext dataContext) { diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/ModelBuilderExtensions.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/ModelBuilderExtensions.cs index 1045a2a..c255fc0 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/ModelBuilderExtensions.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/ModelBuilderExtensions.cs @@ -98,25 +98,25 @@ public static ModelBuilder UseOneIdSequence(this ModelBuilder modelBuilder, s public static ModelBuilder UseSnakeCase(this ModelBuilder modelBuilder) { - modelBuilder.Model.SetDefaultSchema(modelBuilder.Model.GetDefaultSchema().ToSnakeCase()); + modelBuilder.Model.SetDefaultSchema(modelBuilder.Model.GetDefaultSchema()?.ToSnakeCase()); foreach (var entity in modelBuilder.Model.GetEntityTypes()) { - entity.SetTableName(entity.GetTableName().ToSnakeCase()); - var storeObjectId = StoreObjectIdentifier.Create(entity, StoreObjectType.Table); + entity.SetTableName(entity.GetTableName()?.ToSnakeCase()); + var storeObjectId = StoreObjectIdentifier.Create(entity, StoreObjectType.Table)!; foreach (var property in entity.GetProperties()) { - property.SetColumnName(property.GetColumnName(storeObjectId!.Value).ToSnakeCase()); + property.SetColumnName(property.GetColumnName(storeObjectId.Value)?.ToSnakeCase()); } - foreach (var key in entity.GetKeys()) - key.SetName(key.GetName().ToSnakeCase()); + foreach (var key in entity.GetKeys()) + key.SetName(key.GetName()?.ToSnakeCase()); - foreach (var key in entity.GetForeignKeys()) - key.SetConstraintName(key.GetConstraintName().ToSnakeCase()); + foreach (var key in entity.GetForeignKeys()) + key.SetConstraintName(key.GetConstraintName()?.ToSnakeCase()); - foreach (var index in entity.GetIndexes()) - index.SetDatabaseName(index.GetDatabaseName().ToSnakeCase()); + foreach (var index in entity.GetIndexes()) + index.SetDatabaseName(index.GetDatabaseName()?.ToSnakeCase()); } return modelBuilder; } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/StringExtensions.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/StringExtensions.cs index 687b3ee..d1c7560 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/StringExtensions.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/StringExtensions.cs @@ -2,15 +2,26 @@ namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.SampleTests { - public static class StringExtensions - { - public static string ToSnakeCase(this string input) - { - if (string.IsNullOrEmpty(input)) - return input; + public static partial class StringExtensions + { + public static string ToSnakeCase(this string input) + { + if (string.IsNullOrEmpty(input)) + return input; - var startUnderscores = Regex.Match(input, @"^_+"); - return startUnderscores + Regex.Replace(input, @"([a-z0-9])([A-Z])", "$1_$2").ToLower(); - } - } + var startUnderscores = UnderscoresMatcher.Match(input); + return startUnderscores + Replacer.Replace(input, "$1_$2").ToLowerInvariant(); + } + + // TODO: uncomment after azure pipelines updated to 17.4 + //[GeneratedRegex("^_+")] + //private static partial Regex UnderscoresMatcher(); + //[GeneratedRegex("([a-z0-9])([A-Z])")] + //private static partial Regex Replacer(); + +#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'. + private static readonly Regex UnderscoresMatcher = new ("^_+", RegexOptions.Compiled); + private static readonly Regex Replacer = new ("([a-z0-9])([A-Z])", RegexOptions.Compiled); +#pragma warning restore SYSLIB1045 // Convert to 'GeneratedRegexAttribute'. + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/ForMapping/ForMappingContext.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/ForMapping/ForMappingContext.cs index b932655..3a64083 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/ForMapping/ForMappingContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/ForMapping/ForMappingContext.cs @@ -5,10 +5,8 @@ namespace LinqToDB.EntityFrameworkCore.SQLite.Tests.Models.ForMapping { public class ForMappingContext : ForMappingContextBase { - public ForMappingContext(DbContextOptions options) : base(options) { - } protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CategoriesMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CategoriesMap.cs index 5537fbe..2fe0cbc 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CategoriesMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CategoriesMap.cs @@ -8,7 +8,6 @@ public class CategoriesMap : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { - builder.HasKey(e => e.CategoryId); builder.HasIndex(e => e.CategoryName) diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomerCustomerDemoMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomerCustomerDemoMap.cs index 3f63adb..e4c1510 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomerCustomerDemoMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomerCustomerDemoMap.cs @@ -4,33 +4,31 @@ namespace LinqToDB.EntityFrameworkCore.SQLite.Tests.Models.Northwind.Mapping { - public class CustomerCustomerDemoMap : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - - builder.HasKey(e => new { e.CustomerId, e.CustomerTypeId }); + public class CustomerCustomerDemoMap : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(e => new { e.CustomerId, e.CustomerTypeId }); - builder.Property(e => e.CustomerId) - .HasColumnName("CustomerID") - .HasMaxLength(5); + builder.Property(e => e.CustomerId) + .HasColumnName("CustomerID") + .HasMaxLength(5); - builder.Property(e => e.CustomerTypeId) - .HasColumnName("CustomerTypeID") - .HasMaxLength(10); + builder.Property(e => e.CustomerTypeId) + .HasColumnName("CustomerTypeID") + .HasMaxLength(10); - builder.HasOne(d => d.Customer) - .WithMany(p => p.CustomerCustomerDemo) - .HasForeignKey(d => d.CustomerId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_CustomerCustomerDemo_Customers"); + builder.HasOne(d => d.Customer) + .WithMany(p => p.CustomerCustomerDemo) + .HasForeignKey(d => d.CustomerId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_CustomerCustomerDemo_Customers"); - builder.HasOne(d => d.CustomerType) - .WithMany(p => p.CustomerCustomerDemo) - .HasForeignKey(d => d.CustomerTypeId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_CustomerCustomerDemo"); - - } - } + builder.HasOne(d => d.CustomerType) + .WithMany(p => p.CustomerCustomerDemo) + .HasForeignKey(d => d.CustomerTypeId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_CustomerCustomerDemo"); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomerDemographicsMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomerDemographicsMap.cs index c118976..edb8e09 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomerDemographicsMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomerDemographicsMap.cs @@ -4,18 +4,18 @@ namespace LinqToDB.EntityFrameworkCore.SQLite.Tests.Models.Northwind.Mapping { - public class CustomerDemographicsMap : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasKey(e => e.CustomerTypeId); + public class CustomerDemographicsMap : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(e => e.CustomerTypeId); - builder.Property(e => e.CustomerTypeId) - .HasColumnName("CustomerTypeID") - .HasMaxLength(10) - .ValueGeneratedNever(); + builder.Property(e => e.CustomerTypeId) + .HasColumnName("CustomerTypeID") + .HasMaxLength(10) + .ValueGeneratedNever(); - builder.Property(e => e.CustomerDesc).HasColumnType("text"); - } - } + builder.Property(e => e.CustomerDesc).HasColumnType("text"); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomersMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomersMap.cs index fda5264..74fa911 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomersMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/CustomersMap.cs @@ -4,44 +4,42 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Northwind.Mapping { - public class CustomersMap : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - - builder.HasKey(e => e.CustomerId); - - builder.HasIndex(e => e.City) - .HasDatabaseName("City"); - - builder.HasIndex(e => e.CompanyName) - .HasDatabaseName("Customer_CompanyName"); - - builder.HasIndex(e => e.PostalCode) - .HasDatabaseName("Customer_Postal_ode"); - - builder.HasIndex(e => e.Region) - .HasDatabaseName("Customer_Region"); - - builder.Property(e => e.CustomerId) - .HasColumnName("CustomerID") - .HasMaxLength(5) - .ValueGeneratedNever(); - - builder.Property(e => e.Address).HasMaxLength(60); - builder.Property(e => e.City).HasMaxLength(15); - builder.Property(e => e.CompanyName) - .IsRequired() - .HasMaxLength(40); - - builder.Property(e => e.ContactName).HasMaxLength(30); - builder.Property(e => e.ContactTitle).HasMaxLength(30); - builder.Property(e => e.Country).HasMaxLength(15); - builder.Property(e => e.Fax).HasMaxLength(24); - builder.Property(e => e.Phone).HasMaxLength(24); - builder.Property(e => e.PostalCode).HasMaxLength(10); - builder.Property(e => e.Region).HasMaxLength(15); - - } - } + public class CustomersMap : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(e => e.CustomerId); + + builder.HasIndex(e => e.City) + .HasDatabaseName("City"); + + builder.HasIndex(e => e.CompanyName) + .HasDatabaseName("Customer_CompanyName"); + + builder.HasIndex(e => e.PostalCode) + .HasDatabaseName("Customer_Postal_ode"); + + builder.HasIndex(e => e.Region) + .HasDatabaseName("Customer_Region"); + + builder.Property(e => e.CustomerId) + .HasColumnName("CustomerID") + .HasMaxLength(5) + .ValueGeneratedNever(); + + builder.Property(e => e.Address).HasMaxLength(60); + builder.Property(e => e.City).HasMaxLength(15); + builder.Property(e => e.CompanyName) + .IsRequired() + .HasMaxLength(40); + + builder.Property(e => e.ContactName).HasMaxLength(30); + builder.Property(e => e.ContactTitle).HasMaxLength(30); + builder.Property(e => e.Country).HasMaxLength(15); + builder.Property(e => e.Fax).HasMaxLength(24); + builder.Property(e => e.Phone).HasMaxLength(24); + builder.Property(e => e.PostalCode).HasMaxLength(10); + builder.Property(e => e.Region).HasMaxLength(15); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/EmployeeTerritoriesMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/EmployeeTerritoriesMap.cs index af6a9ad..97ebfa0 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/EmployeeTerritoriesMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/EmployeeTerritoriesMap.cs @@ -4,29 +4,29 @@ namespace LinqToDB.EntityFrameworkCore.SQLite.Tests.Models.Northwind.Mapping { - public class EmployeeTerritoriesMap : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasKey(e => new { e.EmployeeId, e.TerritoryId }); + public class EmployeeTerritoriesMap : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(e => new { e.EmployeeId, e.TerritoryId }); - builder.Property(e => e.EmployeeId).HasColumnName("EmployeeID"); + builder.Property(e => e.EmployeeId).HasColumnName("EmployeeID"); - builder.Property(e => e.TerritoryId) - .HasColumnName("TerritoryID") - .HasMaxLength(20); + builder.Property(e => e.TerritoryId) + .HasColumnName("TerritoryID") + .HasMaxLength(20); - builder.HasOne(d => d.Employee) - .WithMany(p => p.EmployeeTerritories) - .HasForeignKey(d => d.EmployeeId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_EmployeeTerritories_Employees"); + builder.HasOne(d => d.Employee) + .WithMany(p => p.EmployeeTerritories) + .HasForeignKey(d => d.EmployeeId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_EmployeeTerritories_Employees"); - builder.HasOne(d => d.Territory) - .WithMany(p => p.EmployeeTerritories) - .HasForeignKey(d => d.TerritoryId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_EmployeeTerritories_Territories"); - } - } + builder.HasOne(d => d.Territory) + .WithMany(p => p.EmployeeTerritories) + .HasForeignKey(d => d.TerritoryId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_EmployeeTerritories_Territories"); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/EmployeesMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/EmployeesMap.cs index c619c3e..e03bc45 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/EmployeesMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/EmployeesMap.cs @@ -56,7 +56,7 @@ public void Configure(EntityTypeBuilder builder) builder.Property(e => e.TitleOfCourtesy).HasMaxLength(25); builder.HasOne(d => d.ReportsToNavigation) - .WithMany(p => p!.InverseReportsToNavigation) + .WithMany(p => p.InverseReportsToNavigation) .HasForeignKey(d => d.ReportsTo) .HasConstraintName("FK_Employees_Employees"); } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/OrderDetailsMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/OrderDetailsMap.cs index 9a71f50..7aae32f 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/OrderDetailsMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/OrderDetailsMap.cs @@ -4,39 +4,39 @@ namespace LinqToDB.EntityFrameworkCore.SQLite.Tests.Models.Northwind.Mapping { - public class OrderDetailsMap : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasKey(e => new { e.OrderId, e.ProductId }); + public class OrderDetailsMap : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(e => new { e.OrderId, e.ProductId }); - builder.ToTable("Order Details"); + builder.ToTable("Order Details"); - builder.HasIndex(e => e.OrderId) - .HasDatabaseName("OrdersOrder_Details"); + builder.HasIndex(e => e.OrderId) + .HasDatabaseName("OrdersOrder_Details"); - builder.HasIndex(e => e.ProductId) - .HasDatabaseName("ProductsOrder_Details"); + builder.HasIndex(e => e.ProductId) + .HasDatabaseName("ProductsOrder_Details"); - builder.Property(e => e.OrderId).HasColumnName("OrderID"); + builder.Property(e => e.OrderId).HasColumnName("OrderID"); - builder.Property(e => e.ProductId).HasColumnName("ProductID"); + builder.Property(e => e.ProductId).HasColumnName("ProductID"); - builder.Property(e => e.Quantity).HasDefaultValue(1); + builder.Property(e => e.Quantity).HasDefaultValue(1); - builder.Property(e => e.UnitPrice).HasColumnType("decimal(13, 4)"); + builder.Property(e => e.UnitPrice).HasColumnType("decimal(13, 4)"); - builder.HasOne(d => d.Order) - .WithMany(p => p.OrderDetails) - .HasForeignKey(d => d.OrderId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_Order_Details_Orders"); + builder.HasOne(d => d.Order) + .WithMany(p => p.OrderDetails) + .HasForeignKey(d => d.OrderId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_Order_Details_Orders"); - builder.HasOne(d => d.Product) - .WithMany(p => p.OrderDetails) - .HasForeignKey(d => d.ProductId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_Order_Details_Products"); - } - } + builder.HasOne(d => d.Product) + .WithMany(p => p.OrderDetails) + .HasForeignKey(d => d.ProductId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_Order_Details_Products"); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/OrderMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/OrderMap.cs index 02bacd3..38cc6db 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/OrderMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/OrderMap.cs @@ -8,72 +8,71 @@ public class OrderMap : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { - - builder.HasKey(e => e.OrderId); + builder.HasKey(e => e.OrderId); - builder.HasIndex(e => e.CustomerId) - .HasDatabaseName("Order_CustomersOrders"); + builder.HasIndex(e => e.CustomerId) + .HasDatabaseName("Order_CustomersOrders"); - builder.HasIndex(e => e.EmployeeId) - .HasDatabaseName("Order_EmployeesOrders"); + builder.HasIndex(e => e.EmployeeId) + .HasDatabaseName("Order_EmployeesOrders"); - builder.HasIndex(e => e.OrderDate) - .HasDatabaseName("Order_OrderDate"); + builder.HasIndex(e => e.OrderDate) + .HasDatabaseName("Order_OrderDate"); - builder.HasIndex(e => e.ShipPostalCode) - .HasDatabaseName("Order_ShipPostalCode"); + builder.HasIndex(e => e.ShipPostalCode) + .HasDatabaseName("Order_ShipPostalCode"); - builder.HasIndex(e => e.ShipVia) - .HasDatabaseName("Order_ShippersOrders"); + builder.HasIndex(e => e.ShipVia) + .HasDatabaseName("Order_ShippersOrders"); - builder.HasIndex(e => e.ShippedDate) - .HasDatabaseName("Order_ShippedDate"); + builder.HasIndex(e => e.ShippedDate) + .HasDatabaseName("Order_ShippedDate"); - builder.Property(e => e.OrderId).HasColumnName("OrderID") - .ValueGeneratedNever(); + builder.Property(e => e.OrderId).HasColumnName("OrderID") + .ValueGeneratedNever(); - builder.Property(e => e.CustomerId) - .HasColumnName("CustomerID") - .HasMaxLength(5); + builder.Property(e => e.CustomerId) + .HasColumnName("CustomerID") + .HasMaxLength(5); - builder.Property(e => e.EmployeeId).HasColumnName("EmployeeID"); + builder.Property(e => e.EmployeeId).HasColumnName("EmployeeID"); - builder.Property(e => e.Freight) - .HasColumnType("decimal(13, 4)") - .HasDefaultValue(0m); + builder.Property(e => e.Freight) + .HasColumnType("decimal(13, 4)") + .HasDefaultValue(0m); - builder.Property(e => e.OrderDate).HasColumnType("datetime"); + builder.Property(e => e.OrderDate).HasColumnType("datetime"); - builder.Property(e => e.RequiredDate).HasColumnType("datetime"); + builder.Property(e => e.RequiredDate).HasColumnType("datetime"); - builder.Property(e => e.ShipAddress).HasMaxLength(60); + builder.Property(e => e.ShipAddress).HasMaxLength(60); - builder.Property(e => e.ShipCity).HasMaxLength(15); + builder.Property(e => e.ShipCity).HasMaxLength(15); - builder.Property(e => e.ShipCountry).HasMaxLength(15); + builder.Property(e => e.ShipCountry).HasMaxLength(15); - builder.Property(e => e.ShipName).HasMaxLength(40); + builder.Property(e => e.ShipName).HasMaxLength(40); - builder.Property(e => e.ShipPostalCode).HasMaxLength(10); + builder.Property(e => e.ShipPostalCode).HasMaxLength(10); - builder.Property(e => e.ShipRegion).HasMaxLength(15); + builder.Property(e => e.ShipRegion).HasMaxLength(15); - builder.Property(e => e.ShippedDate).HasColumnType("datetime"); + builder.Property(e => e.ShippedDate).HasColumnType("datetime"); - builder.HasOne(d => d.Customer) - .WithMany(p => p!.Orders) - .HasForeignKey(d => d.CustomerId) - .HasConstraintName("FK_Orders_Customers"); + builder.HasOne(d => d.Customer) + .WithMany(p => p.Orders) + .HasForeignKey(d => d.CustomerId) + .HasConstraintName("FK_Orders_Customers"); - builder.HasOne(d => d.Employee) - .WithMany(p => p!.Orders) - .HasForeignKey(d => d.EmployeeId) - .HasConstraintName("FK_Orders_Employees"); + builder.HasOne(d => d.Employee) + .WithMany(p => p.Orders) + .HasForeignKey(d => d.EmployeeId) + .HasConstraintName("FK_Orders_Employees"); - builder.HasOne(d => d.ShipViaNavigation) - .WithMany(p => p!.Orders) - .HasForeignKey(d => d.ShipVia) - .HasConstraintName("FK_Orders_Shippers"); - } + builder.HasOne(d => d.ShipViaNavigation) + .WithMany(p => p.Orders) + .HasForeignKey(d => d.ShipVia) + .HasConstraintName("FK_Orders_Shippers"); + } } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/ProductsMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/ProductsMap.cs index 2339d90..6b92ae2 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/ProductsMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/ProductsMap.cs @@ -43,12 +43,12 @@ public void Configure(EntityTypeBuilder builder) builder.Property(e => e.UnitsOnOrder).HasDefaultValue((short)0); builder.HasOne(d => d.Category) - .WithMany(p => p!.Products) + .WithMany(p => p.Products) .HasForeignKey(d => d.CategoryId) .HasConstraintName("FK_Products_Categories"); builder.HasOne(d => d.Supplier) - .WithMany(p => p!.Products) + .WithMany(p => p.Products) .HasForeignKey(d => d.SupplierId) .HasConstraintName("FK_Products_Suppliers"); } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/RegionMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/RegionMap.cs index e8a80dc..66eb2b3 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/RegionMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind.Mapping/RegionMap.cs @@ -4,19 +4,19 @@ namespace LinqToDB.EntityFrameworkCore.SQLite.Tests.Models.Northwind.Mapping { - public class RegionMap : IEntityTypeConfiguration - { - public void Configure(EntityTypeBuilder builder) - { - builder.HasKey(e => e.RegionId); + public class RegionMap : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(e => e.RegionId); - builder.Property(e => e.RegionId) - .HasColumnName("RegionID") - .ValueGeneratedNever(); + builder.Property(e => e.RegionId) + .HasColumnName("RegionID") + .ValueGeneratedNever(); - builder.Property(e => e.RegionDescription) - .IsRequired() - .HasMaxLength(50); - } - } + builder.Property(e => e.RegionDescription) + .IsRequired() + .HasMaxLength(50); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind/NorthwindContext.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind/NorthwindContext.cs index 1697076..e555c35 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind/NorthwindContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/Models/Northwind/NorthwindContext.cs @@ -23,7 +23,6 @@ public class NorthwindContext : DbContext public NorthwindContext(DbContextOptions options) : base(options) { - } protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/SQLiteTests.cs b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/SQLiteTests.cs index af110e6..9a44204 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/SQLiteTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SQLite.Tests/SQLiteTests.cs @@ -34,6 +34,5 @@ private NorthwindContext CreateSQLiteSqlExntitiesContext() ctx.Database.EnsureCreated(); return ctx; } - } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ForMappingTests.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ForMappingTests.cs index 7badcbd..34ae3c6 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ForMappingTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ForMappingTests.cs @@ -16,7 +16,7 @@ public class ForMappingTests : ForMappingTestsBase public override ForMappingContextBase CreateContext() { var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlServer("Server=.;Database=ForMapping;Integrated Security=SSPI"); + optionsBuilder.UseSqlServer("Server=.;Database=ForMapping;Integrated Security=SSPI;Encrypt=true;TrustServerCertificate=true"); optionsBuilder.UseLoggerFactory(TestUtils.LoggerFactory); var options = optionsBuilder.Options; diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/IssueTests.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/IssueTests.cs index 097a9f9..8186b54 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/IssueTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/IssueTests.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Diagnostics.CodeAnalysis; +using System.Linq; using FluentAssertions; using LinqToDB.EntityFrameworkCore.BaseTests; using LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.IssueModel; @@ -10,7 +11,7 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests [TestFixture] public class IssueTests : TestsBase { - private DbContextOptions? _options; + private DbContextOptions _options; private bool _created; public IssueTests() @@ -18,11 +19,12 @@ public IssueTests() InitOptions(); } + [MemberNotNull(nameof(_options))] private void InitOptions() { var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlServer("Server=.;Database=IssuesEFCore;Integrated Security=SSPI"); + optionsBuilder.UseSqlServer("Server=.;Database=IssuesEFCore;Integrated Security=SSPI;Encrypt=true;TrustServerCertificate=true"); optionsBuilder.UseLoggerFactory(TestUtils.LoggerFactory); _options = optionsBuilder.Options; @@ -30,7 +32,7 @@ private void InitOptions() private IssueContext CreateContext() { - var ctx = new IssueContext(_options!); + var ctx = new IssueContext(_options); if (!_created) { diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/JsonConverTests.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/JsonConverTests.cs index 0039be9..52b88aa 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/JsonConverTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/JsonConverTests.cs @@ -9,7 +9,6 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests { - [TestFixture] public class JsonConverTests : TestsBase { @@ -69,7 +68,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.Property(e => e.NameLocalized) .HasColumnName("NameLocalized_JSON") .HasConversion(v => JsonConvert.SerializeObject(v), - v => JsonConvert.DeserializeObject(v)); + v => JsonConvert.DeserializeObject(v) ?? new()); entity.Property(e => e.CrashEnum).HasColumnType("tinyint"); entity.Property(e => e.GuidColumn).HasColumnType("uniqueidentifier"); }); @@ -85,13 +84,13 @@ public JsonConverTests() var optionsBuilder = new DbContextOptionsBuilder(); //new SqlServerDbContextOptionsBuilder(optionsBuilder); - optionsBuilder.UseSqlServer("Server=.;Database=JsonConvertContext;Integrated Security=SSPI"); + optionsBuilder.UseSqlServer("Server=.;Database=JsonConvertContext;Integrated Security=SSPI;Encrypt=true;TrustServerCertificate=true"); optionsBuilder.UseLoggerFactory(TestUtils.LoggerFactory); _options = optionsBuilder.Options; } - public static string JsonValue(string column, [NotParameterized] string path) + public static string JsonValue(string? column, [NotParameterized] string path) { throw new NotSupportedException(); } @@ -133,7 +132,7 @@ public void TestJsonConvert() p.NameLocalized, p.CrashEnum, p.GuidColumn, - JsonValue = JsonValue(p.JsonColumn!, path) + JsonValue = JsonValue(p.JsonColumn, path) }); var item = items.FirstOrDefault(); @@ -152,7 +151,6 @@ public void TestJsonConvert() // // Assert.That(concrete.English, Is.EqualTo("English")); } - } } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/ForMapping/ForMappingContext.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/ForMapping/ForMappingContext.cs index 061b0af..674c7bd 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/ForMapping/ForMappingContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/ForMapping/ForMappingContext.cs @@ -5,10 +5,8 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.ForMapping { public class ForMappingContext : ForMappingContextBase { - public ForMappingContext(DbContextOptions options) : base(options) { - } protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Inheritance/InheritanceContext.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Inheritance/InheritanceContext.cs index a61edcd..ef00fc9 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Inheritance/InheritanceContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Inheritance/InheritanceContext.cs @@ -1,6 +1,4 @@ -using System; -using System.Linq; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Inheritance { diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/Issue73Entity.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/Issue73Entity.cs index 2a95979..2e16a57 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/Issue73Entity.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/Issue73Entity.cs @@ -8,10 +8,9 @@ public sealed class Issue73Entity public int? ParentId { get; set; } - public Issue73Entity? Parent { get; set; } = null!; + public Issue73Entity? Parent { get; set; } public List Childs { get; set; } = null!; public string Name { get; set; } = null!; } - } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/IssueContext.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/IssueContext.cs index e8dee5c..a1e1d95 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/IssueContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/IssueContext.cs @@ -10,7 +10,6 @@ public class IssueContext : DbContext public IssueContext(DbContextOptions options) : base(options) { - } protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -20,9 +19,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) b.HasKey(x => new { x.Id }); b.HasOne(x => x.Parent) - .WithMany(x => x!.Childs) + .WithMany(x => x.Childs) .HasForeignKey(x => new { x.ParentId }) - .HasPrincipalKey(x => new { x!.Id }); + .HasPrincipalKey(x => new { x.Id }); b.HasData(new[] { @@ -43,7 +42,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder .Entity() .HasOne(p => p.Assessment) - .WithOne(pa => pa!.Patent) + .WithOne(pa => pa.Patent) .HasForeignKey(pa => pa.PatentId) .OnDelete(DeleteBehavior.Restrict); diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomerCustomerDemoMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomerCustomerDemoMap.cs index f4376ae..d681035 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomerCustomerDemoMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomerCustomerDemoMap.cs @@ -4,36 +4,34 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Northwind.Mapping { - public class CustomerCustomerDemoMap : BaseEntityMap - { - public override void Configure(EntityTypeBuilder builder) - { - base.Configure(builder); + public class CustomerCustomerDemoMap : BaseEntityMap + { + public override void Configure(EntityTypeBuilder builder) + { + base.Configure(builder); - - builder.HasKey(e => new { e.CustomerId, e.CustomerTypeId }) - .IsClustered(false); + builder.HasKey(e => new { e.CustomerId, e.CustomerTypeId }) + .IsClustered(false); - builder.Property(e => e.CustomerId) - .HasColumnName("CustomerID") - .HasMaxLength(5); + builder.Property(e => e.CustomerId) + .HasColumnName("CustomerID") + .HasMaxLength(5); - builder.Property(e => e.CustomerTypeId) - .HasColumnName("CustomerTypeID") - .HasMaxLength(10); + builder.Property(e => e.CustomerTypeId) + .HasColumnName("CustomerTypeID") + .HasMaxLength(10); - builder.HasOne(d => d.Customer) - .WithMany(p => p.CustomerCustomerDemo) - .HasForeignKey(d => d.CustomerId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_CustomerCustomerDemo_Customers"); + builder.HasOne(d => d.Customer) + .WithMany(p => p.CustomerCustomerDemo) + .HasForeignKey(d => d.CustomerId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_CustomerCustomerDemo_Customers"); - builder.HasOne(d => d.CustomerType) - .WithMany(p => p.CustomerCustomerDemo) - .HasForeignKey(d => d.CustomerTypeId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_CustomerCustomerDemo"); - - } - } + builder.HasOne(d => d.CustomerType) + .WithMany(p => p.CustomerCustomerDemo) + .HasForeignKey(d => d.CustomerTypeId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_CustomerCustomerDemo"); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomerDemographicsMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomerDemographicsMap.cs index 447dd94..780eb77 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomerDemographicsMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomerDemographicsMap.cs @@ -4,21 +4,21 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Northwind.Mapping { - public class CustomerDemographicsMap : BaseEntityMap - { - public override void Configure(EntityTypeBuilder builder) - { - base.Configure(builder); + public class CustomerDemographicsMap : BaseEntityMap + { + public override void Configure(EntityTypeBuilder builder) + { + base.Configure(builder); - builder.HasKey(e => e.CustomerTypeId) - .IsClustered(false); + builder.HasKey(e => e.CustomerTypeId) + .IsClustered(false); - builder.Property(e => e.CustomerTypeId) - .HasColumnName("CustomerTypeID") - .HasMaxLength(10) - .ValueGeneratedNever(); + builder.Property(e => e.CustomerTypeId) + .HasColumnName("CustomerTypeID") + .HasMaxLength(10) + .ValueGeneratedNever(); - builder.Property(e => e.CustomerDesc).HasColumnType("ntext"); - } - } + builder.Property(e => e.CustomerDesc).HasColumnType("ntext"); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomersMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomersMap.cs index 6ebe33f..b299db0 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomersMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/CustomersMap.cs @@ -4,45 +4,44 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Northwind.Mapping { - public class CustomersMap : BaseEntityMap - { - public override void Configure(EntityTypeBuilder builder) - { - base.Configure(builder); - - builder.HasKey(e => e.CustomerId); - - builder.HasIndex(e => e.City) - .HasDatabaseName("City"); - - builder.HasIndex(e => e.CompanyName) - .HasDatabaseName("CompanyName"); - - builder.HasIndex(e => e.PostalCode) - .HasDatabaseName("PostalCode"); - - builder.HasIndex(e => e.Region) - .HasDatabaseName("Region"); - - builder.Property(e => e.CustomerId) - .HasColumnName("CustomerID") - .HasMaxLength(5) - .ValueGeneratedNever(); - - builder.Property(e => e.Address).HasMaxLength(60); - builder.Property(e => e.City).HasMaxLength(15); - builder.Property(e => e.CompanyName) - .IsRequired() - .HasMaxLength(40); - - builder.Property(e => e.ContactName).HasMaxLength(30); - builder.Property(e => e.ContactTitle).HasMaxLength(30); - builder.Property(e => e.Country).HasMaxLength(15); - builder.Property(e => e.Fax).HasMaxLength(24); - builder.Property(e => e.Phone).HasMaxLength(24); - builder.Property(e => e.PostalCode).HasMaxLength(10); - builder.Property(e => e.Region).HasMaxLength(15); - - } - } + public class CustomersMap : BaseEntityMap + { + public override void Configure(EntityTypeBuilder builder) + { + base.Configure(builder); + + builder.HasKey(e => e.CustomerId); + + builder.HasIndex(e => e.City) + .HasDatabaseName("City"); + + builder.HasIndex(e => e.CompanyName) + .HasDatabaseName("CompanyName"); + + builder.HasIndex(e => e.PostalCode) + .HasDatabaseName("PostalCode"); + + builder.HasIndex(e => e.Region) + .HasDatabaseName("Region"); + + builder.Property(e => e.CustomerId) + .HasColumnName("CustomerID") + .HasMaxLength(5) + .ValueGeneratedNever(); + + builder.Property(e => e.Address).HasMaxLength(60); + builder.Property(e => e.City).HasMaxLength(15); + builder.Property(e => e.CompanyName) + .IsRequired() + .HasMaxLength(40); + + builder.Property(e => e.ContactName).HasMaxLength(30); + builder.Property(e => e.ContactTitle).HasMaxLength(30); + builder.Property(e => e.Country).HasMaxLength(15); + builder.Property(e => e.Fax).HasMaxLength(24); + builder.Property(e => e.Phone).HasMaxLength(24); + builder.Property(e => e.PostalCode).HasMaxLength(10); + builder.Property(e => e.Region).HasMaxLength(15); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/EmployeeTerritoriesMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/EmployeeTerritoriesMap.cs index 7261074..6b969cb 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/EmployeeTerritoriesMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/EmployeeTerritoriesMap.cs @@ -4,32 +4,32 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Northwind.Mapping { - public class EmployeeTerritoriesMap : BaseEntityMap - { - public override void Configure(EntityTypeBuilder builder) - { - base.Configure(builder); + public class EmployeeTerritoriesMap : BaseEntityMap + { + public override void Configure(EntityTypeBuilder builder) + { + base.Configure(builder); - builder.HasKey(e => new { e.EmployeeId, e.TerritoryId }) - .IsClustered(false); + builder.HasKey(e => new { e.EmployeeId, e.TerritoryId }) + .IsClustered(false); - builder.Property(e => e.EmployeeId).HasColumnName("EmployeeID"); + builder.Property(e => e.EmployeeId).HasColumnName("EmployeeID"); - builder.Property(e => e.TerritoryId) - .HasColumnName("TerritoryID") - .HasMaxLength(20); + builder.Property(e => e.TerritoryId) + .HasColumnName("TerritoryID") + .HasMaxLength(20); - builder.HasOne(d => d.Employee) - .WithMany(p => p.EmployeeTerritories) - .HasForeignKey(d => d.EmployeeId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_EmployeeTerritories_Employees"); + builder.HasOne(d => d.Employee) + .WithMany(p => p.EmployeeTerritories) + .HasForeignKey(d => d.EmployeeId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_EmployeeTerritories_Employees"); - builder.HasOne(d => d.Territory) - .WithMany(p => p.EmployeeTerritories) - .HasForeignKey(d => d.TerritoryId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_EmployeeTerritories_Territories"); - } - } + builder.HasOne(d => d.Territory) + .WithMany(p => p.EmployeeTerritories) + .HasForeignKey(d => d.TerritoryId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_EmployeeTerritories_Territories"); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/EmployeesMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/EmployeesMap.cs index 3be298a..8db37b6 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/EmployeesMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/EmployeesMap.cs @@ -58,7 +58,7 @@ public override void Configure(EntityTypeBuilder builder) builder.Property(e => e.TitleOfCourtesy).HasMaxLength(25); builder.HasOne(d => d.ReportsToNavigation) - .WithMany(p => p!.InverseReportsToNavigation) + .WithMany(p => p.InverseReportsToNavigation) .HasForeignKey(d => d.ReportsTo) .HasConstraintName("FK_Employees_Employees"); } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/OrderMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/OrderMap.cs index 972e5f4..2a4f9cb 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/OrderMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/OrderMap.cs @@ -63,17 +63,17 @@ public override void Configure(EntityTypeBuilder builder) builder.Property(e => e.ShippedDate).HasColumnType("datetime"); builder.HasOne(d => d.Customer) - .WithMany(p => p!.Orders) + .WithMany(p => p.Orders) .HasForeignKey(d => d.CustomerId) .HasConstraintName("FK_Orders_Customers"); builder.HasOne(d => d.Employee) - .WithMany(p => p!.Orders) + .WithMany(p => p.Orders) .HasForeignKey(d => d.EmployeeId) .HasConstraintName("FK_Orders_Employees"); builder.HasOne(d => d.ShipViaNavigation) - .WithMany(p => p!.Orders) + .WithMany(p => p.Orders) .HasForeignKey(d => d.ShipVia) .HasConstraintName("FK_Orders_Shippers"); } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/ProductsMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/ProductsMap.cs index 14c3801..9da5e12 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/ProductsMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/ProductsMap.cs @@ -43,12 +43,12 @@ public override void Configure(EntityTypeBuilder builder) builder.Property(e => e.UnitsOnOrder).HasDefaultValueSql("((0))"); builder.HasOne(d => d.Category) - .WithMany(p => p!.Products) + .WithMany(p => p.Products) .HasForeignKey(d => d.CategoryId) .HasConstraintName("FK_Products_Categories"); builder.HasOne(d => d.Supplier) - .WithMany(p => p!.Products) + .WithMany(p => p.Products) .HasForeignKey(d => d.SupplierId) .HasConstraintName("FK_Products_Suppliers"); } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/RegionMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/RegionMap.cs index 8e354aa..3a76668 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/RegionMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/RegionMap.cs @@ -4,22 +4,22 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Northwind.Mapping { - public class RegionMap : BaseEntityMap - { - public override void Configure(EntityTypeBuilder builder) - { - base.Configure(builder); + public class RegionMap : BaseEntityMap + { + public override void Configure(EntityTypeBuilder builder) + { + base.Configure(builder); - builder.HasKey(e => e.RegionId) - .IsClustered(false); + builder.HasKey(e => e.RegionId) + .IsClustered(false); - builder.Property(e => e.RegionId) - .HasColumnName("RegionID") - .ValueGeneratedNever(); + builder.Property(e => e.RegionId) + .HasColumnName("RegionID") + .ValueGeneratedNever(); - builder.Property(e => e.RegionDescription) - .IsRequired() - .HasMaxLength(50); - } - } + builder.Property(e => e.RegionDescription) + .IsRequired() + .HasMaxLength(50); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/TerritoriesMap.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/TerritoriesMap.cs index da3fe48..4326c73 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/TerritoriesMap.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind.Mapping/TerritoriesMap.cs @@ -4,31 +4,31 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Northwind.Mapping { - public class TerritoriesMap : BaseEntityMap - { - public override void Configure(EntityTypeBuilder builder) - { - base.Configure(builder); + public class TerritoriesMap : BaseEntityMap + { + public override void Configure(EntityTypeBuilder builder) + { + base.Configure(builder); - builder.HasKey(e => e.TerritoryId) - .IsClustered(false); + builder.HasKey(e => e.TerritoryId) + .IsClustered(false); - builder.Property(e => e.TerritoryId) - .HasColumnName("TerritoryID") - .HasMaxLength(20) - .ValueGeneratedNever(); + builder.Property(e => e.TerritoryId) + .HasColumnName("TerritoryID") + .HasMaxLength(20) + .ValueGeneratedNever(); - builder.Property(e => e.RegionId).HasColumnName("RegionID"); + builder.Property(e => e.RegionId).HasColumnName("RegionID"); - builder.Property(e => e.TerritoryDescription) - .IsRequired() - .HasMaxLength(50); + builder.Property(e => e.TerritoryDescription) + .IsRequired() + .HasMaxLength(50); - builder.HasOne(d => d.Region) - .WithMany(p => p.Territories) - .HasForeignKey(d => d.RegionId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("FK_Territories_Region"); - } - } + builder.HasOne(d => d.Region) + .WithMany(p => p.Territories) + .HasForeignKey(d => d.RegionId) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("FK_Territories_Region"); + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind/NorthwindContext.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind/NorthwindContext.cs index 4dd87d3..46b02e7 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind/NorthwindContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/Northwind/NorthwindContext.cs @@ -26,7 +26,6 @@ public class NorthwindContext : DbContext public NorthwindContext(DbContextOptions options) : base(options) { - } [DbFunction("ProcessLong", "dbo")] @@ -73,7 +72,7 @@ private void ConfigureGlobalQueryFilters(ModelBuilder builder) MemberHelper.MethodOf(() => ((NorthwindContext)null!).ConfigureEntityFilter(null!)).GetGenericMethodDefinition(); public void ConfigureEntityFilter(ModelBuilder builder) - where TEntity: class, ISoftDelete + where TEntity: class, ISoftDelete { NorthwindContext? obj = null; diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/QueryableExtensions.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/QueryableExtensions.cs index 98608b7..3a155e0 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/QueryableExtensions.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/QueryableExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Threading; @@ -10,6 +11,58 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests { public static class QueryableExtensions { + public static IQueryable AnyFromItems(this IQueryable source, IEnumerable items, + string propName) + { + var entityParam = Expression.Parameter(typeof(T), "e"); + var itemParam = Expression.Parameter(typeof(TItem), "i"); + + var anyPredicate = + Expression.Lambda( + Expression.Equal(itemParam, Expression.PropertyOrField(entityParam, propName)), + itemParam); + + var filterLambda = + Expression.Lambda>( + Expression.Call(typeof(Enumerable), nameof(Enumerable.Any), new[] { typeof(TItem) }, + Expression.Constant(items), anyPredicate), + entityParam); + + return source.Where(filterLambda); + } + + public static IQueryable AnyFromItems(this IQueryable source, string items, string propName) + { + var strItems = items.Split(",", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + + var entityParam = Expression.Parameter(typeof(T), "e"); + var propExpression = Expression.PropertyOrField(entityParam, propName); + var itemType = propExpression.Type; + var itemParam = Expression.Parameter(itemType, "i"); + + var anyPredicate = + Expression.Lambda( + Expression.Equal(itemParam, Expression.PropertyOrField(entityParam, propName)), + itemParam); + + // apply conversion + var itemsExpression = Expression.Call(typeof(QueryableExtensions), nameof(QueryableExtensions.ParseItems), + new[] { itemType }, Expression.Constant(strItems)); + + var filterLambda = + Expression.Lambda>( + Expression.Call(typeof(Enumerable), nameof(Enumerable.Any), new[] { itemType }, + itemsExpression, anyPredicate), + entityParam); + + return source.Where(filterLambda); + } + + private static IEnumerable ParseItems(IEnumerable items) + { + return items.Select(i => (TItem)Convert.ChangeType(i, typeof(TItem))); + } + public static async Task> FilterExistentAsync(this ICollection items, IQueryable dbQuery, Expression> prop, CancellationToken cancellationToken = default) { @@ -70,7 +123,7 @@ public static IQueryable FilterByProperties(this IQueryable que return query.Where(MakePropertiesPredicate(pattern, searchValue, isOr)); } - class ExpressionReplacer : ExpressionVisitor + sealed class ExpressionReplacer : ExpressionVisitor { readonly IDictionary _replaceMap; @@ -79,7 +132,10 @@ public ExpressionReplacer(IDictionary replaceMap) _replaceMap = replaceMap ?? throw new ArgumentNullException(nameof(replaceMap)); } - public override Expression Visit(Expression node) + // TODO: uncomment after azure pipelines updated to 17.4 + //[return: NotNullIfNotNull(nameof(node))] + [return: NotNullIfNotNull("node")] + public override Expression? Visit(Expression? node) { if (node != null && _replaceMap.TryGetValue(node, out var replacement)) return replacement; diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ToolsTests.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ToolsTests.cs index 9809ba6..51e0fec 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ToolsTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ToolsTests.cs @@ -5,7 +5,6 @@ using LinqToDB.Data; using LinqToDB.EntityFrameworkCore.BaseTests; using LinqToDB.EntityFrameworkCore.BaseTests.Models.Northwind; -using LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Inheritance; using LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Northwind; using LinqToDB.Expressions; using LinqToDB.Mapping; @@ -17,8 +16,7 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests [TestFixture] public class ToolsTests : TestsBase { - private readonly DbContextOptions _northwindOptions; - private DbContextOptions? _inheritanceOptions; + private readonly DbContextOptions _options; private readonly DbContextOptions _inmemoryOptions; static ToolsTests() @@ -27,35 +25,17 @@ static ToolsTests() DataConnection.TurnTraceSwitchOn(); } - static DbContextOptions CreateNorthwindOptions() + public ToolsTests() { var optionsBuilder = new DbContextOptionsBuilder(); //new SqlServerDbContextOptionsBuilder(optionsBuilder); - optionsBuilder.UseSqlServer("Server=.;Database=NorthwindEFCore;Integrated Security=SSPI"); + optionsBuilder.UseSqlServer("Server=.;Database=NorthwindEFCore;Integrated Security=SSPI;Encrypt=true;TrustServerCertificate=true"); optionsBuilder.UseLoggerFactory(TestUtils.LoggerFactory); - return optionsBuilder.Options; - } - - static DbContextOptions CreateInheritanceOptions() - { - var optionsBuilder = new DbContextOptionsBuilder(); - //new SqlServerDbContextOptionsBuilder(optionsBuilder); - - optionsBuilder.UseSqlServer("Server=.;Database=InheritanceEFCore;Integrated Security=SSPI"); - optionsBuilder.UseLoggerFactory(TestUtils.LoggerFactory); - optionsBuilder.EnableSensitiveDataLogging(); - - return optionsBuilder.Options; - } - - public ToolsTests() - { - _northwindOptions = CreateNorthwindOptions(); - + _options = optionsBuilder.Options; - var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder = new DbContextOptionsBuilder(); //new SqlServerDbContextOptionsBuilder(optionsBuilder); optionsBuilder.UseInMemoryDatabase("sample"); @@ -86,7 +66,7 @@ private void SetIdentityInsert(DbContext ctx, string tableName, bool isOn) private NorthwindContext CreateContext(bool enableFilter) { - var ctx = new NorthwindContext(_northwindOptions); + var ctx = new NorthwindContext(_options); ctx.IsSoftDeleteFilterEnabled = enableFilter; //ctx.Database.EnsureDeleted(); if (ctx.Database.EnsureCreated()) @@ -96,23 +76,6 @@ private NorthwindContext CreateContext(bool enableFilter) return ctx; } - private InheritanceContext CreateInheritanceContext() - { - var recreate = _inheritanceOptions == null; - - if (_inheritanceOptions == null) - _inheritanceOptions = CreateInheritanceOptions(); - - var ctx = new InheritanceContext(_inheritanceOptions); - if (recreate) - { - ctx.Database.EnsureDeleted(); - ctx.Database.EnsureCreated(); - } - - return ctx; - } - public class VwProductAndDescription { public int ProductId { get; set; } @@ -207,7 +170,7 @@ orderby pd.ProductId [Test] public void TestCreateFromOptions() { - using (var db = _northwindOptions.CreateLinqToDbConnection()) + using (var db = _options.CreateLinqToDbConnection()) { } } @@ -226,19 +189,19 @@ public void TestFunctions() // Date = Model.TestFunctions.GetDate(), // Len = Model.TestFunctions.Len(p.Name), DiffYear1 = EF.Functions.DateDiffYear(p.ShippedDate, p.OrderDate), - DiffYear2 = p.OrderDate == null ? (int?)null : EF.Functions.DateDiffYear(p.ShippedDate, p.OrderDate.Value), + DiffYear2 = p.OrderDate == null ? null : EF.Functions.DateDiffYear(p.ShippedDate, p.OrderDate.Value), DiffMonth1 = EF.Functions.DateDiffMonth(p.ShippedDate, p.OrderDate), - DiffMonth2 = p.OrderDate == null ? (int?)null : EF.Functions.DateDiffMonth(p.ShippedDate, p.OrderDate.Value), + DiffMonth2 = p.OrderDate == null ? null : EF.Functions.DateDiffMonth(p.ShippedDate, p.OrderDate.Value), DiffDay1 = EF.Functions.DateDiffDay(p.ShippedDate, p.OrderDate), - DiffDay2 = p.OrderDate == null ? (int?)null : EF.Functions.DateDiffDay(p.ShippedDate, p.OrderDate.Value), + DiffDay2 = p.OrderDate == null ? null : EF.Functions.DateDiffDay(p.ShippedDate, p.OrderDate.Value), DiffHour1 = EF.Functions.DateDiffHour(p.ShippedDate, p.OrderDate), - DiffHour2 = p.OrderDate == null ? (int?)null : EF.Functions.DateDiffHour(p.ShippedDate, p.OrderDate.Value), + DiffHour2 = p.OrderDate == null ? null : EF.Functions.DateDiffHour(p.ShippedDate, p.OrderDate.Value), DiffMinute1 = EF.Functions.DateDiffMinute(p.ShippedDate, p.OrderDate), - DiffMinute2 = p.OrderDate == null ? (int?)null : EF.Functions.DateDiffMinute(p.ShippedDate, p.OrderDate.Value), + DiffMinute2 = p.OrderDate == null ? null : EF.Functions.DateDiffMinute(p.ShippedDate, p.OrderDate.Value), DiffSecond1 = EF.Functions.DateDiffSecond(p.ShippedDate, p.OrderDate), - DiffSecond2 = p.OrderDate == null ? (int?)null : EF.Functions.DateDiffSecond(p.ShippedDate, p.OrderDate.Value), + DiffSecond2 = p.OrderDate == null ? null : EF.Functions.DateDiffSecond(p.ShippedDate, p.OrderDate.Value), DiffMillisecond1 = EF.Functions.DateDiffMillisecond(p.ShippedDate, p.ShippedDate!.Value.AddMilliseconds(100)), - DiffMillisecond2 = p.OrderDate == null ? (int?)null : EF.Functions.DateDiffMillisecond(p.ShippedDate, p.ShippedDate.Value.AddMilliseconds(100)), + DiffMillisecond2 = p.OrderDate == null ? null : EF.Functions.DateDiffMillisecond(p.ShippedDate, p.ShippedDate.Value.AddMilliseconds(100)), }; // var items1 = query.ToArray(); @@ -571,7 +534,7 @@ public async Task TestChangeTracker([Values(true, false)] bool enableFilter) orderDetail.UnitPrice = orderDetail.UnitPrice * 1.1m; ctx.ChangeTracker.DetectChanges(); - var changedEntry = ctx.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).Single(); + var changedEntry = ctx.ChangeTracker.Entries().Single(e => e.State == EntityState.Modified); ctx.SaveChanges(); } } @@ -594,7 +557,7 @@ public async Task TestChangeTrackerDisabled1([Values(true, false)] bool enableFi orderDetail.UnitPrice = orderDetail.UnitPrice * 1.1m; ctx.ChangeTracker.DetectChanges(); - var changedEntry = ctx.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).SingleOrDefault(); + var changedEntry = ctx.ChangeTracker.Entries().SingleOrDefault(e => e.State == EntityState.Modified); Assert.AreEqual(changedEntry, null); ctx.SaveChanges(); } @@ -620,7 +583,7 @@ public async Task TestChangeTrackerDisabled2([Values(true, false)] bool enableFi orderDetail.UnitPrice = orderDetail.UnitPrice * 1.1m; ctx.ChangeTracker.DetectChanges(); - var changedEntry = ctx.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).SingleOrDefault(); + var changedEntry = ctx.ChangeTracker.Entries().SingleOrDefault(e => e.State == EntityState.Modified); Assert.AreEqual(changedEntry, null); ctx.SaveChanges(); } @@ -631,23 +594,6 @@ public async Task TestChangeTrackerDisabled2([Values(true, false)] bool enableFi } } - [Test] - public async Task TestChangeTrackerTemporaryTable([Values(true, false)] bool enableFilter) - { - using var ctx = CreateContext(enableFilter); - - var query = ctx.Orders; - - using var db = ctx.CreateLinqToDbConnection(); - - using var temp = await db.CreateTempTableAsync(query, tableName: "#Orders"); - - var result = temp.Take(2).ToList(); - - ctx.Orders.Local.Should().BeEmpty(); - } - - [Test] public void NavigationProperties() { @@ -890,46 +836,6 @@ public void TestTagWith([Values(true, false)] bool enableFilter) str.Should().Contain("Tagged query"); } } - - [Test] - public void TestInheritanceBulkCopy([Values] BulkCopyType copyType) - { - using (var ctx = CreateInheritanceContext()) - { - var data = new BlogBase[] { new Blog() { Url = "BlogUrl" }, new RssBlog() { Url = "RssUrl" } }; - - ctx.BulkCopy(new BulkCopyOptions(){ BulkCopyType = BulkCopyType.RowByRow }, data); - - var items = ctx.Blogs.ToArray(); - - items[0].Should().BeOfType(); - ((Blog)items[0]).Url.Should().Be("BlogUrl"); - - items[1].Should().BeOfType(); - ((RssBlog)items[1]).Url.Should().Be("RssUrl"); - } - } - - /* - [Test] - public void TestInheritanceShadowBulkCopy([Values] BulkCopyType copyType) - { - using (var ctx = CreateInheritanceContext()) - { - var data = new ShadowBlogBase[] { new ShadowBlog() { Url = "BlogUrl" }, new ShadowRssBlog() { Url = "RssUrl" } }; - - ctx.BulkCopy(new BulkCopyOptions(){ BulkCopyType = BulkCopyType.RowByRow }, data); - - var items = ctx.ShadowBlogs.ToArray(); - - items[0].Should().BeOfType(); - ((ShadowBlog)items[0]).Url.Should().Be("BlogUrl"); - - items[1].Should().BeOfType(); - ((ShadowRssBlog)items[1]).Url.Should().Be("RssUrl"); - } - } - */ } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ValueConversion/ConvertorTests.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ValueConversion/ConvertorTests.cs index c776ff4..327968d 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ValueConversion/ConvertorTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ValueConversion/ConvertorTests.cs @@ -29,7 +29,7 @@ public ConvertorTests() optionsBuilder .ReplaceService() - .UseSqlServer("Server=.;Database=ConverterTests;Integrated Security=SSPI") + .UseSqlServer("Server=.;Database=ConverterTests;Integrated Security=SSPI;Encrypt=true;TrustServerCertificate=true") .UseLoggerFactory(TestUtils.LoggerFactory);; _options = optionsBuilder.Options; @@ -58,7 +58,7 @@ public void TestToList() var ef = ctx.Subdivisions.Where(s => s.Id == 1L).ToArray(); var ltdb = ctx.Subdivisions.ToLinqToDB().Where(s => s.Id == 1L).ToArray(); - var id = new Nullable>(0L.AsId()); + var id = new Id?(0L.AsId()); var ltdb2 = ctx.Subdivisions.ToLinqToDB().Where(s => s.Id == id).ToArray(); var ids = new[] {1L.AsId(), 2L.AsId(),}; diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ValueConversion/IEntity`1.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ValueConversion/IEntity`1.cs index 74a3617..8137ee0 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ValueConversion/IEntity`1.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ValueConversion/IEntity`1.cs @@ -4,5 +4,4 @@ public interface IEntity { public TKey Id { get; } } - } diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ef9c72c..fc53f15 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,8 +1,8 @@ variables: solution: 'linq2db.EFCore.sln' build_configuration: 'Release' - assemblyVersion: 5.13.0 - nugetVersion: 5.13.0 + assemblyVersion: 7.0.0 + nugetVersion: 7.0.0 artifact_nugets: 'nugets' # build on commits to important branches (master + release branches): @@ -32,6 +32,12 @@ stages: steps: + + - task: UseDotNet@2 + displayName: 'Install .NET 7' + inputs: + version: 7.x + - task: PowerShell@2 inputs: filePath: '$(Build.SourcesDirectory)/Build/SetVersion.ps1' diff --git a/linq2db.EFCore.sln b/linq2db.EFCore.sln index 2cf6bb7..53d666c 100644 --- a/linq2db.EFCore.sln +++ b/linq2db.EFCore.sln @@ -11,7 +11,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A3F30061 .gitignore = .gitignore azure-pipelines.yml = azure-pipelines.yml Directory.Packages.props = Directory.Packages.props - global.json = global.json Build\linq2db.Default.props = Build\linq2db.Default.props Build\linq2db.snk = Build\linq2db.snk Build\linq2db.Tests.props = Build\linq2db.Tests.props @@ -41,7 +40,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LinqToDB.EntityFrameworkCor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LinqToDB.EntityFrameworkCore.SQLite.Tests", "Tests\LinqToDB.EntityFrameworkCore.SQLite.Tests\LinqToDB.EntityFrameworkCore.SQLite.Tests.csproj", "{615C5697-5FA7-490C-8812-3D61994A8AC1}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "LinqToDB.EntityFrameworkCore.FSharpTests", "Tests\LinqToDB.EntityFrameworkCore.FSharpTests\LinqToDB.EntityFrameworkCore.FSharpTests.fsproj", "{ECF4637B-1C93-4D87-BDF2-E7F4DF7ED5C9}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "LinqToDB.EntityFrameworkCore.FSharpTests", "Tests\LinqToDB.EntityFrameworkCore.FSharpTests\LinqToDB.EntityFrameworkCore.FSharpTests.fsproj", "{ECF4637B-1C93-4D87-BDF2-E7F4DF7ED5C9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution