From ebe011a6f1b2a2a9709fe558cfc7ed3215b55c37 Mon Sep 17 00:00:00 2001 From: Laurents Meyer Date: Mon, 3 May 2021 01:38:40 +0200 Subject: [PATCH] Upgrade to EF Core 6.0.0-preview4 (#1416) * Migrate to EF Core 6.0.0-preview4. * Fix MySqlMigrationsModelDiffer. * Fix MySqlSqlTranslatingExpressionVisitor (NotTranslatedExpressionType after visiting a SqlBinaryExpression). * Fix MySqlSqlTranslatingExpressionVisitor. * Implement support to return a single byte from a byte array/binary column by index and First() extension method. * Implement explicit datetime/timestamp, date and time literals. * Implement SQL Server based workaround for EXISTS(...LIMIT 0 OFFSET 0) bug in MySQL (MariaDB works fine). * Fix tests. * Implement MySqlNetTopologySuiteApiConsistencyTest. * Implement MySqlApiConsistencyTest. * Setup CI usage of .NET Core preview release. * Skip failing FromSqlQuery test cases, until https://github.com/dotnet/efcore/pull/24806 has been merged. * Implement FieldsOnlyLoadMySqlTest. * Implement DesignTimeMySqlTest. * Implement ManyToManyFieldsLoadMySqlTest. * Implement MySqlUpdateSqlGeneratorTest. * Annotate tests, that are not supported for MariaDB. * Fix tests with inaccurate orderings. (Should be fixed in EF Core.) * Annotate tests, that require window functions support (relevant for MySQL < 8.0.0). --- Dependencies.targets | 61 +- Directory.Build.props | 4 +- NuGet.config | 7 +- Pomelo.EFCore.MySql.sln | 1 + Version.props | 22 +- azure-pipelines.yml | 117 ++- dotnet-tools.json | 2 +- global.json | 6 +- .../EFCore.MySql.Json.Microsoft.csproj | 2 +- .../MySqlJsonMicrosoftPropertyExtensions.cs | 4 +- .../MySqlJsonMicrosoftValueComparer.cs | 4 +- .../EFCore.MySql.Json.Newtonsoft.csproj | 2 +- .../MySqlJsonNewtonsoftPropertyExtensions.cs | 4 +- src/EFCore.MySql.NTS/EFCore.MySql.NTS.csproj | 2 +- ...qlDbFunctionsExtensionsMethodTranslator.cs | 2 +- ...MySqlGeometryCollectionMemberTranslator.cs | 2 +- ...MySqlGeometryCollectionMethodTranslator.cs | 2 +- .../Internal/MySqlGeometryMemberTranslator.cs | 2 +- .../Internal/MySqlGeometryMethodTranslator.cs | 2 +- .../MySqlLineStringMemberTranslator.cs | 2 +- .../MySqlLineStringMethodTranslator.cs | 2 +- .../MySqlMultiLineStringMemberTranslator.cs | 2 +- ...opologySuiteEvaluatableExpressionFilter.cs | 2 +- .../Internal/MySqlPolygonMemberTranslator.cs | 2 +- .../Internal/MySqlPolygonMethodTranslator.cs | 2 +- .../Internal/MySqlDesignTimeServices.cs | 23 +- src/EFCore.MySql/EFCore.MySql.csproj | 3 +- .../MySqlEntityTypeBuilderExtensions.cs | 13 + .../Extensions/MySqlEntityTypeExtensions.cs | 14 +- .../Extensions/MySqlIndexBuilderExtensions.cs | 50 ++ .../Extensions/MySqlIndexExtensions.cs | 48 +- .../Extensions/MySqlModelBuilderExtensions.cs | 13 + .../Extensions/MySqlModelExtensions.cs | 40 +- .../MySqlPropertyBuilderExtensions.cs | 45 + .../Extensions/MySqlPropertyExtensions.cs | 91 +- src/EFCore.MySql/Infrastructure/CharSet.cs | 8 +- .../Internal/MySqlJsonOptionsExtension.cs | 4 +- .../Internal/MySqlOptionsExtension.cs | 38 +- .../MySqlDefaultDataTypeMappings.cs | 18 +- .../Infrastructure/MySqlServerVersion.cs | 1 + .../Infrastructure/ServerVersionSupport.cs | 3 +- src/EFCore.MySql/Internal/MySqlOptions.cs | 2 +- .../MySqlValueGenerationConvention.cs | 2 +- .../Internal/MySqlMigrationsModelDiffer.cs | 26 +- .../Migrations/MySqlMigrationsSqlGenerator.cs | 9 +- .../MySqlByteArrayMethodTranslator.cs | 48 +- .../Internal/MySqlConvertTranslator.cs | 2 +- ...qlDbFunctionsExtensionsMethodTranslator.cs | 2 +- .../Internal/MySqlRegexIsMatchTranslator.cs | 2 +- .../MySqlStringComparisonMethodTranslator.cs | 12 +- .../Internal/MySqlQuerySqlGenerator.cs | 8 +- .../MySqlSqlTranslatingExpressionVisitor.cs | 68 +- .../MySqlComplexFunctionArgumentExpression.cs | 2 +- .../Internal/MySqlJsonArrayIndexExpression.cs | 2 +- .../Query/Internal/MySqlCommandParser.cs | 8 +- .../Internal/MySqlMathMethodTranslator.cs | 2 +- .../MySqlParameterBasedSqlProcessor.cs | 28 +- .../Internal/MySqlSqlExpressionFactory.cs | 6 +- .../SkipTakeCollapsingExpressionVisitor.cs | 89 ++ .../Internal/MySqlDatabaseModelFactory.cs | 2 +- .../IDefaultValueCompatibilityAware.cs | 17 + .../Internal/MySqlByteArrayTypeMapping.cs | 1 - .../Internal/MySqlConnectionSettings.cs | 2 +- .../Storage/Internal/MySqlDatabaseCreator.cs | 12 +- .../MySqlDateTimeOffsetTypeMapping.cs | 25 +- .../Internal/MySqlDateTimeTypeMapping.cs | 26 +- .../Storage/Internal/MySqlDateTypeMapping.cs | 29 +- .../Storage/Internal/MySqlGuidTypeMapping.cs | 2 +- .../Storage/Internal/MySqlJsonTypeMapping.cs | 2 +- .../MySqlJsonTypeMappingSourcePlugin.cs | 2 +- .../Internal/MySqlRelationalConnection.cs | 10 +- .../MySqlScaffoldingConnectionSettings.cs | 10 +- .../Internal/MySqlStringTypeMapping.cs | 4 +- .../Internal/MySqlTimeSpanTypeMapping.cs | 29 +- .../Internal/MySqlModificationCommandBatch.cs | 5 +- .../Internal/MySqlUpdateSqlGenerator.cs | 6 - .../MySqlSequentialGuidValueGenerator.cs | 4 +- .../AssemblyInfo.cs | 2 + .../BuiltInDataTypesMySqlTest.cs | 2 +- .../ConcurrencyDetectorDisabledMySqlTest.cs | 45 + .../ConcurrencyDetectorEnabledMySqlTest.cs | 42 + .../ConcurrencyDetectorMySqlTest.cs | 14 - .../DataAnnotationMySqlTest.cs | 12 +- .../DesignTimeMySqlTest.cs | 25 + .../EFCore.MySql.FunctionalTests.csproj | 5 +- .../MigrationsInfrastructureMySqlTest.cs | 3 +- .../MigrationsMySqlTest.cs | 11 +- .../MigrationsSqlGeneratorTestBase.cs | 806 ------------------ ...> MonsterFixupChangedChangingMySqlTest.cs} | 10 +- .../MySqlApiConsistencyTest.cs | 94 ++ .../MySqlMigrationsSqlGeneratorTest.cs | 39 +- ...MySqlNetTopologySuiteApiConsistencyTest.cs | 31 + .../OptimisticConcurrencyMySqlTest.cs | 6 +- .../PropertyEntryMySqlTest.cs | 38 - .../Query/AsyncFromSqlQueryMySqlTest.cs | 15 - .../Query/AsyncGearsOfWarQueryMySqlTest.cs | 18 - .../Query/ComplexNavigationsQueryMySqlTest.cs | 30 +- ...lexNavigationsSharedTypeQueryMySqlTest.cs} | 104 ++- ...ComplexNavigationsWeakQueryMySqlFixture.cs | 12 - .../Query/FieldsOnlyLoadMySqlTest.cs | 20 + .../Query/FromSqlQueryMySqlTest.cs | 41 +- .../Query/GearsOfWarQueryMySqlTest.cs | 102 +++ .../Query/JsonPocoQueryTestBase.cs | 3 +- .../Query/ManyToManyFieldsLoadMySqlTest.cs | 46 + .../NorthwindAsyncSimpleQueryMySqlTest.cs | 36 - .../Query/NorthwindFunctionsQueryMySqlTest.cs | 40 +- .../Query/NorthwindGroupByQueryMySqlTest.cs | 6 + ...orthwindIncludeNoTrackingQueryMySqlTest.cs | 13 + .../Query/NorthwindIncludeQueryMySqlTest.cs | 13 + .../NorthwindMiscellaneousQueryMySqlTest.cs | 36 +- .../NorthwindQueryFiltersQueryMySqlTest.cs | 7 +- .../Query/NorthwindSelectQueryMySqlTest.cs | 66 +- ...indSplitIncludeNoTrackingQueryMySqlTest.cs | 13 + .../NorthwindSplitIncludeQueryMySqlTest.cs | 13 + .../NorthwindStringIncludeQueryMySqlTest.cs | 13 + .../Query/NorthwindWhereQueryMySqlTest.cs | 23 +- .../QueryFilterFuncletizationMySqlTest.cs | 38 +- .../Query/TPTGearsOfWarQueryMySqlTest.cs | 102 +++ .../SeedingMySqlTest.cs | 13 +- .../Update/MySqlUpdateSqlGeneratorTest.cs | 235 +++++ .../UpdatesMySqlTest.MySql.cs | 41 - .../Commands/CommandRunner.cs | 6 +- .../Commands/TestMigrateCommand.cs | 123 ++- .../EFCore.MySql.IntegrationTests.csproj | 23 +- .../Properties/launchSettings.json | 1 + .../scripts/scaffold.ps1 | 2 +- .../EFCore.MySql.Tests.csproj | 4 +- .../Migrations/ModelSnapshotMySqlTest.cs | 257 ------ .../FakeProvider/FakeRelationalConnection.cs | 62 +- .../FakeRelationalCommandDiagnosticsLogger.cs | 220 +++++ .../TestModificationCommandBatchFactory.cs | 13 +- 131 files changed, 2384 insertions(+), 1789 deletions(-) create mode 100644 src/EFCore.MySql/Query/Internal/SkipTakeCollapsingExpressionVisitor.cs create mode 100644 src/EFCore.MySql/Storage/Internal/IDefaultValueCompatibilityAware.cs create mode 100644 test/EFCore.MySql.FunctionalTests/ConcurrencyDetectorDisabledMySqlTest.cs create mode 100644 test/EFCore.MySql.FunctionalTests/ConcurrencyDetectorEnabledMySqlTest.cs delete mode 100644 test/EFCore.MySql.FunctionalTests/ConcurrencyDetectorMySqlTest.cs create mode 100644 test/EFCore.MySql.FunctionalTests/DesignTimeMySqlTest.cs delete mode 100644 test/EFCore.MySql.FunctionalTests/MigrationsSqlGeneratorTestBase.cs rename test/EFCore.MySql.FunctionalTests/{MonsterFixupChangedOnlyMySqlTest.cs => MonsterFixupChangedChangingMySqlTest.cs} (64%) create mode 100644 test/EFCore.MySql.FunctionalTests/MySqlApiConsistencyTest.cs create mode 100644 test/EFCore.MySql.FunctionalTests/MySqlNetTopologySuiteApiConsistencyTest.cs delete mode 100644 test/EFCore.MySql.FunctionalTests/PropertyEntryMySqlTest.cs delete mode 100644 test/EFCore.MySql.FunctionalTests/Query/AsyncFromSqlQueryMySqlTest.cs delete mode 100644 test/EFCore.MySql.FunctionalTests/Query/AsyncGearsOfWarQueryMySqlTest.cs rename test/EFCore.MySql.FunctionalTests/Query/{ComplexNavigationsWeakQueryMySqlTest.cs => ComplexNavigationsSharedTypeQueryMySqlTest.cs} (81%) delete mode 100644 test/EFCore.MySql.FunctionalTests/Query/ComplexNavigationsWeakQueryMySqlFixture.cs create mode 100644 test/EFCore.MySql.FunctionalTests/Query/FieldsOnlyLoadMySqlTest.cs create mode 100644 test/EFCore.MySql.FunctionalTests/Query/ManyToManyFieldsLoadMySqlTest.cs delete mode 100644 test/EFCore.MySql.FunctionalTests/Query/NorthwindAsyncSimpleQueryMySqlTest.cs create mode 100644 test/EFCore.MySql.FunctionalTests/Update/MySqlUpdateSqlGeneratorTest.cs delete mode 100644 test/EFCore.MySql.FunctionalTests/test/EFCore.MySql.FunctionalTests/UpdatesMySqlTest.MySql.cs delete mode 100644 test/EFCore.MySql.Tests/Migrations/ModelSnapshotMySqlTest.cs create mode 100644 test/EFCore.MySql.Tests/TestUtilities/FakeRelationalCommandDiagnosticsLogger.cs diff --git a/Dependencies.targets b/Dependencies.targets index d6f60fa95..8ff64dc83 100644 --- a/Dependencies.targets +++ b/Dependencies.targets @@ -1,7 +1,8 @@ - 5.0.5 - [$(DotnetRuntimeVersion), 6.0.0) + 6.0.0-preview.4.* + $(DotnetRuntimeVersion) + $(DotnetRuntimeVersion) @@ -10,38 +11,38 @@ - + - - - + + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Directory.Build.props b/Directory.Build.props index cc61d3cdc..8566d9826 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -8,7 +8,7 @@ Pomelo.EntityFrameworkCore.MySql Laurents Meyer, Caleb Lloyd, Yuko Zheng Pomelo Foundation - Copyright 2020 © Pomelo Foundation + Copyright 2021 © Pomelo Foundation https://avatars3.githubusercontent.com/u/19828814 icon.png true @@ -23,7 +23,7 @@ net5.0 - netcoreapp5.0 + net6.0 netstandard2.1 diff --git a/NuGet.config b/NuGet.config index dd1d34a7c..6986ec247 100644 --- a/NuGet.config +++ b/NuGet.config @@ -6,8 +6,11 @@ - - + + + + + diff --git a/Pomelo.EFCore.MySql.sln b/Pomelo.EFCore.MySql.sln index 2408dcf0d..3344d8121 100644 --- a/Pomelo.EFCore.MySql.sln +++ b/Pomelo.EFCore.MySql.sln @@ -23,6 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md dotnet-tools.json = dotnet-tools.json Dependencies.targets = Dependencies.targets + NuGet.config = NuGet.config EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.MySql", "src\EFCore.MySql\EFCore.MySql.csproj", "{FC2779F0-2A2A-4BE2-B5A8-FDA31A4A404A}" diff --git a/Version.props b/Version.props index 437bfcf98..c5981371c 100644 --- a/Version.props +++ b/Version.props @@ -2,15 +2,19 @@ - 5.0.1 - servicing - 1 + 6.0.0 + preview + 4 + + + $(LocalEFCoreRepository)\artifacts\bin\EFCore.Design.Tests\Debug\$(LegacyTargetFramework)\Microsoft.EntityFrameworkCore.dll @@ -55,20 +65,11 @@ $(LocalEFCoreRepository)\artifacts\bin\EFCore.Relational.Tests\Debug\$(LegacyTargetFramework)\Microsoft.EntityFrameworkCore.Specification.Tests.dll - - - - $(LocalMySqlConnectorRepository)\src\MySqlConnector\bin\Debug\$(TargetFramework)\MySqlConnector.dll + $(LocalMySqlConnectorRepository)\src\MySqlConnector\bin\Debug\$(DefaultNetCoreTargetFramework)\MySqlConnector.dll diff --git a/test/EFCore.MySql.IntegrationTests/Properties/launchSettings.json b/test/EFCore.MySql.IntegrationTests/Properties/launchSettings.json index b47a8bb37..2dc4e8111 100644 --- a/test/EFCore.MySql.IntegrationTests/Properties/launchSettings.json +++ b/test/EFCore.MySql.IntegrationTests/Properties/launchSettings.json @@ -17,6 +17,7 @@ }, "EFCore.MySql.IntegrationTests": { "commandName": "Project", + "commandLineArgs": "testMigrate", /* debug */ "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/test/EFCore.MySql.IntegrationTests/scripts/scaffold.ps1 b/test/EFCore.MySql.IntegrationTests/scripts/scaffold.ps1 index 3ba9f89a2..1678752e4 100644 --- a/test/EFCore.MySql.IntegrationTests/scripts/scaffold.ps1 +++ b/test/EFCore.MySql.IntegrationTests/scripts/scaffold.ps1 @@ -12,7 +12,7 @@ try Remove-Item -Recurse -Force $targetDirectoryName -ErrorAction Ignore mkdir $targetDirectoryName - $connectionString = dotnet run connectionString + $connectionString = (Select-String config.json -Pattern '(?<="ConnectionString":\s*")(.*?)(?=")').Matches.Value $arguments = "ef", "dbcontext", "scaffold", $connectionString, "Pomelo.EntityFrameworkCore.MySql", "--output-dir", $targetDirectoryName foreach ($table in $tables) diff --git a/test/EFCore.MySql.Tests/EFCore.MySql.Tests.csproj b/test/EFCore.MySql.Tests/EFCore.MySql.Tests.csproj index a2d875cc3..97a1cebc2 100644 --- a/test/EFCore.MySql.Tests/EFCore.MySql.Tests.csproj +++ b/test/EFCore.MySql.Tests/EFCore.MySql.Tests.csproj @@ -1,7 +1,7 @@  - $(DefaultNetCoreTargetFramework) + $(DefaultNetCoreLegacyTargetFramework) $(DefaultNetCoreLegacyTargetFramework) true Pomelo.EntityFrameworkCore.MySql.Tests @@ -73,7 +73,7 @@ - $(LocalMySqlConnectorRepository)\src\MySqlConnector\bin\Debug\$(TargetFramework)\MySqlConnector.dll + $(LocalMySqlConnectorRepository)\src\MySqlConnector\bin\Debug\$(DefaultNetCoreTargetFramework)\MySqlConnector.dll diff --git a/test/EFCore.MySql.Tests/Migrations/ModelSnapshotMySqlTest.cs b/test/EFCore.MySql.Tests/Migrations/ModelSnapshotMySqlTest.cs deleted file mode 100644 index b830f95cd..000000000 --- a/test/EFCore.MySql.Tests/Migrations/ModelSnapshotMySqlTest.cs +++ /dev/null @@ -1,257 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.EntityFrameworkCore.Design.Internal; -using Microsoft.EntityFrameworkCore.Diagnostics.Internal; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Conventions; -using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Migrations.Design; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Pomelo.EntityFrameworkCore.MySql.Design.Internal; -using Pomelo.EntityFrameworkCore.MySql.Diagnostics.Internal; -using Pomelo.EntityFrameworkCore.MySql.Internal; -using Pomelo.EntityFrameworkCore.MySql.Storage.Internal; -using Pomelo.EntityFrameworkCore.TestUtilities; -using Xunit; - -namespace Pomelo.EntityFrameworkCore.MySql.Migrations -{ - public class ModelSnapshotMySqlTest - { - [Fact(Skip = "2.1.0 test invalid with 2.2.0 codebase")] - public virtual void Column_types_for_some_string_properties_are_stored_in_the_snapshot() - { - Test( - builder => - { - builder.Entity(eb => - { - // Need to specify the type until EF#12212 is fixed - eb.Property(e => e.TypeJsonArray).HasColumnType("json"); - eb.Property(e => e.TypeJsonArrayN).HasColumnType("json"); - eb.Property(e => e.TypeJsonObject).HasColumnType("json"); - eb.Property(e => e.TypeJsonObjectN).HasColumnType("json"); - }); - }, - @"builder - .HasAnnotation(""Relational:MaxIdentifierLength"", 64); - -builder.Entity(""Pomelo.EntityFrameworkCore.MySql.Migrations.ModelSnapshotMySqlTest+DataTypesVariable"", b => - { - b.Property(""Id"") - .ValueGeneratedOnAdd(); - - b.Property(""TypeByteArray"") - .IsRequired(); - - b.Property(""TypeByteArray255"") - .IsRequired() - .HasMaxLength(255); - - b.Property(""TypeByteArray255N"") - .HasMaxLength(255); - - b.Property(""TypeByteArrayN""); - - b.Property(""TypeJsonArray"") - .IsRequired() - .HasColumnType(""json""); - - b.Property(""TypeJsonArrayN"") - .HasColumnType(""json""); - - b.Property(""TypeJsonObject"") - .IsRequired() - .HasColumnType(""json""); - - b.Property(""TypeJsonObjectN"") - .HasColumnType(""json""); - - b.Property(""TypeString"") - .IsRequired(); - - b.Property(""TypeString255"") - .IsRequired() - .HasMaxLength(255); - - b.Property(""TypeString255N"") - .HasMaxLength(255); - - b.Property(""TypeStringN""); - - b.HasKey(""Id""); - - b.ToTable(""DataTypesVariable""); - }); -", - o => { Assert.Null(o.GetEntityTypes().First().FindProperty("Id")[CoreAnnotationNames.ValueGeneratorFactory]); } - ); - } - - public class DataTypesVariable - { - public int Id { get; set; } - - // string not null - [Required] - public string TypeString { get; set; } - - [Required] - [MaxLength(255)] - public string TypeString255 { get; set; } - - // string null - public string TypeStringN { get; set; } - - [MaxLength(255)] - public string TypeString255N { get; set; } - - - // binary not null - [Required] - [MaxLength(255)] - public byte[] TypeByteArray255 { get; set; } - - [Required] - public byte[] TypeByteArray { get; set; } - - // binary null - [MaxLength(255)] - public byte[] TypeByteArray255N { get; set; } - - public byte[] TypeByteArrayN { get; set; } - - - // json not null - [Required] - public List TypeJsonArray { get; set; } - - [Required] - public Dictionary TypeJsonObject { get; set; } - - // json null - public List TypeJsonArrayN { get; set; } - - public Dictionary TypeJsonObjectN { get; set; } - } - - protected virtual ICollection GetReferences() => new List - { - BuildReference.ByName("Microsoft.EntityFrameworkCore"), - BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational"), - BuildReference.ByName("Pomelo.EntityFrameworkCore.MySql") - }; - - protected void Test(Action buildModel, string expectedCode, Action assert) - { - var modelBuilder = CreateConventionalModelBuilder(); - modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.Snapshot); - buildModel(modelBuilder); - - var typeMappingSource = new MySqlTypeMappingSource( - TestServiceFactory.Instance.Create(), - TestServiceFactory.Instance.Create(), - TestServiceFactory.Instance.Create()); - - var modelValidator = CreateModelValidator(typeMappingSource); - modelValidator.Validate( - modelBuilder.Model, - new DiagnosticsLogger( - new ListLoggerFactory(category => category == DbLoggerCategory.Model.Validation.Name), - new LoggingOptions(), - new DiagnosticListener("Fake"), - new MySqlLoggingDefinitions(), - new NullDbContextLogger())); - - var model = modelBuilder.Model; - - var codeHelper = new CSharpHelper( - typeMappingSource); - - var annotationCodeGenerator = new MySqlAnnotationCodeGenerator( - new AnnotationCodeGeneratorDependencies(typeMappingSource)); - - var generator = new CSharpMigrationsGenerator( - new MigrationsCodeGeneratorDependencies( - typeMappingSource, - annotationCodeGenerator), - new CSharpMigrationsGeneratorDependencies( - codeHelper, - new CSharpMigrationOperationGenerator( - new CSharpMigrationOperationGeneratorDependencies( - codeHelper)), - new CSharpSnapshotGenerator( - new CSharpSnapshotGeneratorDependencies( - codeHelper, - typeMappingSource, - annotationCodeGenerator)))); - - var code = generator.GenerateSnapshot("RootNamespace", typeof(DbContext), "Snapshot", model); - - Assert.Equal(expectedCode, code, ignoreLineEndingDifferences: true); - - var build = new BuildSource - { - Sources = - { - @" - using System; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Metadata; - using Microsoft.EntityFrameworkCore.Metadata.Conventions; - using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - - public static class ModelSnapshot - { - public static IModel Model - { - get - { - var builder = new ModelBuilder(new ConventionSet()); - " + code + @" - - return builder.Model; - } - } - } - " - } - }; - - foreach (var buildReference in GetReferences()) - { - build.References.Add(buildReference); - } - - var assembly = build.BuildInMemory(); - var factoryType = assembly.GetType("ModelSnapshot"); - var property = factoryType.GetTypeInfo().GetDeclaredProperty("Model"); - var value = (IModel)property.GetValue(null); - - Assert.NotNull(value); - assert(value); - } - - protected ModelBuilder CreateConventionalModelBuilder() => new ModelBuilder(MySqlConventionSetBuilder.Build()); - - protected ModelValidator CreateModelValidator(IRelationalTypeMappingSource typeMappingSource) - { - return new RelationalModelValidator( - new ModelValidatorDependencies( - typeMappingSource, - new MemberClassifier( - typeMappingSource, - TestServiceFactory.Instance.Create())), - new RelationalModelValidatorDependencies(typeMappingSource)); - } - } -} diff --git a/test/EFCore.MySql.Tests/TestUtilities/FakeProvider/FakeRelationalConnection.cs b/test/EFCore.MySql.Tests/TestUtilities/FakeProvider/FakeRelationalConnection.cs index df67f6fbb..92bfa2805 100644 --- a/test/EFCore.MySql.Tests/TestUtilities/FakeProvider/FakeRelationalConnection.cs +++ b/test/EFCore.MySql.Tests/TestUtilities/FakeProvider/FakeRelationalConnection.cs @@ -4,9 +4,9 @@ using System.Collections.Generic; using System.Data.Common; using System.Diagnostics; -using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.Extensions.Logging; @@ -17,25 +17,61 @@ public class FakeRelationalConnection : RelationalConnection { private DbConnection _connection; - private readonly List _dbConnections = new List(); + private readonly List _dbConnections = new(); - public FakeRelationalConnection(IDbContextOptions options) + public FakeRelationalConnection(IDbContextOptions options = null) : base( new RelationalConnectionDependencies( - options, - new FakeDiagnosticsLogger(), - new FakeDiagnosticsLogger(), - new NamedConnectionStringResolver(options), - new RelationalTransactionFactory(new RelationalTransactionFactoryDependencies()), - null)) + options ?? CreateOptions(), + new DiagnosticsLogger( + new LoggerFactory(), + new LoggingOptions(), + new DiagnosticListener("FakeDiagnosticListener"), + new TestRelationalLoggingDefinitions(), + new NullDbContextLogger()), + new RelationalConnectionDiagnosticsLogger( + new LoggerFactory(), + new LoggingOptions(), + new DiagnosticListener("FakeDiagnosticListener"), + new TestRelationalLoggingDefinitions(), + new NullDbContextLogger(), + CreateOptions()), + new NamedConnectionStringResolver(options ?? CreateOptions()), + new RelationalTransactionFactory( + new RelationalTransactionFactoryDependencies( + new RelationalSqlGenerationHelper( + new RelationalSqlGenerationHelperDependencies()))), + new CurrentDbContext(new FakeDbContext()), + new RelationalCommandBuilderFactory( + new RelationalCommandBuilderDependencies( + new TestRelationalTypeMappingSource( + TestServiceFactory.Instance.Create(), + TestServiceFactory.Instance.Create()))))) { } - public void UseConnection(DbConnection connection) => _connection = connection; + private class FakeDbContext : DbContext + { + } + + private static IDbContextOptions CreateOptions() + { + var optionsBuilder = new DbContextOptionsBuilder(); + + // ((IDbContextOptionsBuilderInfrastructure)optionsBuilder) + // .AddOrUpdateExtension(new FakeRelationalOptionsExtension().WithConnectionString("Database=Dummy")); + + return optionsBuilder.Options; + } + + public void UseConnection(DbConnection connection) + => _connection = connection; - public override DbConnection DbConnection => _connection ?? base.DbConnection; + public override DbConnection DbConnection + => _connection ?? base.DbConnection; - public IReadOnlyList DbConnections => _dbConnections; + public IReadOnlyList DbConnections + => _dbConnections; protected override DbConnection CreateDbConnection() { diff --git a/test/EFCore.MySql.Tests/TestUtilities/FakeRelationalCommandDiagnosticsLogger.cs b/test/EFCore.MySql.Tests/TestUtilities/FakeRelationalCommandDiagnosticsLogger.cs new file mode 100644 index 000000000..9e5e50094 --- /dev/null +++ b/test/EFCore.MySql.Tests/TestUtilities/FakeRelationalCommandDiagnosticsLogger.cs @@ -0,0 +1,220 @@ + // Copyright (c) .NET Foundation. All rights reserved. + // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + + using System; + using System.Data.Common; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.EntityFrameworkCore.Diagnostics; + using Microsoft.EntityFrameworkCore.Storage; + + #nullable enable + + namespace Microsoft.EntityFrameworkCore.TestUtilities + { + public class FakeRelationalCommandDiagnosticsLogger + : FakeDiagnosticsLogger, IRelationalCommandDiagnosticsLogger + { + public InterceptionResult CommandCreating( + IRelationalConnection connection, + DbCommandMethod commandMethod, + DbContext? context, + Guid commandId, + Guid connectionId, + DateTimeOffset startTime) + => default; + + public DbCommand CommandCreated( + IRelationalConnection connection, + DbCommand command, + DbCommandMethod commandMethod, + DbContext? context, + Guid commandId, + Guid connectionId, + DateTimeOffset startTime, + TimeSpan duration) + => command; + + public InterceptionResult CommandReaderExecuting( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + DateTimeOffset startTime) + => default; + + public InterceptionResult CommandScalarExecuting( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + DateTimeOffset startTime) + => default; + + /// + /// Logs for the event. + /// + /// The connection. + /// The database command object. + /// The currently being used, to null if not known. + /// The correlation ID associated with the given . + /// The correlation ID associated with the being used. + /// The time that execution began. + /// An intercepted result. + public InterceptionResult CommandNonQueryExecuting( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + DateTimeOffset startTime) + => default; + + public ValueTask> CommandReaderExecutingAsync( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + DateTimeOffset startTime, + CancellationToken cancellationToken = default) + => default; + + public ValueTask> CommandScalarExecutingAsync( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + DateTimeOffset startTime, + CancellationToken cancellationToken = default) + => default; + + public ValueTask> CommandNonQueryExecutingAsync( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + DateTimeOffset startTime, + CancellationToken cancellationToken = default) + => default; + + public DbDataReader CommandReaderExecuted( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + DbDataReader methodResult, + DateTimeOffset startTime, + TimeSpan duration) + => methodResult; + + public object? CommandScalarExecuted( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + object? methodResult, + DateTimeOffset startTime, + TimeSpan duration) + => methodResult; + + public int CommandNonQueryExecuted( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + int methodResult, + DateTimeOffset startTime, + TimeSpan duration) + => methodResult; + + public ValueTask CommandReaderExecutedAsync( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + DbDataReader methodResult, + DateTimeOffset startTime, + TimeSpan duration, + CancellationToken cancellationToken = default) + => new(methodResult); + + public ValueTask CommandScalarExecutedAsync( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + object? methodResult, + DateTimeOffset startTime, + TimeSpan duration, + CancellationToken cancellationToken = default) + => new(methodResult); + + public ValueTask CommandNonQueryExecutedAsync( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + Guid commandId, + Guid connectionId, + int methodResult, + DateTimeOffset startTime, + TimeSpan duration, + CancellationToken cancellationToken = default) + => new(methodResult); + + public void CommandError( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + DbCommandMethod executeMethod, + Guid commandId, + Guid connectionId, + Exception exception, + DateTimeOffset startTime, + TimeSpan duration) + { + } + + public Task CommandErrorAsync( + IRelationalConnection connection, + DbCommand command, + DbContext? context, + DbCommandMethod executeMethod, + Guid commandId, + Guid connectionId, + Exception exception, + DateTimeOffset startTime, + TimeSpan duration, + CancellationToken cancellationToken = default) + => Task.CompletedTask; + + public InterceptionResult DataReaderDisposing( + IRelationalConnection connection, + DbCommand command, + DbDataReader dataReader, + Guid commandId, + int recordsAffected, + int readCount, + DateTimeOffset startTime, + TimeSpan duration) + => default; + + public bool ShouldLogCommandCreate(DateTimeOffset now) + => true; + + public bool ShouldLogCommandExecute(DateTimeOffset now) + => true; + + public bool ShouldLogDataReaderDispose(DateTimeOffset now) + => true; + } + } diff --git a/test/EFCore.MySql.Tests/TestUtilities/TestModificationCommandBatchFactory.cs b/test/EFCore.MySql.Tests/TestUtilities/TestModificationCommandBatchFactory.cs index bd090844c..92a5f46b4 100644 --- a/test/EFCore.MySql.Tests/TestUtilities/TestModificationCommandBatchFactory.cs +++ b/test/EFCore.MySql.Tests/TestUtilities/TestModificationCommandBatchFactory.cs @@ -33,13 +33,12 @@ public virtual ModificationCommandBatch Create() return new SingularModificationCommandBatch( new ModificationCommandBatchFactoryDependencies( - _commandBuilderFactory, - _sqlGenerationHelper, - _updateSqlGenerator, - _valueBufferFactoryFactory, - null, - new FakeDiagnosticsLogger() - )); + _commandBuilderFactory, + _sqlGenerationHelper, + _updateSqlGenerator, + _valueBufferFactoryFactory, + null, + new FakeRelationalCommandDiagnosticsLogger())); } } }