我所理解的IRepository

究竟是人性的扭曲还是道德的沦丧?答案就在:

    小结:

比如Json.NET的JObject明明实现了IEnumerable<T>,具体来说是IEnumerable<KeyValuePair<string, JToken>>,按说JObject类型的对象是可以直接调用Select、Where等linq扩展方法的,但偏偏就是不行,代码如下:

    缺陷一:对于仓储接口,集合返回IEnumerable。
    如果返回的是IEnumerable,那么实际上,系统会将表中的所有数据加载到内存中,然后再进行条件过滤,排序,再分页。如果表记录稍微多一点的话,性能可想而知。此种情况下应该推荐返回IQueryable,它才是真正适合和数据库打交道的对象。在客户端应用程序没有访问实际对象值之前,比如ToList()操作,它只是一个编译过程,根据用户传入的参数构建查询计划最终生成用于查询所用的SQLScript脚本。这种方式才是真正意义上的按需所取。
    
    下面我们来定义一个新接口:    

因为JObject除了本身实现了一个IEnumerable<KeyValuePair<string, JToken>>,它实现的另一个接口JContainer也实现了一个IEnumerable<JToken>,等于JObject直接和间接实现了两个不同的IEnumerable<T>,当.Select的时候编译器不能确定调用哪个类型的Select,所以就这样了。——爆栈

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>();

- EOF -

    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);
    }

using System.Linq;
...
var jobj = new JObject();
var xxx = jobj.Select(x=>x); //报错:JObject未包含Select定义,也不存在第1个参数为JObject的Select扩展方法...
foreach(var x in jobj) { } //可以
var xxx = ((IEnumerable<KeyValuePair<string, JTokin>>)jobj).Select(x=>x); //也可以

   

    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);
    }

 缺陷二:不太实用的接口定义
    我们来看一下这个接口定义   

   如果还有哪些不够的,可以根据情况再决定增加哪些功能。创建接口不推荐直接开放给客户端,应该在此基础上重新为每个应用定义接口。   

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

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这也没也问题,而且也不推荐将仓储接口直接开放给客户端应用程序,应该在仓储接口上为每个特定的应用系统提供全新的接口,比如可以这样:    

金沙官网线上 1金沙官网线上 2View Code

    IEnumerable情况下生成的脚本:    

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

  接口实现:

本文由金沙官网线上发布于编程,转载请注明出处:我所理解的IRepository

您可能还会对下面的文章感兴趣: