一個典型的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.