4

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

我需要多个连接,因为我在单独的数据库中记录了审计日志。我使用类似的代码从 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();
    }

这个问题似乎是相关的

更新:

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

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

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

4

2 回答 2

7

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

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

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

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

3)如果不存在 - EF/CF 会根据你的提供者 -和你的上下文的类名- 制作“默认” - 这通常不是你想要的,

出于这个原因,您不应该使用初始化程序进行自定义 - 初始化程序应该是不可知的并用于其他目的 - 在 .config 中设置连接 - 或直接在您的DbContext

还要首先检查这个实体框架代码 - 一旦开发完成,我如何告诉我的应用程序现在使用生产数据库而不是创建本地数据库?

在做任何事情之前,请始终检查“您的数据”的去向。

对于初始化程序的实际工作方式- 检查我的另一个帖子,我做了一个完整的例子

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

注:(来自评论)

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

或者 - 放一些像 public MyContext() : base("MyContextConnection")- 指向<connectionStrings>配置的 东西

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

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

关于通过迁移(本地和远程从一个应用程序)来娱乐“多个数据库” - 不完全相关 - 但这个链接 -迁移没有按我的意愿工作...... Asp.net EntityFramework

更新:( 在这里进一步讨论-如果添加一个继承自某事物的类是否会改变代码的行为,是否违反了可靠的原则?

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

首先,这很“愉快”:

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

发生了什么事,令我惊讶的是 - 它实际上是在第一遍创建了两个数据库吗?

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

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

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

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

于 2013-04-06T00:46:47.417 回答
0

您可以在 MigrateDatabaseToLatestVersion 构造函数中提供配置。如果您在 DbContext 中设置初始化程序,您还可以传递“true”以使用当前连接字符串。

于 2016-03-01T11:02:52.197 回答