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); }
/// <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"); }