一、概述
Entity Framework
可以在配置文件(app.config/web.config)中指定实体框架应用程序的配置,也可以通过代码进行指定。后者称为基于代码的配置。
本博文将介绍配置文件中的配置。配置文件优于基于代码的配置。换而言之,如果在代码和配置文件中都有配置选择,则使用配置文件中的配置。
博文讨论仅限于EF6及更高的版本,此页面中讨论的功能,API等已引入实体框架6。如果使用的是早期版本,则部分或全部信息不适用。
二、使用DbConfiguration
EF6和更高版本中基于代码的配置是通过创建System.Data.Entity.Config.DbConfiguration
的子类实现的。设置DbConfiguration的子类时,需要遵循以下标准:
- 仅为应用程序创建一个
DbConfiguration
类。此类指定应用域范围内的设置。 - 将
DbConfiguration
类放在与DbContext
类相同的程序集中。 - 为
DbConfiguration
类提供一个公共无参数构造函数。
- 通过从此构造函数内调用受保护的
DbConfiguration
方法来设置配置选项。
DbConfiguration使用实体
实例设置EF以使用SQL Azure 执行策略 - 自动重试失败的数据库操作,并对由 Code First 中的约定创建的数据库使用本地 DB。
using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Data.Entity.SqlServer; namespace MyNamespace { public class MyConfiguration : DbConfiguration { public MyConfiguration() { SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy()); SetDefaultConnectionFactory(new LocalDbConnectionFactory("mssqllocaldb")); } } }
三、动态使用DbConfiguration
并不是所有的配置,都会将DbConfiguation
类放在与DbContext
类相同的程序集中。如,不同的程序集中有两个DbContext
类。有两个选项可用于处理这种情况。
3/1. 配置文件指定要使用的DbConfiguration
实例
使用配置文件指定要使用的DbConfiguration实例,请设置entityFramework部分的CodeConfigurationType属性。
<entityFramework codeConfigurationType="MyNamespace.MyDbConfiguration, MyAssembly"> ...Your EF config... </entityFramework>
codeConfigurationType的值必须是DbConfiguration
类的程序集和命名空间限定名称。
3/2. 将DbConfigurationTypeAttribute放置在上下文类中
- 传递给特性的值为
DbConfiguation
类型
[DbConfigurationType(typeof(MyDbConfiguration))] public class MyContextContext : DbContext { }
- 程序集和命名空间限定的类型名称字符串
[DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssembly")] public class MyContextContext : DbContext { }
四、显示设置DbConfiguration
在使用任何DbContext
类型之前可能需要先进行配置。这种情况的示例包括:
- 使用
DbModelBuilder
生成没有上下文的模型 - 使用应用程序上下文之前,使用其他一些框架/实用程序代码,这些代码在使用该上下文的情况中利用
DbContext
。
在这种情况下,EF 无法自动发现配置,必须执行以下操作之一:
- 在配置文件中设置
DbConfiguration
,如上文中的移动DbConfiguration
部分中所述 - 在应用程序启动过程中调用静态
DbConfiguration
.SetConfiguration 方法
五、重新DbConfiguration
在使用DbConfiguration时,某些情况需要重写DbConfiguration中设置的配置。这通常不由应用程序开发人员完成,而是由不能使用派生的DbConfigration类的第三方提供程序和插件来完成。
为此,EntityFramework 允许注册事件处理程序,该事件处理程序可以在锁定之前修改现有配置。 它还提供专门用于替换 EF 服务定位器返回的任何服务的 sugar 方法。 下面是它的预期使用方法:
- 在应用启动(使用 EF 之前)时,插件或提供程序应为此事件注册事件处理程序方法。 (注意,此操作必须在应用程序使用 EF 之前进行。)
- 事件处理程序为需要替换的每个服务调用 ReplaceService。
例如,要替换 IDbConnectionFactory
和 DbProviderService
,需要注册类似于以下的处理程序:
DbConfiguration.Loaded += (_, a) => { a.ReplaceService<DbProviderServices>((s, k) => new MyProviderServices(s)); a.ReplaceService<IDbConnectionFactory>((s, k) => new MyConnectionFactory(s)); };
在上面的代码中,MyProviderServices
和 MyConnectionFactory
表示服务的实现。
五、总结
你还可以添加其他依赖关系处理程序来获得相同的效果。
请注意,你也可以通过这种方式包装 DbProviderFactory
,但这样做只会影响 EF,而不会影响在 EF 之外使用 DbProviderFactory
。 出于此原因,你可能会希望继续像以前一样包装 DbProviderFactory
。
还应记住在应用程序外部运行的服务 - 例如,从程序包管理器控制台运行迁移时。 从控制台运行迁移时,它会尝试查找 DbConfiguration。 但是,它是否将获得包装好的服务取决于它注册的事件处理程序的位置。 如果已将其注册为 DbConfiguration 的构造的一部分,则应执行代码并包装服务。 通常不会出现这种情况,这意味着工具不会获得包装好的服务。