放置Database.SetInitializer的地方

tor*_*orm 32 c# entity-framework ef-code-first asp.net-mvc-3

我正在开发一个最终可能有多个UI版本/变体的项目,但到目前为止,我的解决方案Web中有两个子项目 - 包含ASP.NET MVC的Web界面.服务项目是我定义数据库上下文和模型的地方.

我的目标是在我的Web项目中对EF特定代码进行最少或可能没有引用.我希望它是独立的,所以当我用服务后端切换dll(从假设SQL到XML或MySQL)时,我不应该在我的MVC项目中进行多次修改.

这是它的样子:

项目布局

我的问题是: - 到目前为止,我没有找到在Global.asax之外的其他地方使用Database.SetInitializer的示例.如果模型在我的工厂类似的DatabaseContextProvider类或服务类中更改,从内容中提取数据并将其提供给具有DTO的UI,我想放置数据库重新创建.那个地方有没有缺点? - 我想让上下文的connectionString可以使用Properties/Settings.settings文件进行配置 - 这是否合理?

Ron*_*nyK 37

为了避免耦合,我宁愿不在包含DataContext的Assembly之外设置初始化程序.所以,我为DataContext添加了一个静态构造函数.这样,引用此程序集的每个项目都将享受初始化程序而无需显式设置它,并且初始化程序仅在每个进程中设置一次.

static MyDataContext()
{
   Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDataContext, Configuration>());
}
Run Code Online (Sandbox Code Playgroud)

连接字符串当然将从应用程序配置文件中获取.

  • 不确定这是一个好主意,因为你在`DbContext`和初始化程序之间有一个紧密耦合.初始化策略取决于上下文,例如,对于您将使用`DropCreateDatabaseAlways`的测试,以及用于生成`CreateDatabaseIfNotExists`的测试... (10认同)
  • @Pragmateek对于测试,您可以始终为该类型的静态初始化程序运行,然后直接调用`Database.SetInitializer()`.对于许多使用迁移的人来说,外部消费者应该使用的迁移集已经与模型本身密切相关,因此静态初始化器可能是指定对大多数正常情况有意义的默认初始化器的好地方(例如,非测试/开发消费者. (3认同)

Era*_*nga 15

您需要一种机制来Database.SetInitializer在第一次使用之前调用该方法DbContext.这就是为什么它通常在Global.asax文件中调用.

您可以在tm.Service项目中使用初始化方法创建一个类,并在方法中调用它Application_Start并将其Database.SetInitializer放入该初始化方法中.

可以从设置文件中提供连接字符串.


Ric*_*tas 9

我把它放在DbContext构造函数上并为我工作.

public myDbContext() : base(connectionToDatabase) {
        Database.SetInitializer<myDbContext>(null);
    }
Run Code Online (Sandbox Code Playgroud)

上面的解决方案可行,但效率不如以下代码:

  protected void Application_Start()
    {
        Database.SetInitializer<myDbContext>(null);
    }
Run Code Online (Sandbox Code Playgroud)

在我的情况下,我没有在UI上引用我的DAL,因此我做的是,我创建了一个EntityFramework配置并使用反射注册我的设置.

 protected void Application_Start()
    {           
        EntityFrameworkConfig.RegisterSettings();
    }


 public static class EntityFrameworkConfig
{
    public static void RegisterSettings()
    {
        // Use the file name to load the assembly into the current
        // application domain.
        Assembly a = Assembly.Load("MyAssembly");
        // Get the type to use.
        Type myType = a.GetType("MyType");
        // Get the method to call.
        MethodInfo myMethod = myType.GetMethod("MySettingsMethod");
        // Create an instance.
        object obj = Activator.CreateInstance(MyType);
        // Execute the method.
        myMethod.Invoke(obj, null);
    }
}

  public void Configurations()
    {
      //Other settings
        Database.SetInitializer<myDbContext>(null);
    }
Run Code Online (Sandbox Code Playgroud)

更新

使用Entity Framework 6,现在可以使用NullDatabaseInitializer

Database.SetInitializer(new NullDatabaseInitializer<MyDbContext>());
Run Code Online (Sandbox Code Playgroud)

  • 这样做的一个潜在问题是,每次构造myDbContext类时都可以调用它,这很可能是每次使用数据库时.我认为这是一个相当昂贵的操作,你不希望这发生.使用Global.asax Application_Start或DataContext类中的静态构造函数可确保在启动应用程序时仅调用一次代码. (6认同)