public DatabaseOperations( [NotNull] ILoggerProvider loggerProvider, [NotNull] AssemblyLoader startupAssemblyLoader, [NotNull] Assembly startupAssembly, [CanBeNull] string environment, [NotNull] string projectDir, [NotNull] string contentRootPath, [NotNull] string rootNamespace) { Check.NotNull(startupAssemblyLoader, nameof(startupAssemblyLoader)); Check.NotNull(loggerProvider, nameof(loggerProvider)); Check.NotNull(startupAssembly, nameof(startupAssembly)); Check.NotNull(projectDir, nameof(projectDir)); Check.NotEmpty(contentRootPath, nameof(contentRootPath)); Check.NotNull(rootNamespace, nameof(rootNamespace)); _loggerProvider = loggerProvider; _projectDir = projectDir; _rootNamespace = rootNamespace; var logger = new LazyRef <ILogger>(() => loggerProvider.CreateCommandsLogger()); var startup = new StartupInvoker(logger, startupAssembly, environment, contentRootPath); _servicesBuilder = new DesignTimeServicesBuilder(startupAssemblyLoader, startup); }
public MigrationsOperations( [NotNull] ILoggerProvider loggerProvider, [NotNull] string assemblyName, [NotNull] string startupAssemblyName, [NotNull] string projectDir, [NotNull] string rootNamespace, [CanBeNull] IServiceProvider dnxServices = null) { Check.NotNull(loggerProvider, nameof(loggerProvider)); Check.NotEmpty(assemblyName, nameof(assemblyName)); Check.NotEmpty(startupAssemblyName, nameof(startupAssemblyName)); Check.NotNull(projectDir, nameof(projectDir)); Check.NotNull(rootNamespace, nameof(rootNamespace)); var loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(loggerProvider); _loggerProvider = loggerProvider; _logger = new LazyRef <ILogger>(() => loggerFactory.CreateCommandsLogger()); _projectDir = projectDir; _rootNamespace = rootNamespace; _servicesBuilder = new DesignTimeServicesBuilder(dnxServices); _contextOperations = new DbContextOperations( loggerProvider, assemblyName, startupAssemblyName, dnxServices); }
private static void ValidateMigrationAndSnapshotCode( DbContext context, MigrationCodeGetter migrationCodeGetter, SnapshotCodeGetter snapshotCodeGetter) { const string migrationName = "MyMigration"; const string rootNamespace = "MyApp.Data"; var expectedMigration = migrationCodeGetter(migrationName, rootNamespace); var expectedSnapshot = snapshotCodeGetter(rootNamespace); var reporter = new OperationReporter( new OperationReportHandler( m => Console.WriteLine($" error: {m}"), m => Console.WriteLine($" warn: {m}"), m => Console.WriteLine($" info: {m}"), m => Console.WriteLine($"verbose: {m}"))); var assembly = System.Reflection.Assembly.GetExecutingAssembly(); //this works because we have placed the DesignTimeServicesReferenceAttribute //in the test project's properties, which simulates //the nuget package's build target var migration = new DesignTimeServicesBuilder(assembly, assembly, reporter, Array.Empty <string>()) .Build(context) .GetRequiredService <IMigrationsScaffolder>() .ScaffoldMigration(migrationName, rootNamespace); Assert.Equal(expectedMigration, migration.MigrationCode); Assert.Equal(expectedSnapshot, migration.SnapshotCode); }
public void ScaffoldModel_works_with_named_connection_string() { var resolver = new TestNamedConnectionStringResolver("Data Source=Test"); var databaseModelFactory = new TestDatabaseModelFactory(); var scaffolder = new DesignTimeServicesBuilder( typeof(ReverseEngineerScaffolderTest).Assembly, typeof(ReverseEngineerScaffolderTest).Assembly, new TestOperationReporter(), new string[0]) .CreateServiceCollection(SqlServerTestHelpers.Instance.CreateContext()) .AddSingleton <INamedConnectionStringResolver>(resolver) .AddSingleton <IDatabaseModelFactory>(databaseModelFactory) .BuildServiceProvider() .GetRequiredService <IReverseEngineerScaffolder>(); var result = scaffolder.ScaffoldModel( "Name=DefaultConnection", new DatabaseModelFactoryOptions(), new ModelReverseEngineerOptions(), new ModelCodeGenerationOptions { ModelNamespace = "Foo" }); Assert.Equal("Data Source=Test", databaseModelFactory.ConnectionString); Assert.Contains("Name=DefaultConnection", result.ContextFile.Code); Assert.DoesNotContain("Data Source=Test", result.ContextFile.Code); Assert.DoesNotContain("#warning", result.ContextFile.Code); }
/// <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 MigrationsOperations( IOperationReporter reporter, Assembly assembly, Assembly startupAssembly, string projectDir, string?rootNamespace, string?language, bool nullable, string[]?args) { _reporter = reporter; _assembly = assembly; _projectDir = projectDir; _rootNamespace = rootNamespace; _language = language; _nullable = nullable; _args = args ?? Array.Empty <string>(); _contextOperations = new DbContextOperations( reporter, assembly, startupAssembly, projectDir, rootNamespace, language, nullable, _args); _servicesBuilder = new DesignTimeServicesBuilder(assembly, startupAssembly, reporter, _args); }
public MigrationsOperations( [NotNull] ILoggerProvider loggerProvider, [NotNull] Assembly assembly, [NotNull] Assembly startupAssembly, [CanBeNull] string environment, [NotNull] string projectDir, [NotNull] string rootNamespace) { Check.NotNull(loggerProvider, nameof(loggerProvider)); Check.NotNull(assembly, nameof(assembly)); Check.NotNull(startupAssembly, nameof(startupAssembly)); Check.NotNull(projectDir, nameof(projectDir)); Check.NotNull(rootNamespace, nameof(rootNamespace)); var loggerFactory = new LoggerFactory(); loggerFactory.AddProvider(loggerProvider); _loggerProvider = loggerProvider; _logger = new LazyRef <ILogger>(() => loggerFactory.CreateCommandsLogger()); _assembly = assembly; _projectDir = projectDir; _rootNamespace = rootNamespace; _contextOperations = new DbContextOperations( loggerProvider, assembly, startupAssembly, projectDir, environment); var startup = new StartupInvoker(startupAssembly, environment); _servicesBuilder = new DesignTimeServicesBuilder(startup); }
public void ScaffoldModel_works_with_overridden_connection_string() { var resolver = new TestNamedConnectionStringResolver("Data Source=Test"); var databaseModelFactory = new TestDatabaseModelFactory(); databaseModelFactory.ScaffoldedConnectionString = "Data Source=ScaffoldedConnectionString"; var scaffolder = new DesignTimeServicesBuilder( typeof(ReverseEngineerScaffolderTest).Assembly, typeof(ReverseEngineerScaffolderTest).Assembly, new TestOperationReporter(), new string[0]) .CreateServiceCollection("Microsoft.EntityFrameworkCore.SqlServer") .AddSingleton <INamedConnectionStringResolver>(resolver) .AddScoped <IDatabaseModelFactory>(p => databaseModelFactory) .BuildServiceProvider(validateScopes: true) .CreateScope() .ServiceProvider .GetRequiredService <IReverseEngineerScaffolder>(); var result = scaffolder.ScaffoldModel( "Name=DefaultConnection", new DatabaseModelFactoryOptions(), new ModelReverseEngineerOptions(), new ModelCodeGenerationOptions { ModelNamespace = "Foo" }); Assert.Contains("Data Source=ScaffoldedConnectionString", result.ContextFile.Code); Assert.DoesNotContain("Name=DefaultConnection", result.ContextFile.Code); Assert.DoesNotContain("Data Source=Test", result.ContextFile.Code); }
public static ScaffoldedModel ScaffoldContext( [NotNull] string provider, [NotNull] string connectionString, [CanBeNull] string outputDir, [CanBeNull] string outputContextDir, [CanBeNull] string dbContextClassName, [NotNull] IEnumerable <string> schemas, [NotNull] IEnumerable <string> tables, bool useDataAnnotations, bool overwriteFiles, bool useDatabaseNames) { var unwrappedReportHandler = ForwardingProxy.Unwrap <IOperationReportHandler>(new OperationReportHandler()); var reporter = new OperationReporter(unwrappedReportHandler); var _servicesBuilder = new DesignTimeServicesBuilder(Assembly.GetExecutingAssembly(), reporter, Array.Empty <string>()); var services = _servicesBuilder.Build(provider); var scaffolder = services.GetRequiredService <IReverseEngineerScaffolder>(); var @namespace = "DiplomWork"; var scaffoldedModel = scaffolder.ScaffoldModel( connectionString, tables, schemas, @namespace, null, MakeDirRelative(outputDir, outputContextDir), dbContextClassName, new ModelReverseEngineerOptions { UseDatabaseNames = useDatabaseNames }, new ModelCodeGenerationOptions { UseDataAnnotations = useDataAnnotations }); return(scaffoldedModel); }
public async Task RunAsync(IDbContext context) { IModel lastModel = null; try { var lastMigration = context.Migrations .OrderByDescending(e => e.MigrationTime) .OrderByDescending(e => e.Id) // mysql下自动生成的时间日期字段时间精度为秒 .FirstOrDefault(); lastModel = lastMigration == null ? null : ((await CreateModelSnapshot(context, Encoding.UTF8.GetString(Convert.FromBase64String(lastMigration.SnapshotDefine))))?.Model); } catch (DbException) { } // 需要从历史版本库中取出快照定义,反序列化成类型 GetDifferences(快照模型, context.Model); // 实际情况下要传入历史快照 var modelDiffer = context.Context .GetInfrastructure() .GetService <IMigrationsModelDiffer>(); var hasDiffer = modelDiffer.HasDifferences(lastModel, context.Context.Model); if (hasDiffer) { var upOperations = modelDiffer.GetDifferences(lastModel, context.Context.Model); using (var trans = context.Context.Database.BeginTransaction()) { try { context.Context.GetInfrastructure() .GetRequiredService <IMigrationsSqlGenerator>() .Generate(upOperations, context.Context.Model) .ToList() .ForEach(cmd => context.Context.Database.ExecuteSqlCommand(cmd.CommandText)); context.Context.Database.CommitTransaction(); } catch (DbException ex) { context.Context.Database.RollbackTransaction(); throw ex; } string snapshotCode = new DesignTimeServicesBuilder(context.GetType().Assembly, context.GetType().Assembly, new ModuleDbOperationReporter(), new string[0]) .Build((DbContext)context) .GetService <IMigrationsCodeGenerator>() .GenerateSnapshot(ContextAssembly, context.GetType(), SnapshotName, context.Context.Model); context.Migrations.Add(new MigrationRecord() { SnapshotDefine = Convert.ToBase64String(Encoding.UTF8.GetBytes(snapshotCode)), MigrationTime = DateTime.Now }); await context.Context.SaveChangesAsync(true); } } }
/// <summary> /// 把model生成快照 /// </summary> /// <param name="_dbContext">efcontent</param> /// <param name="nameSpace">快照类的空间名称</param> /// <param name="className">快照类的名称</param> /// <returns></returns> private static string ModelSnapshotToString(EfContent _dbContext, string nameSpace, string className) { var snapshotCode = new DesignTimeServicesBuilder(typeof(EfContent).Assembly, Assembly.GetEntryAssembly(), new OperationReporter(new OperationReportHandler()), new string[0]) .Build((DbContext)_dbContext) .GetService <IMigrationsCodeGenerator>() .GenerateSnapshot(nameSpace, typeof(EfContent), className, _dbContext.Model);//modelSnapshotNamespace:给动态生成类添加nameplace(必须和当前代码所在的命名控件下或者一样)modelSnapshotName:动态生成类的名称 return(snapshotCode); }
protected static IServiceCollection CreateServices() { var testAssembly = typeof(ModelCodeGeneratorTestBase).Assembly; var reporter = new TestOperationReporter(); var services = new DesignTimeServicesBuilder(testAssembly, testAssembly, reporter, new string[0]) .CreateServiceCollection("Microsoft.EntityFrameworkCore.SqlServer"); return(services); }
public CodeFirstMigrations(string projectPath, Type dbContextType, Func <DbContext> resolveDbContext) { ProjectPath = projectPath; ResolveDbContext = resolveDbContext; var entryAssembly = dbContextType.GetTypeInfo().Assembly; var al = new AssemblyLoader(name => entryAssembly); var startupInvoker = new StartupInvoker(entryAssembly, "Debug", projectPath); _servicesBuilder = new DesignTimeServicesBuilder(al, startupInvoker); }
public void Design_time_works() { var services = new DesignTimeServicesBuilder( typeof(EndToEndTests).Assembly, typeof(EndToEndTests).Assembly, new OperationReporter(null), Array.Empty <string>()) .Build("Microsoft.EntityFrameworkCore.Sqlite"); var namedConnectionStringResolver = services.GetService <INamedConnectionStringResolver>(); Assert.IsType <ConfigrationManagerConnectionStringResolver>(namedConnectionStringResolver); }
/// <summary> /// Automatically migrate the database /// Note: The DbContext to be migrated needs to inherit from IKingsDbContext or manually add entity MigrationLog in any way. /// </summary> /// <param name="dbContext"></param> public static void AutoMigratorDatabase(this DbContext dbContext) { Console.WriteLine($"database begin to magration ......"); IModel lastModel = null; try { var relationDatabase = dbContext.GetService <IRelationalDatabaseCreator>(); if (!relationDatabase.Exists()) { relationDatabase.Create(); } else { var lastMigration = dbContext.Set <MigrationLog>() .OrderByDescending(e => e.Id) .FirstOrDefault(); lastModel = lastMigration == null ? null : (CreateModelSnapshot(lastMigration.SnapshotDefine, typeof(DbContextMigrationExtensions).Namespace , _dbContentModelSnapshot, dbContext.GetType())?.Model); } } catch (Exception ex) { throw ex; } var modelDiffer = dbContext.Database.GetService <IMigrationsModelDiffer>(); if (modelDiffer.HasDifferences(lastModel, dbContext.Model)) { var upOperations = modelDiffer.GetDifferences(lastModel, dbContext.Model); Migrationing(upOperations, dbContext); var serviceProvider = new DesignTimeServicesBuilder(dbContext.GetType().Assembly, Assembly.GetEntryAssembly(), new OperationReporter(new OperationReportHandler()), new string[0]) .Build(dbContext); var migrationsCodeGenerator = serviceProvider.GetService(typeof(IMigrationsCodeGenerator)) as IMigrationsCodeGenerator; var snapshotCode = migrationsCodeGenerator.GenerateSnapshot(typeof(DbContextMigrationExtensions).Namespace, dbContext.GetType(), _dbContentModelSnapshot, dbContext.Model); dbContext.Set <MigrationLog>().Add(new MigrationLog() { SnapshotDefine = snapshotCode, MigrationTime = DateTime.Now }); dbContext.SaveChanges(); } Console.WriteLine($"database magration end......"); }
public void ModelChangesAreNotPending() { var servicesBuilder = new DesignTimeServicesBuilder(Assembly.GetExecutingAssembly(), Mock.Of <IOperationReporter>()); var services = servicesBuilder.Build(db); var dependencies = services.GetService <MigrationsScaffolderDependencies>(); var modelSnapshot = dependencies.MigrationsAssembly.ModelSnapshot; Assert.NotNull(modelSnapshot); var lastModel = dependencies.SnapshotModelProcessor.Process(modelSnapshot.Model); var upOperations = dependencies.MigrationsModelDiffer.GetDifferences(lastModel, dependencies.Model); if (upOperations.Any()) { throw new XunitException("There are pending model changes."); } }
private DesignTimeServicesBuilder GetDesignTimeServicesBuilder(string outputPath) { var assembly = Load(outputPath); if (assembly == null) { throw new ArgumentException("Unable to load project assembly"); } //TODO Use OperationHandler output!! var reporter = new OperationReporter( new OperationReportHandler()); var builder = new DesignTimeServicesBuilder(assembly, reporter); return(builder); }
/// <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 DatabaseOperations( IOperationReporter reporter, Assembly assembly, Assembly startupAssembly, string projectDir, string?rootNamespace, string?language, bool nullable, string[]?args) { _projectDir = projectDir; _rootNamespace = rootNamespace; _language = language; _nullable = nullable; _args = args ?? Array.Empty <string>(); _servicesBuilder = new DesignTimeServicesBuilder(assembly, startupAssembly, reporter, _args); }
private void ValidateContextNameInReverseEngineerGenerator(string contextName) { var assembly = typeof(ReverseEngineeringConfigurationTests).Assembly; var reverseEngineer = new DesignTimeServicesBuilder(assembly, assembly, new TestOperationReporter(), new string[0]) .Build("Microsoft.EntityFrameworkCore.SqlServer") .GetRequiredService <IReverseEngineerScaffolder>(); Assert.Equal( DesignStrings.ContextClassNotValidCSharpIdentifier(contextName), Assert.Throws <ArgumentException>( () => reverseEngineer.ScaffoldModel( "connectionstring", new DatabaseModelFactoryOptions(), new ModelReverseEngineerOptions(), new ModelCodeGenerationOptions { ModelNamespace = "FakeNamespace", ContextName = contextName })) .Message); }
public DatabaseOperations( [NotNull] ILoggerProvider loggerProvider, [NotNull] string assemblyName, [NotNull] string startupAssemblyName, [NotNull] string projectDir, [NotNull] string rootNamespace, [CanBeNull] IServiceProvider dnxServices = null) { Check.NotNull(loggerProvider, nameof(loggerProvider)); Check.NotEmpty(assemblyName, nameof(assemblyName)); Check.NotEmpty(startupAssemblyName, nameof(startupAssemblyName)); Check.NotNull(projectDir, nameof(projectDir)); Check.NotNull(rootNamespace, nameof(rootNamespace)); _loggerProvider = loggerProvider; _projectDir = projectDir; _rootNamespace = rootNamespace; _servicesBuilder = new DesignTimeServicesBuilder(dnxServices); }
private ServiceProvider CreateDesignServiceProvider( string assemblyCode, string startupAssemblyCode = null, DbContext context = null) { var assembly = Compile(assemblyCode); var startupAssembly = startupAssemblyCode == null ? assembly : Compile(startupAssemblyCode); var reporter = new TestOperationReporter(); var servicesBuilder = new DesignTimeServicesBuilder(assembly, startupAssembly, reporter, new string[0]); return((context == null ? servicesBuilder .CreateServiceCollection("Microsoft.EntityFrameworkCore.SqlServer") : servicesBuilder .CreateServiceCollection(context)) .BuildServiceProvider(validateScopes: true)); }
public EFCoreAutoMigrator(DbContext _dbContext, ILogger _logger) { dbMigratorProps = new DBMigratorProps() { dbContext = _dbContext, logger = _logger, dbMigratorTableMetatdata = new DefaultMigrationMetadata(), migrationProviderFactory = new MigrationProviderFactory(), allowDestructive = false, snapshotHistoryLimit = -1 }; var migrationAssembly = _dbContext.GetService <IMigrationsAssembly>(); DesignTimeServicesBuilder builder = new DesignTimeServicesBuilder(migrationAssembly.Assembly, Assembly.GetEntryAssembly(), this, null); var dbServices = builder.Build(_dbContext); var dependencies = dbServices.GetRequiredService <MigrationsScaffolderDependencies>(); var migrationName = dependencies.MigrationsIdGenerator.GenerateId(Utilities.DalConsts.MIGRATION_NAME_PREFIX); dbMigratorProps.dbServices = dbServices; dbMigratorProps.migrationName = migrationName; }
/// <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> protected DbContextOperations( IOperationReporter reporter, Assembly assembly, Assembly startupAssembly, string projectDir, string?rootNamespace, string?language, bool nullable, string[]?args, AppServiceProviderFactory appServicesFactory) { _reporter = reporter; _assembly = assembly; _startupAssembly = startupAssembly; _projectDir = projectDir; _rootNamespace = rootNamespace; _language = language; _nullable = nullable; _args = args ?? Array.Empty <string>(); _appServicesFactory = appServicesFactory; _servicesBuilder = new DesignTimeServicesBuilder(assembly, startupAssembly, reporter, _args); }
public DatabaseOperations( [NotNull] ILoggerProvider loggerProvider, [NotNull] string assemblyName, [NotNull] string startupAssemblyName, [CanBeNull] string environment, [NotNull] string projectDir, [NotNull] string rootNamespace) { Check.NotNull(loggerProvider, nameof(loggerProvider)); Check.NotEmpty(assemblyName, nameof(assemblyName)); Check.NotEmpty(startupAssemblyName, nameof(startupAssemblyName)); Check.NotNull(projectDir, nameof(projectDir)); Check.NotNull(rootNamespace, nameof(rootNamespace)); _loggerProvider = loggerProvider; _projectDir = projectDir; _rootNamespace = rootNamespace; var startup = new StartupInvoker(startupAssemblyName, environment); _servicesBuilder = new DesignTimeServicesBuilder(startup); }
public DbContextOperations( [NotNull] ILoggerProvider loggerProvider, [NotNull] Assembly assembly, [NotNull] Assembly startupAssembly, [NotNull] string projectDir, [CanBeNull] string environment) { Check.NotNull(loggerProvider, nameof(loggerProvider)); Check.NotNull(assembly, nameof(assembly)); Check.NotNull(startupAssembly, nameof(startupAssembly)); Check.NotEmpty(projectDir, nameof(projectDir)); _loggerProvider = loggerProvider; _assembly = assembly; _startupAssembly = startupAssembly; _projectDir = projectDir; _logger = new LazyRef <ILogger>(() => _loggerProvider.CreateCommandsLogger()); var startup = new StartupInvoker(startupAssembly, environment); _runtimeServices = startup.ConfigureServices(); _servicesBuilder = new DesignTimeServicesBuilder(startup); }
public async Task RunAsync(IDbContext context) { IModel lastModel = null; var contextServiceProvider = context.Context.GetInfrastructure(); var store = context.Context.GetService <IStore>(); await new InitlizationDbContext(store.CreateOptions(false)).Database.EnsureCreatedAsync(); try { var lastMigration = context.Migrations .OrderByDescending(e => e.MigrationTime) .OrderByDescending(e => e.Id) // mysql下自动生成的时间日期字段时间精度为秒 .FirstOrDefault(); lastModel = lastMigration == null ? null : ((await CreateModelSnapshot(context, Encoding.UTF8.GetString(Convert.FromBase64String(lastMigration.SnapshotDefine))))?.Model); } catch (DbException) { } var designTimeServices = new DesignTimeServicesBuilder( context.Context.GetType().Assembly, context.Context.GetType().Assembly, new OperationReporter(), new string[0]).Build(context.Context); var process = designTimeServices.GetService <ISnapshotModelProcessor>(); // 需要从历史版本库中取出快照定义,反序列化成类型 GetDifferences(快照模型, context.Model); // 实际情况下要传入历史快照 var modelDiffer = contextServiceProvider.GetService <IMigrationsModelDiffer>(); var hasDiffer = modelDiffer.HasDifferences( lastModel != null ? process.Process(lastModel).GetRelationalModel() : null, context.Context.Model.GetRelationalModel()); if (!hasDiffer) { return; } var upOperations = modelDiffer.GetDifferences( lastModel != null ? lastModel.GetRelationalModel() : null, context.Context.Model.GetRelationalModel()); using (var trans = context.Context.Database.BeginTransaction()) { try { contextServiceProvider.GetRequiredService <IMigrationsSqlGenerator>() .Generate(upOperations, context.Context.Model) .ToList() .ForEach(cmd => context.Context.Database.ExecuteSqlRaw(cmd.CommandText)); trans.Commit(); } catch (DbException ex) { trans.Rollback(); throw ex; } context.Migrations.Add(new MigrationRecord() { SnapshotDefine = await CreateSnapshotCode(designTimeServices, context), MigrationTime = DateTime.Now }); await context.Context.SaveChangesAsync(true); } }