gpt4 book ai didi

c# - 如何创建初始化程序来创建和迁移 mysql 数据库?

转载 作者:IT老高 更新时间:2023-10-29 00:07:37 25 4
gpt4 key购买 nike

我已经学习如何使用 EF 大约一周了,但我一直在纠结于创建/更新我的数据库的问题。如果数据库不存在,我可以创建一个初始化程序来创建数据库:

static class Program
{
static void Main()
{
Database.SetInitializer<GumpDatabase>(new GumpDatabaseInitializer());
....

class GumpDatabaseInitializer : CreateDatabaseIfNotExists<GumpDatabase>
{
public GumpDatabaseInitializer()
{
}
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
// Other stuff
}
}

或者我可以创建一个配置来迁移数据库

static class Program
{
static void Main()
{
Database.SetInitializer<GumpDatabase>(new MigrateDatabaseToLatestVersion<GumpDatabase, Configuration>());
....

internal sealed class Configuration : DbMigrationsConfiguration<GumpDatabase>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
}

protected override void Seed(GumpDatabase context)
{

}

每个都可以正常工作,但我还没有想出一个方法来做到这两个。我可以通过更改 SetInitializer 调用在两个初始化程序之间切换,但是如果我想创建数据库(如果它不存在)并且如果它是迁移它我该怎么办?我需要创建自定义初始化程序吗?

谢谢

根据 NSGaga 回答编辑

class CreateOrMigrateDatabaseInitializer<TContext, TConfiguration> : CreateDatabaseIfNotExists<TContext>, IDatabaseInitializer<TContext>
where TContext : DbContext
where TConfiguration : DbMigrationsConfiguration<TContext>, new()
{
private readonly DbMigrationsConfiguration _configuration;
public CreateOrMigrateDatabaseInitializer()
{
_configuration = new TConfiguration();
}
public CreateOrMigrateDatabaseInitializer(string connection)
{
Contract.Requires(!string.IsNullOrEmpty(connection), "connection");

_configuration = new TConfiguration
{
TargetDatabase = new DbConnectionInfo(connection)
};
}
void IDatabaseInitializer<TContext>.InitializeDatabase(TContext context)
{
Contract.Requires(context != null, "context");

if (context.Database.Exists())
{
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
{
var migrator = new DbMigrator(_configuration);
migrator.Update();
}
}
else
{
context.Database.Create();
Seed(context);
context.SaveChanges();
}


}
protected virtual void Seed(TContext context)
{
}
}

internal sealed class Configuration : DbMigrationsConfiguration<GumpDatabase>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = false;
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
}

protected override void Seed(GumpDatabase context)
{
}
}

class GumpDatabaseInitializer : CreateOrMigrateDatabaseInitializer<GumpDatabase,Gump.Migrations.Configuration>
{
public GumpDatabaseInitializer()
{
}
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Sequences (Name)");
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX StationPartNumber ON StationPartNumbers (StationId,PartNumberId)");
}
}

最后

static void Main()
{
Database.SetInitializer<GumpDatabase>(new GumpDatabaseInitializer());

最佳答案

我想你已经差不多了 - 你可以查找 MigrateDatabaseToLatestVersion 的源代码(它是开源的 http://entityframework.codeplex.com/ ) - 它非常简单,它所做的几乎就是调用 DbMigrator - 据我所知。

您所要做的似乎就是合并两者 - 使用一个或另一个作为基础,在其中添加其他功能 - 我认为这应该可以正常工作。

class CreateAndMigrateDatabaseInitializer<TContext, TConfiguration> : CreateDatabaseIfNotExists<TContext>, IDatabaseInitializer<TContext> 
where TContext : DbContext
where TConfiguration : DbMigrationsConfiguration<TContext>, new()
{
private readonly DbMigrationsConfiguration _configuration;
public CreateAndMigrateDatabaseInitializer()
{
_configuration = new TConfiguration();
}
public CreateAndMigrateDatabaseInitializer(string connection)
{
Contract.Requires(!string.IsNullOrEmpty(connection), "connection");

_configuration = new TConfiguration
{
TargetDatabase = new DbConnectionInfo(connection)
};
}
void IDatabaseInitializer<TContext>.InitializeDatabase(TContext context)
{
Contract.Requires(context != null, "context");

var migrator = new DbMigrator(_configuration);
migrator.Update();

// move on with the 'CreateDatabaseIfNotExists' for the 'Seed'
base.InitializeDatabase(context);
}
protected override void Seed(TContext context)
{
}
}

这样调用它...

Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>());

...实际上,覆盖它(因为它是通用实现),就像您为 CreateDatabaseIfNotExists 所做的那样(您只是为配置提供了额外的“参数”)——并且只需提供“种子”。

class GumpDatabaseInitializer : CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>
{
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
}
}

...并称它为

Database.SetInitializer(new GumpDatabaseInitializer());

编辑:根据评论 - DbMigrator 不应运行两次。它总是检查(花费一些时间)并进行“空白”更新并继续前进。但是,以防万一如果您想在进入之前删除它并“检查” - 这应该有效(更改上面的类似部分)......

var migrator = new DbMigrator(_configuration);
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();

(这是一个冗余/双重检查 - 一个 if-s 应该足够了。在那里休息一下 - 看看到底发生了什么,它不应该进入 - 一旦 Db 被迁移。正如我提到的,工作当我测试它时很好。

编辑:

InitializeDatabase内部替换为...

var doseed = !context.Database.Exists();
// && new DatabaseTableChecker().AnyModelTableExists(context);
// check to see if to seed - we 'lack' the 'AnyModelTableExists' - could be copied/done otherwise if needed...

var migrator = new DbMigrator(_configuration);
// if (doseed || !context.Database.CompatibleWithModel(throwIfNoMetadata: false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();

// move on with the 'CreateDatabaseIfNotExists' for the 'Seed'
base.InitializeDatabase(context);
if (doseed)
{
Seed(context);
context.SaveChanges();
}

这解决了(中途)非播种 - 如果迁移先进行。迁移必须是第一位的,否则就会有问题。

您仍然需要正确地完成它 - 如果不是您可能需要的全部,这就是要点 - 但如果 MySQL 等有任何问题,可能需要更多的工作。

注意:如果您有数据库,播种仍然不会调用,但它是空的。问题是混合使用两个不同的初始值设定项。因此,您必须解决这个问题 - 通过实现 Create... 在内部执行的操作(我们无法调用的调用)或其他方式。

关于c# - 如何创建初始化程序来创建和迁移 mysql 数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15796115/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com