大神勿噴,小神默默學。
會了就是不值一提的東西,不會就是絕對的高大上。
最后上傳源碼。希望能給讀者帶來一些新的認識及知識。
還沒上過頭條。。各位大神,請點支持一下小弟。
陸續更新。更新到你會為止!!
我不是話嘮,我只把重點點出來,細枝末節的不懂的可以留言探討。這個系列的最后,我會再統一的把大家的問題,列在一篇新的Blog。工作需要規划,寫博客也是如此。
需求
①請保持EF上下文的線程唯一。防止臟臨時數據的出現
②請對程序擴展性做好設計。以后ef框架可能改為Spring框架
③服務層調用倉儲層時。DBContext為統一入口
③.1 方便程序員開發,提供統一入口。把ef封裝到此入口里面。
③.2防止臟臨時數據的出現,“也”請保持這個入口的線程內唯一。
③.3要這個統一入口去除服務層和倉儲層的耦合
思路
①把ef放進CallContext內。鍵值對形式存放。
②面向接口的思想
新建一個工廠接口+工廠。用一個“工廠方法”模式,非“簡單工廠”,也非“抽象工廠”設計模式。如果您對工廠的幾個設計模式不了解,請參考我寫過的設計模式一篇blog。
③ ③.1新建一個類,命名DBContact里面的一個屬性類型為ObjectContext,因為上下文繼承ObjectContext,繼而“點”多個倉儲。
③.2放進CallContext內。鍵值對存儲。
③.3新建一個IDBContact接口,讓DBContact繼承。用一個工廠繼承一個接口工廠創建。“工廠方法”設計模式
思想
面向接口+工廠模式+線程唯一 2個抽象方法工廠作用:線程唯一+擴展性(面向接口)
詳情代碼
ISingleEFCntextFactory.cs
using System.Data.Objects; namespace LKBS.CommunicationPlatform.IDAL { public interface ISingleEFCntextFactory {//no public ObjectContext GetCurrentEFContext(); } }
SingleEFCntextFactory.cs
using LKBS.CommunicationPlatform.IDAL; using System.Data.Objects;//添加引用 System.Data.Entity using System.Runtime.Remoting.Messaging; using LKBS.CommunicationPlatform.Model; namespace LKBS.CommunicationPlatform.Factory { public class SingleEFCntextFactory : ISingleEFCntextFactory { public ObjectContext GetCurrentEFContext() { //把上下文(基類)放在一個線程內。讓一次請求(一個ACTION)可能執行CRUD中的幾步,公用一個上下文. ObjectContext callEFContext = (ObjectContext)CallContext.GetData("efContext");//線程槽 存放“鍵值對” //先讀后寫。沒有就new一個上下文 if (callEFContext == null) { callEFContext = new ModelContainer(); } CallContext.SetData("efContext", callEFContext); return callEFContext; } } }
BaseRespository.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Entity; using LKBS.CommunicationPlatform.Model; using LKBS.CommunicationPlatform.IDAL; using System.Data; using LKBS.CommunicationPlatform.Factory; using System.Data.Objects; namespace LKBS.CommunicationPlatform.DAL { public class BaseRespository<T> where T : class,new() { ISingleEFCntextFactory singleEFFactory = new SingleEFCntextFactory(); //中間加一個工廠,這里“去除”ef和具體倉儲的耦合。可以更換ef。而Respositiry db不用變 ObjectContext db;//如果沒賦值,那就是賦值的問題。找對應賦值的工廠 或者工廠還沒編譯 public BaseRespository() { ObjectContext db = singleEFFactory.GetCurrentEFContext(); } //ModelContainer db = efFactory.GetCurrentEFContext(); //字段初始值無法引用非靜態字段、方法或屬性. //那我們在構造方法內賦值 ....CRUD } }
為方便業務邏輯層調用,建立統一入口。
IDBContact.cs
using System.Data.Objects;//上下文在的空間 namespace LKBS.CommunicationPlatform.IDAL { public interface IDBContact { //接口中的屬性要{} ObjectContext currentEFContext { get; set; } IUserInforRespository userinforResponsity { get; set; } //...多個其他表的倉儲,在T4模板中加OK } }
DBContact.cs
using LKBS.CommunicationPlatform.IDAL; using System.Data.Objects;//上下文的命名空間 using LKBS.CommunicationPlatform.Factory; namespace LKBS.CommunicationPlatform.DAL { public class DBContact : IDBContact { public ObjectContext currentEFContext { get; set; } ISingleEFCntextFactory singleEFCntextFactory = new SingleEFCntextFactory();//SingleEFCntextFactory做到單一上下文 public DBContact() { currentEFContext = singleEFCntextFactory.GetCurrentEFContext();// } public IUserInforRespository userinforResponsity { get; set; } } }
ISingleDBContactFactory.cs
namespace LKBS.CommunicationPlatform.IDAL { public interface ISingleDBContactFactory { IDBContact CreateDBCotactUseEF(); } }
SingleDBContactFactory.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using LKBS.CommunicationPlatform.IDAL; using System.Data.Objects; using System.Runtime.Remoting.Messaging; using LKBS.CommunicationPlatform.DAL; namespace LKBS.CommunicationPlatform.Factory { //繼承接口①接口要編譯過,②引入接口所用的程序集+ using class SingleDBContactFactory : ISingleDBContactFactory { public IDBContact CreateDBCotactUseEF() { //ObjectContext currentEFContext = new ObjectContext("currentEFContext"); //return currentEFContext; IDBContact dbCotact = (DBContact)CallContext.GetData("currentDBContact"); if (dbCotact==null) { dbCotact = new DBContact(); } CallContext.SetData("currentDBContact", dbCotact); return dbCotact; } } }