gpt4 book ai didi

entity-framework-5 - Database.SetInitializer 实际上是如何工作的? (EF 代码优先创建数据库并使用多个连接字符串应用迁移)

转载 作者:行者123 更新时间:2023-12-05 00:30:50 27 4
gpt4 key购买 nike

给定连接字符串,我正在尝试编写一种方法来创建数据库并在其上运行迁移。

我需要多个连接,因为我在单独的数据库中记录了审计日志。
我使用类似的代码从 app.config 中获取连接字符串

ConfigurationManager.ConnectionStrings["Master"].ConnectionString;

该代码适用于我的 app.config 中定义的第一个连接字符串,但不适用于其他代码,这让我认为它以某种我不知道的方式从 app.config 获取连接字符串。

如果数据库不存在,我创建数据库的代码是
private static Context MyCreateContext(string ConnectionString)
{
// put the connection string where the factory method can get it
AppDomain.CurrentDomain.SetData("ConnectionString", ConnectionString );
var factory = new ContextFactory();
// I know I need this line - but I cant see how what follows actually uses it
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context,DataLayer.Migrations.Configuration>());
var context = factory.Create();
context.Database.CreateIfNotExists();
return context
}

Migrations.Configuration 中的代码是
Public sealed class Configuration :  DbMigrationsConfiguration<DataLayer.Context>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
}

上下文工厂代码是
  public class ContextFactory : IDbContextFactory<Context>
{
public Context Create()
{
var s = (string)AppDomain.CurrentDomain.GetData("ConnectionString");

return new Context(s);
}
}

因此,我在创建上下文之前设置了连接字符串。
考虑到除了数据库名称之外的连接字符串都相同,并且迁移代码使用一个连接字符串运行,但不使用其他连接字符串运行,我哪里会出错?

我想知道我的问题是否与了解 Database.SetInitializer 如何实际工作有关。我在猜测关于反射或泛型的一些事情。我如何使对 SetInitializer 的调用与我的实际上下文相关联?

我尝试了以下代码,但迁移不运行
 private static Context MyCreateContext(string ConnectionString)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, DataLayer.Migrations.Configuration>());
var context = new Context(ConnectionString);
context.Database.CreateIfNotExists();
}

This question appears to be related

更新:

如果我使用引用连接字符串,我可以让迁移工作
public MyContext() : base("MyContextConnection") - 指向配置

如果我创建了一个 ContextFactory 类并通过引用全局将连接传递给它,我还能够使用上下文的不同实例进行迁移。 (请参阅我对相关问题链接的回答)

现在我想知道为什么它必须这么难。

最佳答案

我不确定你面临的问题是什么,但让我试试

提供连接的最简单方法 - 并确保它以这种方式工作......

1) Use your 'DbContext' class name - 并在 app.config(或 web.config)中定义连接。这是最简单的,你应该有一个与你的上下文类名匹配的连接,

2)如果您通过构造函数将其放入 DbContext - 然后保持一致并使用那个。我还建议从配置连接中“读取” - 并再次将其命名为与您的上下文类“相同”(使用连接“名称”,而不是实际字符串),

3) 如果不存在 - EF/CF 将“默认”设为 - 基于您的提供商 - 和你的上下文的类名 - 这通常不是你想要的,

You shouldn't customize with initializers for that reason - initializers should be agnostic and serve other purpose - setup connection in the .config - or directly on your DbContext



另请查看 Entity Framework Code First - How do I tell my app to NOW use the production database once development is complete instead of creating a local db?

Always check 'where your data' goes - before doing anything.



初始化器的实际工作方式 - 检查我的另一个帖子,我做了一个详尽的例子

How to create initializer to create and migrate mysql database?

注:(来自评论)

连接不应该是非常动态的 - 配置是它的正确位置,除非你有充分的理由。
构造函数也应该可以正常工作。 CreateDbIfNotExists不能与“迁移”初始化程序一起使用。您可以使用 MigrateDatabaseToLatestVersion初始化器。不要“混合”它

或者 - 把一些像 public MyContext() : base("MyContextConnection") - 指向 <connectionStrings>在配置中

指向连接 - 只需使用它的“名称”并将其放入构造函数中。

或使用类似 ConfigurationManager.ConnectionStrings["CommentsContext"].ConnectionString 的东西

关于通过迁移(本地和远程从一个应用程序)来娱乐“多个数据库” - 不完全相关 - 但这个链接 - Migration not working as I wish... Asp.net EntityFramework

更新:
(此处进一步讨论 - Is adding a class that inherits from something a violation of the solid principles if it changes the behavior of code?)

这里变得越来越有趣了。我确实设法重现了您实际面临的问题。以下是我认为正在发生的事情的简短分割:

首先,这很“愉快”:
Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<MyContext, MyProject.Migrations.Configuration>());
for (var flip = false; true; flip = !flip)
{
using (var db = new MyContext(flip ? "Name=MyContext" : "Name=OtherContext"))
{
// insert some records...
db.SaveChanges();
}
}

(我使用了我另一篇文章中的自定义初始化程序,它“手动”控制迁移/创建)

在没有初始化程序的情况下工作得很好。一旦我打开它,我遇到了一些奇怪的问题。

我删除了 Db-s(每个连接两个)。我希望要么不工作,要么创建一个数据库,然后在下一次传递中创建另一个(就像它所做的那样,没有迁移,只是“创建”初始化程序)。

What happened, to my surprise - is it actually created both databases on the first pass ??



然后,作为一个好奇的人:),我在 MyContext 上设置了断点。 ctor,并通过迁移器/初始化器进行调试。再次为空/无 db-s 等。

它在我的通话中创建了第一个实例 flip .然后在第一次访问“模型”时,它调用了初始化程序。 Migrator 接管(没有 db-s)。期间 migrator.Update();它实际上构造了 MyContext (我通过配置中的通用参数猜测) - 并调用“默认”空 ctor。默认情况下,它具有“其他连接/名称” - 并且也创建了其他 Db。

所以,我认为这解释了你正在经历的事情。以及为什么您必须创建“工厂”来支持上下文创建。这似乎是唯一的方法。并设置一些“AppDomain”范围的“连接字符串”(实际上你做得很好),默认情况下 ctor 调用不会“覆盖”。

我看到的解决方案是——你只需要通过工厂运行所有东西——并在那里“翻转”连接(不需要静态连接,只要你的工厂是单例的。

关于entity-framework-5 - Database.SetInitializer 实际上是如何工作的? (EF 代码优先创建数据库并使用多个连接字符串应用迁移),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15830030/

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