EF 数据库连接约定(Connection String Conventions in Code First)
一个典型的EF应用大多数情况下是一个DbContext的派生类(derived class)来控制,通常可以使用该派生类调用DbContext的构造函数,来控制以下的东西:
(1)、上下文如何连接到数据库(给定连接字符串)
(2)、上下文是通过Code First语法计算模型还是使用EF 设计器
(3)、额外的高级选项
下面是DbContext构造器的常用的用途:
一、DbContext无参构造函数
如果当前EF应用中没有做任何的配置.且在你自定义的数据库上下文类中没有调用DbContext带参的构造函数,那么当前应用对应的数据库上下文类,将会调用DbContext的默认无参的构造函数(EF默认规定的数据库连接),代码如下:
namespace Demo.EF { public class EFStudyContext : DbContext { public EFStudyContext()// C# will call base class parameterless constructor by default { } } }
EF默认的联结字符串如下:
Data Source=(localdb)\mssqllocaldb;Initial Catalog=EFStudyConsole(项目名称).EFStudyDbContext(上下文名称);Integrated Security=True;MultipleActiveResultSets=True
EF会用上下文的完全限定名(命名空间+上下文类)作为数据库名,创建一个连接字符串,该连接字符串会连接本地的SQL Express或者LocalDb,并在SQL Express或者LocalD创建对应的数据库,如果两者都安装了,则会选择连接SQL Express。
注:VS2010默认安装SQL Express,VS2012默认安装LocalDb,在安装过程中,EF NuGet包会检查哪个数据库服务(前面介绍的)可用,当EF创建默认连接的时候,当EF创建默认链接的时候,NuGet包将通过设置默认的Code First数据库服务器来更新配置文件,该数据库服务器在通过约定创建连接时首先使用该服务器。.如果SQL Express 正在运行,它会被使用,如果它不可用,LocalDb会替代它,但是这个过程不会对配置文件做任何的更改,如果它已经包含默认连接工厂的设置.
二、DbContext带string参数的构造函数
1、如果没有在数据库上下文进行其他额外的配置,然后调用DbContext中的带参的构造函数,传入你想要使用的数据库连接字符串,然后Code First中的数据库上下文就会运行在基于当前数据库连接字符串上.代码如下:
public class BloggingContext : DbContext { public BloggingContext(): base("BloggingDatabase") {} }
Data Source=(localdb)\mssqllocaldb;Initial Catalog=BloggingDatabase;Integrated Security=True;MultipleActiveResultSets=True
2、使用app.config/web.config配置文件中的连接字符串,表示你在应用程序中已经进行了配置,这一点要区分上面的方法.
(1)、有Ado.Net使用经历的都知道,一般情况下,数据库连接字符串一般定义在app.config/web.config配置文件中,例如:
<configuration> <connectionStrings> <add name="BolggingContext" providerName="System.Data.SqlServerCe.4.0" connectionString="Data Source=Blogging.sdf"/> </connectionStrings> </configuration>
这在EF中相当于告诉数据库上下文去使用当前连接字符串对应的数据库服务,而不是使用SQL Express or LocalDb,数据库上下文代码如下:
public class BloggingContext : DbContext { public BloggingContext() { } }
如果连接字符串的name属性值和上下文类名一样(either with or without namespace qualification),那么数据库上下文在执行无参构造函数的时候,会使用配置文件的连接字符串去连接数据库.
using (var context=new BloggingContext()) { string connStr = context.Database.Connection.ConnectionString; Console.WriteLine(connStr); }
(2)、如果连接字符串的name属性值和上下文类名不一样,但是还是希望上下文使用配置文件的数据库连接进行数据库连接,这时就需要在上下文构造函数中调用DbContext的带string参数的构造函数,并传入连接字符串的name属性值,代码如下:
public class BloggingContext:DbContext { public DbSet<User> Users { get; set; } public BloggingContext():base("BloggingStr") { } } static void Main(string[] args) { using (var context=new BloggingContext()) { string connStr = context.Database.Connection.ConnectionString; Console.WriteLine(connStr); } Console.ReadKey(); }
另外一种方式是传递给DbContext构造函数配置文件中的connectionString节点的name属性来指定上下文通过配置文件中connectionString来连接字符串,代码如下:
public class BloggingContext:DbContext { public DbSet<User> Users { get; set; } public BloggingContext():base("name=BloggingStr") { } } static void Main(string[] args) { using (var context=new BloggingContext()) { string connStr = context.Database.Connection.ConnectionString; Console.WriteLine(connStr); } Console.ReadKey(); }
上面这种方式是明确EF进行数据库连接的时候去配置文件找连接字符串。
(3)、连接字符串的终极解决方案,直接给连接字符串,什么都不要配,代码如下:
public class BloggingContext:DbContext { public DbSet<User> Users { get; set; } public BloggingContext():base("server=.;database=EFStudy;uid=sa;pwd=123456;") { } } static void Main(string[] args) { using (var context=new BloggingContext()) { string connStr = context.Database.Connection.ConnectionString; Console.WriteLine(connStr); } Console.ReadKey(); }
注:默认情况下,当前的连接字符串使用的是System.Data.SqlClilent作为provider,这里可以被改变通过做一个IConnectionFactory的不同的实现来替换context.Database.DefaultConnectionFactory默认的实现.
三、还有其他两种方法,不常用
1、You can use an existing DbConnection object by passing it to a DbContext constructor. If the connection object is an instance of EntityConnection, then the model specified in the connection will be used rather than calculating a model using Code First. If the object is an instance of some other type—for example, SqlConnection—then the context will use it for Code First mode.
使用一个DbConnection 实例,或者是SqlConnection实例或者EntityConnection实例,传递给DbContext的构造函数均可指定对应的数据库连接规则.
2、You can pass an existing ObjectContext to a DbContext constructor to create a DbContext wrapping the existing context. This can be used for existing applications that use ObjectContext but which want to take advantage of DbContext in some parts of the application.