我所理解的IRepository
?? ?
??? 分頁查詢接口。
? ? ?
??? 接口定義:
接口實現:
? ?
????????{
????????????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,那么實際上,系統會將表中的所有數據加載到內存中,然后再進行條件過濾,排序,再分頁。如果表記錄稍微多一點的話,性能可想而知。此種情況下應該推薦返回IQueryable,它才是真正適合和數據庫打交道的對象。在客戶端應用程序沒有訪問實際對象值之前,比如ToList()操作,它只是一個編譯過程,根據用戶傳入的參數構建查詢計劃最終生成用于查詢所用的SQLScript腳本。這種方式才是真正意義上的按需所取。
?? ?
??? 下面我們來定義一個新接口:
???
??? 注意這里是一個開放性特別大的查詢接口,如果說不要輕易為客戶端開放IQueryable這也沒也問題,而且也不推薦將倉儲接口直接開放給客戶端應用程序,應該在倉儲接口上為每個特定的應用系統提供全新的接口,比如可以這樣:
???
????{
???? ?????? List<aspnet_UsersModel>?QueryByPage(Expression<Func<T,?bool>>?filter,?Expression<Func<T,?string>>?FunOrder,?int?PageSize,?int?PageIndex,?out?int?recordsCount);
????}
??? 這里為了演示方便,就直接調用倉儲接口做測試。?
?? ?
??? IEnumerable調用代碼:
???
??? IEnumerable情況下生成的腳本:
???
[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調用
??? IQueryable情況下生成的腳本
?
[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,才會實現按需所取。盡管這個方法在最上層的服務層沒有進行封裝,理論上客戶端應用程序無法訪問到此方法,但既然提供了,而且對外是Public,那么在一定程度上就會對程序員造成誤導。
???
缺陷二:不太實用的接口定義
??? 我們來看一下這個接口定義
??
??? 再看下它的實現,可以看出這個方法實現了按需所取,但這是多么的不協調啊(上面那個分頁方法就不是按需所取)。就像有人做事一樣,50%的工作可以打100分,其余的50%只能打60分,而且這40分很容易得到。
???
????????????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>>,用戶根本不知道需要傳遞什么參數,提供的接口參數一定要讓調用者容易理解。
?? ?
?? 我理解的倉儲接口
?? 如果還有哪些不夠的,可以根據情況再決定增加哪些功能。創建接口不推薦直接開放給客戶端,應該在此基礎上重新為每個應用定義接口。
??
????{
????????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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FreeSql (十)更新数据
- 下一篇: Springcloud 引导上下文