ash*_*ina 17 c# entity-framework ef-code-first ef-migrations entity-framework-6
我有一个自定义DatabaseInitialiser,如下所示
/// <summary>
/// Implements the IDatabaseInitializer to provide a custom database initialisation for the context.
/// </summary>
/// <typeparam name="TContext">TContext is the DbContext</typeparam>
public class ParikshaDataBaseInitializer<TContext> : IDatabaseInitializer<TContext> where TContext : DbContext
{
/// <summary>
/// The method to Initialise the database.
/// Takes care of the database cannot be dropped since it is in use problem while dropping and recreating the database.
/// </summary>
/// <param name="context">The DbContext on which to run the initialiser</param>
public void InitializeDatabase(TContext context)
{
var exists = context.Database.Exists();
try
{
if (exists && context.Database.CompatibleWithModel(true))
{
// everything is good , we are done
return;
}
if (!exists)
{
context.Database.Create();
}
}
catch (Exception)
{
//Something is wrong , either we could not locate the metadata or the model is not compatible.
if (exists)
{
context.Database.ExecuteSqlCommand("ALTER DATABASE Pariksha SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
context.Database.ExecuteSqlCommand("USE Master DROP DATABASE Pariksha");
context.SaveChanges();
}
context.Database.Create();
}
}
}
Run Code Online (Sandbox Code Playgroud)
关于上述代码的一些不仅仅是hacky(随意提供帮助)
然后,我添加了迁移并使迁移脚本也正常工作.
internal sealed class Configuration : DbMigrationsConfiguration<ParikshaContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "EFRepository.Context.ParikshaContext";
}
protected override void Seed(ParikshaContext context)
{
}
}
Run Code Online (Sandbox Code Playgroud)
迁移按预期工作.
现在,问题出在我的应用程序启动中,我该怎么办?像这样的东西
var config = new Configuration();
var migrator = new DbMigrator(config);
migrator.Update();
Run Code Online (Sandbox Code Playgroud)
一些论坛也在构造函数中提出了这个看起来有点奇怪的原因,因为我不想每次使用Context时都检查数据库和模式是否正确.那么,这种技术的可能用途是什么?或者我是否认为该建议的背景是错误的?
public ParikshaContext() : base("Pariksha")
{
Database.SetInitializer(new ParikshaDataBaseInitializer<ParikshaContext>());
}
Run Code Online (Sandbox Code Playgroud)
总结一下,
什么是可用的不同技术的正确用例?
什么是理想的策略,以便迁移在所有条件下工作,以及何时将数据库从一个环境移动到另一个环境?
NSG*_*aga 12
这是我尝试Db Initializer将Migration初始化程序和默认程序Db Create与种子组合在一起.(注意:它不是理想的,更像是一个简单的练习,但是给出了你在这里要求的解决方案,主要是工作 - 只需检查我所做的所有更新).
至于why和how- 完全理解我建议你也参考EF源代码(这是新版本,但在许多方面类似)
a)Db初始化程序通常只被调用一次(每个连接) - 并且当您第一次尝试访问"模型"时(第一次查询或类似).在初始化程序中放置一个断点进行检查.
所以把它放在构造函数中是完全安全的(虽然我更喜欢在某个地方的启动时,配置也是如此).只有在需要初始化(并且last one set使用它)时才会调用它,不应该手动调用它.
无论如何,要强制初始化程序,你可以做到 this.Database.Initialize(force: true);
对于切换连接时,请参阅我的帖子中的问题
代码首先自定义连接字符串和迁移而不使用IDbContextFactory
b)如果您创建自己的,IDatabaseInitializer并且仍希望迁移工作side by side
你不应该只是DbMigrator从外面打电话 - 因为你的自定义初始化程序会错过整个'数据库创建'(例如,如果你想种子或其他东西 - 请查看上面的例子).
这两件事都是有效的"初始化者" - 所以你需要将它们整合到一个中,这chain就是某种方式.请记住这order of execution很重要(参见前面的问题) - 你应该检查'空状态',然后调用DbMigrator,然后自己进行初始化.我使用一个初始化程序作为基类,并合并另一个.
如果你只是想seed- 你可以使用迁移配置,这是最简单的,如果合理的话.
是非常"开放式",没有一个答案.通常它可以工作,但问题是...
迁移是3件事(我认为) - 您的代码模型/实体,您的数据库/表和__MigrationHistoryDb中的系统表.所有3都需要留下来in sync.如果您"不同步",您可以删除迁移表,重新创建迁移(使用标记来保留现有数据库),然后继续前进 - 即有实时数据的解决方案.为此,请参阅如何忽略EF 4.3迁移中的表/类,
在移动数据库时你需要删除/创建Db的权限,
确保您的连接正确(更改配置 - 并与您的DbContext名称或ctor同步),
保持简单,不做花哨的事情或从代码切换连接(可能但有问题)等,
不要mix database / code版本 - 即一个代码实体版本 - 一个数据库.如果你想用不同的代码版本共享相同的Db(例如分期,生产) - 不要(EF6中可以使用多租户解决方案 - 例如这个),
如果你需要手动应用数据库 - 生成script通道Update-Database- 并应用它,不要手动操作或者你会弄错(迁移历史表) - 请看这个,
......这只是为数不多的.它是相当稳定和可用的IMO - 但如果你遵守规则 - 并知道有什么限制.
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)
{
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(false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();
// move on with the 'CreateDatabaseIfNotExists' for the 'Seed'
base.InitializeDatabase(context);
if (doseed)
{
Seed(context);
context.SaveChanges();
}
}
protected override void Seed(TContext context)
{
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11872 次 |
| 最近记录: |