,那么我們整個項目里面上下文的實例會有很多個,我們又遇到了多次,當我們在編程的時候遇到多的時候,一般我們就要想想能不能解決多這個問題。
(2)這里我要說的是EF上下文怎么管理呢?很簡單啦,就是要保證線程內唯一,所以這里我們就要進行修改BaseRepository類了。
(3) 在這里BaseRepository倉儲的職責是什么?他的職責就是幫我們實現了所有子倉儲的公共方法(增刪查改),他的職責不包含怎么去管理上下文的實 例,所以我們不能把這種控制上下文實例的線程內唯一的代碼放在這個位置,這就是我們每個類的職責必須唯一,面向對象中的一點就是類的職責必須單一。
(4)下面看一下我們修改后的BaseRepository(倉儲),這里我只列出一小部分,因為下面的都沒有變化
1 namespace LYZJ.UserLimitMVC.DAL 3 { 5 /// <summary> 7 /// 實現對數據庫的操作(增刪改查)的基類 9 /// </smmary> 11 /// <typeparam name="T">定義泛型,約束其是一個類</typeparam> 13 public class BaseRepository<T> where T : class 15 { 16 17 //創建EF框架的上下文 19 //EF上下文的實例保證線程內唯一 21 //private DataModelContainer db = new DataModelContainer(); 25 private DbContext db = EFContextFactory.GetCurrentDbContext(); 26 27 // 實現對數據庫的添加功能,添加實現EF框架的引用 28 29 public T AddEntity(T entity) 31 { 32 33 //EF4.0的寫法 添加實體 35 //db.CreateObjectSet<T>().AddObject(entity); 37 //EF5.0的寫法 39 db.Entry<T>(entity).State = EntityState.Added; 41 //下面的寫法統一 43 db.SaveChanges(); 45 return entity; 47 } 49 } 51 }
(5)那么我們怎么控制上下文的實例並且要求它是線程內唯一呢?這時候我們不能放到BaseRepository(倉儲)中去設置,這時候我們就想到了封裝,我們將控制上下文的實例並且要求它是線程內唯一的代碼封裝到一個公共的類中。這時候怎么做呢?請看下面的做法
(6) 這時候我們看到上面的代碼我們不能直接new來實現了(//private DataModelContainer db = new DataModelContainer();),那么我們怎么獲取這個實例呢?重點是在這里獲取實例的地方必須是公共的,而且還要能夠幫我們管理線程內唯 一,這時候我們可以想到我們能夠通過工廠來實現這個實例,那么我們在這里創建一個EFContextFactory工廠,在這個工廠里面有 GetCurrentDbContext()方法來返回實例( private DbContext db = EFContextFactory.GetCurrentDbContext();)。
那么這時候我們就需要創建上面的類了。
6.EFContextFactory
(1)這時候我們在LYZJ.UserLimitMVC.DAL類庫下面再建立一個EFContextFactory類,在這個類里面含有GetCurrentDbContext方法,下面我解釋一下這些代碼的實現,我們實現這個方法的代碼是:
namespace LYZJ.UserLimitMVC.DAL
{
public class EFContextFactory
{
//幫我們返回當前線程內的數據庫上下文,如果當前線程內沒有上下文,那么創建一個上下文,並保證
//上線問實例在線程內部是唯一的
public static DbContext GetCurrentDbContext()
{
//CallContext:是線程內部唯一的獨用的數據槽(一塊內存空間)
//傳遞DbContext進去獲取實例的信息,在這里進行強制轉換。
DbContext dbContext = CallContext.GetData("DbContext") as DbContext;
if (dbContext == null) //線程在數據槽里面沒有此上下文
{
dbContext = new DataModelContainer(); //如果不存在上下文的話,創建一個EF上下文
//我們在創建一個,放到數據槽中去
CallContext.SetData("DbContext", dbContext);
}
return dbContext;
}
}
}