來源:懶得安分 鏈接:http://www.cnblogs.com/landeanfen/p/4837520.html
前言:上篇介紹了下倉儲(chǔ)的代碼架構(gòu)示例以及簡單分析了倉儲(chǔ)了使用優(yōu)勢。本章還是繼續(xù)來完善下倉儲(chǔ)的設(shè)計(jì)。上章說了,倉儲(chǔ)的最主要作用的分離領(lǐng)域?qū)雍途唧w的技術(shù)架構(gòu),使得領(lǐng)域?qū)痈訉W㈩I(lǐng)域邏輯。那么涉及到具體的實(shí)現(xiàn)的時(shí)候我們應(yīng)該怎么做呢,本章就來說說倉儲(chǔ)里面具體細(xì)節(jié)方便的知識(shí)。
一、對倉儲(chǔ)接口以及實(shí)現(xiàn)基類的完善
1、倉儲(chǔ)實(shí)現(xiàn)基類的所有方法加上virtual關(guān)鍵字,方便具體的倉儲(chǔ)在特定需求的時(shí)候override基類的方法。
//倉儲(chǔ)的泛型實(shí)現(xiàn)類 public class EFBaseRepository : IRepositorywhere TEntity : AggregateRoot { [Import(typeof(IEFUnitOfWork))] public IEFUnitOfWork UnitOfWork { get; set; } public EFBaseRepository() { Regisgter.regisgter().ComposeParts(this); } public virtual IQueryable Entities { get { return UnitOfWork.context.Set(); } } public virtual TEntity GetByKey(object key) { return UnitOfWork.context.Set().Find(key); } public virtual IQueryable Find(Expressionbool>> express) { Funcbool> lamada = express.Compile(); return UnitOfWork.context.Set().Where(lamada).AsQueryable(); } public virtual int Insert(TEntity entity) { UnitOfWork.RegisterNew(entity); return UnitOfWork.Commit(); } public virtual int Insert(IEnumerable entities) { foreach (var obj in entities) { UnitOfWork.RegisterNew(obj); } return UnitOfWork.Commit(); } public virtual int Delete(object id) { var obj = UnitOfWork.context.Set().Find(id); if (obj == null) { return 0; } UnitOfWork.RegisterDeleted(obj); return UnitOfWork.Commit(); } public virtual int Delete(TEntity entity) { UnitOfWork.RegisterDeleted(entity); return UnitOfWork.Commit(); } public virtual int Delete(IEnumerable entities) { foreach (var entity in entities) { UnitOfWork.RegisterDeleted(entity); } return UnitOfWork.Commit(); } public virtual int Delete(Expressionbool>> express) { Funcbool> lamada = express.Compile(); var lstEntity = UnitOfWork.context.Set().Where(lamada); foreach (var entity in lstEntity) { UnitOfWork.RegisterDeleted(entity); } return UnitOfWork.Commit(); } public virtual int Update(TEntity entity) { UnitOfWork.RegisterModified(entity); return UnitOfWork.Commit(); } }
2、查詢和刪除增加了傳參lamada表達(dá)式的方法
倉儲(chǔ)接口:
public interface IRepositorywhere TEntity : AggregateRoot { //........... #region 公共方法 /// /// 根據(jù)lamada表達(dá)式查詢集合 /// /// lamada表達(dá)式 /// IQueryable Find(Expressionbool>> express); /// /// 根據(jù)lamada表達(dá)式刪除對象 /// /// lamada表達(dá)式 /// 操作影響的行數(shù) int Delete(Expressionbool>> express); //.......... }
倉儲(chǔ)的實(shí)現(xiàn)
//倉儲(chǔ)的泛型實(shí)現(xiàn)類 public class EFBaseRepository : IRepositorywhere TEntity : AggregateRoot { //............. public virtual IQueryable Find(Expressionbool>> express) { Funcbool> lamada = express.Compile(); return UnitOfWork.context.Set().Where(lamada).AsQueryable(); } public virtual int Delete(Expressionbool>> express) { Funcbool> lamada = express.Compile(); var lstEntity = UnitOfWork.context.Set().Where(lamada); foreach (var entity in lstEntity) { UnitOfWork.RegisterDeleted(entity); } return UnitOfWork.Commit(); } //............. }
增加這兩個(gè)方法之后,對于單表的一般查詢都可以直接通過lamada表示式的方法傳入即可,并且返回值為IQueryable類型。
3、對于涉及到多張表需要連表的查詢機(jī)制,我們還是通過神奇的Linq來解決。例如我們有一個(gè)通過角色取角色對應(yīng)的菜單的接口需求。
在菜單的倉儲(chǔ)接口里面:
/// /// 菜單這個(gè)聚合根的倉儲(chǔ)接口 /// public interface IMenuRepository:IRepository { IQueryable GetMenusByRole(TB_ROLE oRole); }
對應(yīng)倉儲(chǔ)實(shí)現(xiàn):
[Export(typeof(IMenuRepository))] public class MenuRepository:EFBaseRepository,IMenuRepository { public IQueryable GetMenusByRole(TB_ROLE oRole) { var queryrole = UnitOfWork.context.Set().AsQueryable(); var querymenu = UnitOfWork.context.Set().AsQueryable(); var querymenurole = UnitOfWork.context.Set().AsQueryable(); var lstres = from menu in querymenu from menurole in querymenurole from role in queryrole where menu.MENU_ID == menurole.MENU_ID & menurole.ROLE_ID == role.ROLE_ID && role.ROLE_ID == oRole.ROLE_ID select menu; return lstres; } }
這里也是返回的IQueryable接口的集合,千萬不要小看IQueryable接口,它是一種表達(dá)式樹,可以延遲查詢。也就是說,在我們執(zhí)行GetMenusByRole()之后,得到的是一個(gè)帶有查詢sql語句的表達(dá)式樹結(jié)構(gòu),并沒有去數(shù)據(jù)庫執(zhí)行查詢,只有在我們ToList()的時(shí)候才會(huì)去查詢數(shù)據(jù)庫。我們來寫個(gè)Demo測試下。
class Program { [Import] public IUserRepository userRepository { get; set; } [Import] public IMenuRepository menuRepository { get; set; } static void Main(string[] args) { //注冊MEF var oProgram = new Program(); Regisgter.regisgter().ComposeParts(oProgram); var lstFindUsers = oProgram.userRepository.Find(x => x.USER_NAME !=null); var lstRes = lstFindUsers.ToList(); var lstMenu = oProgram.menuRepository.GetMenusByRole(new TB_ROLE() { ROLE_ID = 'aaaa' }); var lstMenuRes = lstMenu.ToList(); } }
來看執(zhí)行過程:
當(dāng)程序執(zhí)行var lstMenu = oProgram.menuRepository.GetMenusByRole(new TB_ROLE() { ROLE_ID = “aaaa” })這一步的時(shí)候基本是不耗時(shí)的,因?yàn)檫@一步僅僅是在構(gòu)造表達(dá)式樹,只有在.ToList()的時(shí)候才會(huì)有查詢等待。
在dax.net的系列文章中,提到了規(guī)約模式的概念,用于解決條件查詢的問題。博主感覺這個(gè)東西設(shè)計(jì)確實(shí)牛叉,但實(shí)用性不太強(qiáng),一般中小型的項(xiàng)目也用不上。
|