日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

我所理解的IRepository

發(fā)布時間:2023/12/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 我所理解的IRepository 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
最近有一個項目采用了EntityFramework,對于基本的增刪改查操作,我們采用了傳統(tǒng)的倉儲模式(IRepository),但對于項目中的倉儲接口的定義及實現(xiàn)上我認為存在部分缺陷。這個創(chuàng)建模式是以前同事編寫好的,然后我們在新項目中利用它。
?? ?
??? 分頁查詢接口。
? ? ?

??? 接口定義:

IEnumerable<T>?QueryByPage(Func<T,?bool>?FunWhere,?Func<T,?string>?FunOrder,?int?PageSize,?int?PageIndex,?out?int?recordsCount); ???

  接口實現(xiàn):

? ?

??????? public?IEnumerable<T>?QueryByPage(Func<T,?bool>?FunWhere,?Func<T,?string>?FunOrder,?int?PageSize,?int?PageIndex,?out?int?recordsCount)
????????{
????????????recordsCount?=?context.Set<T>().Where(FunWhere).OrderByDescending(FunOrder).Count();
????????????return?context.Set<T>().Where(FunWhere).OrderByDescending(FunOrder).Select(t?=>?t).Skip((PageIndex?-?1)?*?PageSize).Take(PageSize);
????????}

??? 缺陷一:對于倉儲接口,集合返回IEnumerable。
??? 如果返回的是IEnumerable,那么實際上,系統(tǒng)會將表中的所有數(shù)據(jù)加載到內存中,然后再進行條件過濾,排序,再分頁。如果表記錄稍微多一點的話,性能可想而知。此種情況下應該推薦返回IQueryable,它才是真正適合和數(shù)據(jù)庫打交道的對象。在客戶端應用程序沒有訪問實際對象值之前,比如ToList()操作,它只是一個編譯過程,根據(jù)用戶傳入的參數(shù)構建查詢計劃最終生成用于查詢所用的SQLScript腳本。這種方式才是真正意義上的按需所取。
?? ?
??? 下面我們來定義一個新接口:
???

IQueryable<T>?Query(Expression<Func<T,?bool>>?filter);

??? 注意這里是一個開放性特別大的查詢接口,如果說不要輕易為客戶端開放IQueryable這也沒也問題,而且也不推薦將倉儲接口直接開放給客戶端應用程序,應該在倉儲接口上為每個特定的應用系統(tǒng)提供全新的接口,比如可以這樣:
???

??? public?interface?Iaspnet_UsersRepository
????{
????  ?????? List<aspnet_UsersModel>?QueryByPage(Expression<Func<T,?bool>>?filter,?Expression<Func<T,?string>>?FunOrder,?int?PageSize,?int?PageIndex,?out?int?recordsCount);
????}

??? 這里為了演示方便,就直接調用倉儲接口做測試。?
?? ?
??? IEnumerable調用代碼:
???

var?list?=?service.QueryByPage(p?=>?p.UserId?!=?Guid.Empty,p=>p.UserName,1,1,out?recordsCount).ToList();

??? IEnumerable情況下生成的腳本:
???

SELECT
[Extent1].[UserId]?AS?[UserId],
[Extent1].[UserName]?AS?[UserName],
[Extent1].[LoweredUserName]?AS?[LoweredUserName],
[Extent1].[MobileAlias]?AS?[MobileAlias],
[Extent1].[IsAnonymous]?AS?[IsAnonymous],
[Extent1].[LastActivityDate]?AS?[LastActivityDate]
FROM?[dbo].[aspnet_Users]?AS?[Extent1]

 
IQueryable調用

var?list?=?service.Query(p=>p.UserId!=Guid.Empty).OrderBy(p=>p.UserName).Take(1).Skip(1).ToList();

??? IQueryable情況下生成的腳本
?

View Code exec?sp_executesql?N'SELECT
[Limit1].[UserId]?AS?[UserId],
[Limit1].[UserName]?AS?[UserName],
[Limit1].[LoweredUserName]?AS?[LoweredUserName],
[Limit1].[MobileAlias]?AS?[MobileAlias],
[Limit1].[IsAnonymous]?AS?[IsAnonymous],
[Limit1].[LastActivityDate]?AS?[LastActivityDate]
FROM?(?SELECT?[Limit1].[UserId]?AS?[UserId],?[Limit1].[UserName]?AS?[UserName],?[Limit1].[LoweredUserName]?AS?[LoweredUserName],?[Limit1].[MobileAlias]?AS?[MobileAlias],?[Limit1].[IsAnonymous]
AS?[IsAnonymous],?[Limit1].[LastActivityDate]?AS?[LastActivityDate],?row_number()?OVER?(ORDER?BY?[Limit1].[UserName]?ASC)?AS?[row_number]
????FROM?(?SELECT?TOP?(1)?[Project1].[UserId]?AS?[UserId],?[Project1].[UserName]?AS?[UserName],?[Project1].[LoweredUserName]?AS?[LoweredUserName],?[Project1].[MobileAlias]?AS
[MobileAlias],?[Project1].[IsAnonymous]?AS?[IsAnonymous],?[Project1].[LastActivityDate]?AS?[LastActivityDate]
????????FROM?(?SELECT
????????????[Extent1].[UserId]?AS?[UserId],
????????????[Extent1].[UserName]?AS?[UserName],
????????????[Extent1].[LoweredUserName]?AS?[LoweredUserName],
????????????[Extent1].[MobileAlias]?AS?[MobileAlias],
????????????[Extent1].[IsAnonymous]?AS?[IsAnonymous],
????????????[Extent1].[LastActivityDate]?AS?[LastActivityDate]
????????????FROM?[dbo].[aspnet_Users]?AS?[Extent1]
????????????WHERE?[Extent1].[UserId]?<>?@p__linq__0
????????)??AS?[Project1]
????????ORDER?BY?[Project1].[UserName]?ASC
????)??AS?[Limit1]
)??AS?[Limit1]
WHERE?[Limit1].[row_number]?>?0
ORDER?BY?[Limit1].[UserName]?ASC
',N'@p__linq__0?uniqueidentifier',@p__linq__0='00000000-0000-0000-0000-000000000000'


??? 小結:

????????? 只有返回IQueryable,才會實現(xiàn)按需所取。盡管這個方法在最上層的服務層沒有進行封裝,理論上客戶端應用程序無法訪問到此方法,但既然提供了,而且對外是Public,那么在一定程度上就會對程序員造成誤導。
???

 缺陷二:不太實用的接口定義
??? 我們來看一下這個接口定義
??

IEnumerable<T>?QueryByPage(List<KeyValuePair<string,?object>>?queryWhere,?List<KeyValuePair<string,?int>>?funOrder,?int?PageSize,?int?PageIndex,?out?int?recordsCount)

??? 再看下它的實現(xiàn),可以看出這個方法實現(xiàn)了按需所取,但這是多么的不協(xié)調啊(上面那個分頁方法就不是按需所取)。就像有人做事一樣,50%的工作可以打100分,其余的50%只能打60分,而且這40分很容易得到。
???

View Code string?objName?=?string.Empty;
????????????Type?type?=?typeof(T);
????????????var?properties?=?Context.GetType().GetProperties();
????????????foreach?(var?propertyInfo?in?properties)
????????????{
????????????????if?(propertyInfo.PropertyType.GetGenericArguments()[0].Name?==?type.Name)
????????????????{
????????????????????objName?=?propertyInfo.Name;
????????????????????break;
????????????????}
????????????}
????????????string?queryObj?=?EntitySQLGenerator.GenerateQuery(queryWhere,?funOrder,?Context.DefaultContainerName,?objName);
????????????IQueryable<T>?result?=?Context.CreateQuery<T>(queryObj);
????????????recordsCount?=?result.Count();
????????????return?result.Select(t?=>?t).Skip((PageIndex?-?1)?*?PageSize).Take(PageSize).AsEnumerable<T>();

?? 查詢條件難以理解
?? List<KeyValuePair<string, object>>,用戶根本不知道需要傳遞什么參數(shù),提供的接口參數(shù)一定要讓調用者容易理解。
?? ?
?? 我理解的倉儲接口

?? 如果還有哪些不夠的,可以根據(jù)情況再決定增加哪些功能。創(chuàng)建接口不推薦直接開放給客戶端,應該在此基礎上重新為每個應用定義接口。
??

??? public?interface?IMyRepository<T>?where?T?:?class,?new()
????{
????????T?Create();
????????T?Update(T?entity);
????????T?Insert(T?entity);
????????void?Delete(T?entity);
????????List<T>?FindAll();
????????IQueryable<T>?Query(Expression<Func<T,?bool>>?filter);
????}

?

轉載于:https://www.cnblogs.com/ASPNET2008/archive/2012/06/30/2571503.html

總結

以上是生活随笔為你收集整理的我所理解的IRepository的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。