ASP.NET没有魔法——ASP.NET MVC 与数据库之EntityFramework配置与连接字符串
前几篇文章中介绍了如何使用Entity Framework来操作数据库,但是对EF的配置、连接字符串的指定仍然存在一些疑问,EF可以通过两种方式来实现配置,分别是代码方式和配置文件。
本章将通过以下几点对EF的配置进行介绍:
●Entity Framework的配置文件
●EntityFramework节点解析
●关于ConnectionString
●使用代码方式修改配置
●根据实际需求选择适合的配置方式
Entity Framework的配置文件
对于配置文件来说,在安装Entity Framework的时候将会自动在配置文件中插入以下内容:
首先是ConfigSection:
ConfigSection是.Net程序用来自定义配置节点的节点,所以这个节点的作用是告诉.Net程序有一个自定义的配置节点,自定义节点的名称和类型是什么。
名称很好理解就是接下来的entityFramework节点,但是类型指的是什么呢?
类型指的是用于处理名称所指配置信息的处理器,下面代码是上面配置的节点类型定义:
里面的内容与配置文件是有关联的,如何自定义配置节点可参考:https://msdn.microsoft.com/en-us/library/2tw134k3.aspx
EntityFramework节点解析
EntityFramework节点下主要有providers、interceptors、contexts、defaultConnectionFactory,基本上与EntityFrameworkSection类型是对应的。
1. providers:
根据类型EntityFrameworkSection定义来看,providers是一个provider的集合,而每一个provider的配置分别需要provider的名称(不变的用于做标识)、类型(提供器所在的命名空间和程序集)。以下是默认的SqlServer提供器:
2. interceptors:
拦截器,也是一个列表,每一个interceptors提供类型(命名空间和程序集名称)以及相应的参数来完成配置,以下是EF自带的日志拦截器。
以下是加入日志拦截器的运行效果:
注:所谓拦截器是一种面向切面(AOP)的编程方式,是一种不修改源代码的前提下对应用程序进行拓展的编程方式。一般AOP用来处理日志记录、性能统计、安全控制、事务处理、异常处理等不会对原有业务数据进行修改的功能。
3. contexts:
contexts节点下可以存在多个context节点,该节点用于数据库初始化,默认情况下DbContext在初始化的时候如果没有数据库会自动创建。如果不需要可以在配置文件中加入如下配置禁用:
可以使用databaseInitializer元素来设置数据库自定义初始化(以下是官方文档例子):
或者数据库的自动迁移(官方文档例子):
4. defaultConnectionFactory
defaultConnectionFactory会指定一个默认的连接工厂,这个连接工厂当使用代码优先的时候去查找一个数据库给DbContext使用(注:当DbContext不存在数据库连接字符串的时候才会生效)。
当通过Nuget来安装EF包的时候会根据本机情况来注册一个默认的ConnectionFactory,SQL Express或者LocalDb(注:所以说一个新建的MVC带身份验证的模板项目有数据存储机制,这个机制就可能是有SQL Express或者LocalDb来实现的)。以下配置就是基于LocalDb的,主要有Factory类型和参数
如果没有设置defaultConnectionFactory那么默认将使用SqlConnectionFactory(注:所以在没有配置的情况下则使用SQL Server数据库)。
SqlConnectionFactory也可以在defaultConnectionFactory中配置,它可以通过参数来指定一个连接字符串,这样就不需要连接字符串了:
关于ConnectionString
关于ConnectionString上面介绍了defaultConnectionFactory是不存在数据库连接字符串的时候才生效,那么数据库连接字符串要如何处理呢?DbContext又如何来判断连接字符串是否存在?以下就是连接字符串选择的逻辑:
1. 当没有配置任何连接字符串(包括默认连接工厂和ConnectionString节点),DbContext使用无参构造方法时,DbContext将默认使用DbContext所在命名空间和DbContext类型名称来作为数据库名称(如本例中将会是:BlogRepository.BlogDbContext),然后创建一个连接到SQL Express或LocalDb数据库连接前者优先使用。
注:SQL Express和LocalDb都可以看作是SQL Server数据库的开发者使用版本。
2. 在DbContext的构造方法中指定数据库名称(注意必须在基类型的构造中指定),那么将使用指定的名称,然后创建一个连接到SQL Express或LocalDb数据库连接前者优先使用。
3. 在DbContext的构造方法中指定数据库连接字符串(注意必须在基类型的构造中指定),那么将使用该字符串,并且默认使用System.Data.SqlClient作为提供器,即通过这种方式指定连接字符串默认使用SQL Server,如果要使用其它数据库需要更改context.Database.DefaultConnectionFactory的设置。
4. 在web.config/app.config文件中配置了连接字符串后,如果DbContext的类型名称与连接字符的name属性相同(无论是否包含全命名空间)或者在基类构造方法中指定了连接字符串的名称,那么都将使用这个配置信息来作为连接字符串。
详情参考:https://msdn.microsoft.com/en-us/library/jj592674(v=vs.113).aspx
使用代码方式修改配置
以上主要是对EF中的提供器provider、拦截器interceptor、默认连接工厂defaultConnectionFactory以及数据库初始化Context的配置进行了介绍,对于这些内容都可以通过代码的方式来完成配置,但要注意的是代码的配置会被配置文件的配置覆盖,如果相同配置存在代码和配置文件中,那么配置文件的生效。
1. 定义一个类型继承至System.Data.Entity.DbConfiguration。
2. 为该类型创建一个无参公共构造方法。
3. 在构造方法中调用一系列保护方法完成配置。
4. 在DbContext类型上使用DbConfigurationType特性:
注:此处的连接字符串数据库名称需要通过DbContext基类传入,否则使用{命名空间.DbContext}名称作为数据库名。
5. 删除所有与EF相关的配置然后运行程序:
根据实际需求选择适合的配置方式
在本例中因为存在多个数据库解决方案,所以会存在多套配置,而且它们都共用同一个MVC程序,所以每次切换数据库时如果把配置文件放在web.config中都需要修改相应的EF配置,所以应该尽量把不易变的配置写在程序中。
对于拦截器应该写在配置文件中,因为它可能会随意的被添加和删除。
其次数据库连接字符串是会经常改变的,比如环境变化、数据库账号密码变更等,所以也应该放在配置文件中。
根据以上分析对My Blog程序修改如下:
1. 在配置类型中定义provider:
2. 在web.config文件中加入EF配置,但仅配置拦截器:
3. 添加数据库连接字符串:
4. 在DbContext类型上使用DbConfigurationType特性:
5. 运行结果:
小结
本章主要是介绍了EF的配置,分别用配置文件和代码的方式实现了EF配置,当使用代码配置时,MVC项目不再需要加入任何EF配置即可运行应用程序。了解配置文件有利于了解EF的运行机制,也便于将数据库变更至MySQL。
在微软文档中有这样一句话:
Entity Framework allows a number of settings to be specified from the configuration file. In general EF follows a ‘convention over configuration’ principle. All the settings discussed in this post have a default behavior, you only need to worry about changing the setting when the default no longer satisfies your requirements.
意思是说EF遵循约定优先配置原则,所有的配置都有默认的行为,一般如果没有特殊需求不需要修改配置。
参考:
https://msdn.microsoft.com/en-us/library/jj556606(v=vs.113).aspx
https://msdn.microsoft.com/en-us/library/jj680699(v=vs.113).aspx
https://msdn.microsoft.com/en-us/library/jj592674(v=vs.113).aspx
作者:7m鱼
出处:http://www.cnblogs.com/selimsong/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。