public void ModixContext_Always_ModelMatchesMigrationsSnapshot() { var optionsBuilder = new DbContextOptionsBuilder <ModixContext>() .UseNpgsql("Bogus connection string: we don't actually need to connect to the DB, just build ourselves a model."); var context = new ModixContext(optionsBuilder.Options); var migrationsAssembly = context.GetService <IMigrationsAssembly>(); var dependencies = context.GetService <ProviderConventionSetBuilderDependencies>(); var relationalDependencies = context.GetService <RelationalConventionSetBuilderDependencies>(); var modelDiffer = context.GetService <IMigrationsModelDiffer>(); var hasDifferences = false; if (migrationsAssembly.ModelSnapshot != null) { var typeMappingConvention = new TypeMappingConvention(dependencies); typeMappingConvention.ProcessModelFinalizing(((IConventionModel)migrationsAssembly.ModelSnapshot.Model).Builder, null !); var relationalModelConvention = new RelationalModelConvention(dependencies, relationalDependencies); var sourceModel = relationalModelConvention.ProcessModelFinalized(migrationsAssembly.ModelSnapshot.Model); hasDifferences = modelDiffer.HasDifferences( ((IMutableModel)sourceModel).FinalizeModel().GetRelationalModel(), context.Model.GetRelationalModel()); } hasDifferences.ShouldBeFalse(); }
public async Task PendingModelChangesTest() { var dummyConnectionString = "Host=localhost;Database=nxplx_db;Username=postgres;Password=dev"; var databaseContextOptions = new DbContextOptionsBuilder <DatabaseContext>().UseNpgsql(dummyConnectionString, b => b.MigrationsAssembly(typeof(DatabaseContext).Assembly.FullName)).Options; await using var databaseContext = new DatabaseContext(databaseContextOptions, new OperationContext()); var modelDiffer = databaseContext.GetService <IMigrationsModelDiffer>(); var migrationsAssembly = databaseContext.GetService <IMigrationsAssembly>(); var dependencies = databaseContext.GetService <ProviderConventionSetBuilderDependencies>(); var relationalDependencies = databaseContext.GetService <RelationalConventionSetBuilderDependencies>(); var typeMappingConvention = new TypeMappingConvention(dependencies); typeMappingConvention.ProcessModelFinalizing(((IConventionModel)migrationsAssembly.ModelSnapshot.Model).Builder, null); var relationalModelConvention = new RelationalModelConvention(dependencies, relationalDependencies); var sourceModel = relationalModelConvention.ProcessModelFinalized(migrationsAssembly.ModelSnapshot.Model); var finalSourceModel = ((IMutableModel)sourceModel).FinalizeModel().GetRelationalModel(); var finalTargetModel = databaseContext.Model.GetRelationalModel(); var differences = modelDiffer.GetDifferences(finalSourceModel, finalTargetModel); if (differences.Any()) { Assert.True(false, $"{differences.Count} changes between migrations and model. Debug this test for more details"); } Assert.Pass(); }
protected virtual void DiffSnapshot(ModelSnapshot snapshot, DbContext context) { var dependencies = context.GetService <ProviderConventionSetBuilderDependencies>(); var typeMappingConvention = new TypeMappingConvention(dependencies); typeMappingConvention.ProcessModelFinalizing(((IConventionModel)snapshot.Model).Builder, null); var relationalModelConvention = new RelationalModelConvention(); var sourceModel = relationalModelConvention.ProcessModelFinalized(snapshot.Model); var modelDiffer = context.GetService <IMigrationsModelDiffer>(); var operations = modelDiffer.GetDifferences(((IMutableModel)sourceModel).FinalizeModel(), context.Model); Assert.Equal(0, operations.Count); }
public void TestNoDbMigrationNeeded() { using var dbContext = new MemCheckDbContext(new DbContextOptionsBuilder <MemCheckDbContext>().UseSqlServer(@"Server=none;Database=none;Trusted_Connection=True;").Options); var relationalDependencies = dbContext.GetService <RelationalConventionSetBuilderDependencies>(); var relationalModelConvention = new RelationalModelConvention(dbContext.GetService <ProviderConventionSetBuilderDependencies>(), relationalDependencies); var modelSnapshot = (IConventionModel)dbContext.GetService <IMigrationsAssembly>().ModelSnapshot.Model; var finalizedSnapshotModel = relationalModelConvention.ProcessModelFinalized(modelSnapshot).GetRelationalModel(); var possiblyModifiedModel = dbContext.Model.GetRelationalModel(); var changes = dbContext.GetService <IMigrationsModelDiffer>().GetDifferences(finalizedSnapshotModel, possiblyModifiedModel); Assert.AreEqual(0, changes.Count, "A DB model update is needed - Run dotnet ef migrations add - " + string.Join(',', changes.Select(change => change.ToString()))); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual IModel Process(IModel model) { if (model == null) { return(null); } var version = model.GetProductVersion(); if (version != null) { ProcessElement(model, version); foreach (var entityType in model.GetEntityTypes()) { ProcessElement(entityType, version); ProcessCollection(entityType.GetProperties(), version); ProcessCollection(entityType.GetKeys(), version); ProcessCollection(entityType.GetIndexes(), version); foreach (var element in entityType.GetForeignKeys()) { ProcessElement(element, version); ProcessElement(element.DependentToPrincipal, version); ProcessElement(element.PrincipalToDependent, version); } } } if (model is IConventionModel conventionModel && _conventionDependencies != null) { var typeMappingConvention = new TypeMappingConvention(_conventionDependencies); typeMappingConvention.ProcessModelFinalizing(conventionModel.Builder, null); model = new RelationalModelConvention().ProcessModelFinalized(conventionModel); } return(model is IMutableModel mutableModel ? mutableModel.FinalizeModel() : model); }
private string GetMigrationStatus(DbContext context) { var relationalDatabaseCreator = context.GetService <IDatabaseCreator>() as IRelationalDatabaseCreator; if (relationalDatabaseCreator == null) { throw new Exception("Not a relational database, migrations are not supported"); } var databaseExists = relationalDatabaseCreator.Exists(); var migrationsAssembly = context.GetService <IMigrationsAssembly>(); var modelDiffer = context.GetService <IMigrationsModelDiffer>(); #if CORE50 var dependencies = context.GetService <ProviderConventionSetBuilderDependencies>(); var relationalDependencies = context.GetService <RelationalConventionSetBuilderDependencies>(); var hasDifferences = false; if (migrationsAssembly.ModelSnapshot != null) { var typeMappingConvention = new TypeMappingConvention(dependencies); typeMappingConvention.ProcessModelFinalizing(((IConventionModel)migrationsAssembly.ModelSnapshot.Model).Builder, null); var relationalModelConvention = new RelationalModelConvention(dependencies, relationalDependencies); var sourceModel = relationalModelConvention.ProcessModelFinalized(migrationsAssembly.ModelSnapshot.Model); hasDifferences = modelDiffer.HasDifferences( ((IMutableModel)sourceModel).FinalizeModel().GetRelationalModel(), context.Model.GetRelationalModel()); } var pendingModelChanges = (!databaseExists || hasDifferences); #else var pendingModelChanges = (!databaseExists || migrationsAssembly.ModelSnapshot != null) && modelDiffer.HasDifferences(migrationsAssembly.ModelSnapshot?.Model, context.Model); #endif if (pendingModelChanges) { return("Changes"); } var migrations = context.Database.GetMigrations().ToArray(); if (!migrations.Any()) { return("NoMigrations"); } var pendingMigrations = (databaseExists ? context.Database.GetPendingMigrations() : migrations) .ToArray(); if (pendingMigrations.Any()) { return("Pending"); } return("InSync"); }
private IMigrationsScaffolder CreateMigrationScaffolder <TContext>() where TContext : DbContext, new() { var currentContext = new CurrentDbContext(new TContext()); var idGenerator = new MigrationsIdGenerator(); var sqlServerTypeMappingSource = new SqlServerTypeMappingSource( TestServiceFactory.Instance.Create <TypeMappingSourceDependencies>(), TestServiceFactory.Instance.Create <RelationalTypeMappingSourceDependencies>()); var code = new CSharpHelper(sqlServerTypeMappingSource); var reporter = new TestOperationReporter(); var migrationAssembly = new MigrationsAssembly( currentContext, new DbContextOptions <TContext>().WithExtension(new FakeRelationalOptionsExtension()), idGenerator, new FakeDiagnosticsLogger <DbLoggerCategory.Migrations>()); var historyRepository = new MockHistoryRepository(); var services = RelationalTestHelpers.Instance.CreateContextServices(); IModel model = new Model(); model = new RelationalModelConvention().ProcessModelFinalized(model); return(new MigrationsScaffolder( new MigrationsScaffolderDependencies( currentContext, model, migrationAssembly, new MigrationsModelDiffer( new TestRelationalTypeMappingSource( TestServiceFactory.Instance.Create <TypeMappingSourceDependencies>(), TestServiceFactory.Instance.Create <RelationalTypeMappingSourceDependencies>()), new MigrationsAnnotationProvider(new MigrationsAnnotationProviderDependencies()), services.GetRequiredService <IChangeDetector>(), services.GetRequiredService <IUpdateAdapterFactory>(), services.GetRequiredService <CommandBatchPreparerDependencies>()), idGenerator, new MigrationsCodeGeneratorSelector( new[] { new CSharpMigrationsGenerator( new MigrationsCodeGeneratorDependencies(sqlServerTypeMappingSource), new CSharpMigrationsGeneratorDependencies( code, new CSharpMigrationOperationGenerator( new CSharpMigrationOperationGeneratorDependencies( code)), new CSharpSnapshotGenerator( new CSharpSnapshotGeneratorDependencies( code, sqlServerTypeMappingSource)))) }), historyRepository, reporter, new MockProvider(), new SnapshotModelProcessor(reporter), new Migrator( migrationAssembly, historyRepository, services.GetRequiredService <IDatabaseCreator>(), services.GetRequiredService <IMigrationsSqlGenerator>(), services.GetRequiredService <IRawSqlCommandBuilder>(), services.GetRequiredService <IMigrationCommandExecutor>(), services.GetRequiredService <IRelationalConnection>(), services.GetRequiredService <ISqlGenerationHelper>(), services.GetRequiredService <ICurrentDbContext>(), services.GetRequiredService <IDiagnosticsLogger <DbLoggerCategory.Migrations> >(), services.GetRequiredService <IDiagnosticsLogger <DbLoggerCategory.Database.Command> >(), services.GetRequiredService <IDatabaseProvider>())))); }