简体   繁体   English

使用Database.SetInitializer避免Shotgun手术

[英]Avoiding Shotgun Surgery with Database.SetInitializer

The canonical answer on where to put Database.SetInitializer calls is in Global.asax for web projects. 关于在哪里放置Database.SetInitializer调用的规范答案Global.asax用于Web项目。 I'm looking for another option. 我正在寻找另一种选择。

We're using Entity Framework 4.3.1 with Code First. 我们正在使用Entity Framework 4.3.1和Code First。 We write web services and WinForms applications, and typically put data access code (such as DbContexts) in shared libraries. 我们编写Web服务和WinForms应用程序,并且通常将数据访问代码(例如DbContexts)放在共享库中。

Currently, the constructors of our DbContext descendants look like this: 目前,我们的DbContext后代的构造函数如下所示:

public PricingContext(string connectionString)
    : base(connectionString)
{
    Database.SetInitializer<PricingContext>(null);
}

95% of the time, that's the right default. 95%的时间,这是正确的默认值。 5% of the time (some integration tests, greenfield development, etc.) it's not. 5%的时间(某些集成测试,绿地开发等)并非如此。

If we move that code into the initialization (or configuration) of our services and applications, adding a new DbContext to a library involves Shotgun Surgery . 如果我们将该代码移动到我们的服务和应用程序的初始化(或配置)中,则向库中添加新的DbContext涉及Shotgun Surgery All of these projects have to be updated, even if the library doesn't expose the context directly. 即使库未直接公开上下文,也必须更新所有这些项目。

Optional arguments are one possibility: 可选参数是一种可能性:

public PricingContext(string connectionString,
    IDatabaseInitializer<PricingContext> databaseInitializer = null)
    : base(connectionString)
{
    Database.SetInitializer<PricingContext>(databaseInitializer);
}

Overriding the default strategy might involve passing the initializer through multiple layers, though. 但是,覆盖默认策略可能涉及将初始化程序传递给多个层。

We've also considered creating a reflection-based initializer that would set all contexts to a specific strategy. 我们还考虑创建一个基于反射的初始化器,它将所有上下文设置为特定策略。

What's the best practice? 什么是最佳做法?

How about creating a DBContextBootstrapper class that you can instantiate in Global.asax of every project; 如何创建一个可以在每个项目的Global.asax中实例化的DBContextBootstrapper类; which in its implementation sets initializer for every context. 在其实现中为每个上下文设置初始化程序。

This way if you add a new dbcontext you have to make change in the bootstrapper only, not in every project. 这样,如果添加新的dbcontext,则必须仅在引导程序中进行更改,而不是在每个项目中进行更改。

EF 4.3 (and newer) also includes possibility to define initializer from configuration file so you will not need to set it in code at all but it will still require you to maintain multiple configs. EF 4.3(和更新版本)还包括从配置文件定义初始化程序的可能性,因此您根本不需要在代码中设置它,但它仍然需要您维护多个配置。

@Hasan's advice looks like the best solution for you. @ Hasan的建议看起来是最适合您的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Database.SetInitializer中的DropCreateDatabaseIfModelChanges - DropCreateDatabaseIfModelChanges in Database.SetInitializer Database.SetInitializer是否不播种数据库? - Database.SetInitializer is not seeding the database? 放置Database.SetInitializer的地方 - Place to put Database.SetInitializer Database.SetInitializer(new MigrateDatabaseToLatestVersion <Context, Configuration> ()); 错误 - Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Configuration>()); Error Database.SetInitializer的目的 <ArContext> (null)在存储库中? - purpose of Database.SetInitializer<ArContext>(null) inside of repository? 为什么EF4.1 CodeFirst即使没有“ Database.SetInitializer &lt;&gt;()”调用也会创建数据库? - Why is EF4.1 CodeFirst is creating a database even without a `Database.SetInitializer<>()` call? 我可以将我的Database.SetInitializer调用放入具有基本字符串而不是静态构造函数的上下文构造函数中吗? - Can I put my Database.SetInitializer call in the context constructor with the base string instead of a static constructor? 在 MySql.Data.EntityFrameworkCore 中找不到数据库 SetInitializer - Database SetInitializer is not found in MySql.Data.EntityFrameworkCore WebSecurity.InitializeDatabaseConnection,SetInitializer和Database.Initialize - WebSecurity.InitializeDatabaseConnection, SetInitializer and Database.Initialize 避免有关Uris的数据库信息 - Avoiding database information on Uris
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM