【问题标题】:DotNetCore Entity Framework | Generic PaginationDotNetCore 实体框架 |通用分页
【发布时间】:2017-08-15 11:07:45
【问题描述】:

我正在寻找一种在 Dotnet Core 1.1 中使用实体框架进行通用分页的方法。

我在 MSDN 上找到了这个指南:https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application

但这不是通用的,不允许我重用代码。

如果有人正在研究这个问题,我会使用我的答案,我认为很高兴分享。

它在模型上使用自定义属性,并返回一个分页模型。

【问题讨论】:

    标签: entity-framework api pagination .net-core


    【解决方案1】:

    编辑:

    由于 orderBy 未正确转换为 L2E,以下答案不正确。所有记录都将在内存中检索和排序,这会导致性能不佳。检查 cmets 以获取更多信息和可能的解决方案。

    原创:

    我的解决方案:

    模型.cs:

    public class User
    {
    
        // Sorting is not allowed on Id
        public string Id { get; set; }
    
        [Sortable(OrderBy = "FirstName")]
        public string FirstName { get; set; }
    
    }
    

    SortableAttribute.cs:

    public class SortableAttribute : Attribute
    {
        public string OrderBy { get; set; }
    }
    

    PaginationService.cs:

    public static class PaginationService
    {
    
        public static async Task<Pagination<T>> GetPagination<T>(IQueryable<T> query, int page, string orderBy, bool orderByDesc, int pageSize) where T : class
        {
            Pagination<T> pagination = new Pagination<T>
            {
                TotalItems = query.Count(),
                PageSize = pageSize,
                CurrentPage = page,
                OrderBy = orderBy,
                OrderByDesc = orderByDesc
            };
    
            int skip = (page - 1) * pageSize;
            var props = typeof(T).GetProperties();
            var orderByProperty = props.FirstOrDefault(n => n.GetCustomAttribute<SortableAttribute>()?.OrderBy == orderBy);
    
    
             if (orderByProperty == null)
            {
                throw new Exception($"Field: '{orderBy}' is not sortable");
            }
    
            if (orderByDesc)
            {
                pagination.Result = await query
                    .OrderByDescending(x => orderByProperty.GetValue(x))
                    .Skip(skip)
                    .Take(pageSize)
                    .ToListAsync();
    
                return pagination;
            }
            pagination.Result = await query
                .OrderBy(x => orderByProperty.GetValue(x))
                .Skip(skip)
                .Take(pageSize)
                .ToListAsync();
    
            return pagination;
        }
    }
    

    Pagination.cs(模型):

    public class Pagination<T>
    {
        public int CurrentPage { get; set; }
    
        public int PageSize { get; set; }
    
        public int TotalPages { get; set; }
    
        public int TotalItems { get; set; }
    
        public string OrderBy { get; set; }
    
        public bool OrderByDesc { get; set; }
    
        public List<T> Result { get; set; }
    }
    

    UserController.cs(控制器内部),上下文为EntityFramework上下文:

     [HttpGet]
        public async Task<IActionResult> GetUsers([FromQuery] string orderBy, [FromQuery] bool orderByDesc, [FromQuery] int page, [FromQuery] int size)
        {
            var query = _context.User.AsQueryable();
            try
            {
                var list = await PaginationService.GetPagination(query, page, orderBy, orderByDesc, size);
                return new JsonResult(list);
            }
            catch (Exception e)
            {
                return new BadRequestObjectResult(e.Message);
            }
        }
    

    我希望这对将来的人有所帮助!

    【讨论】:

    • 为什么要限制它们?那不是什么有用的东西。如果此代码在您的环境中有效,那么您的跳过和拍摄将运行内存中的整个数据集。 EF 不明白如何处理代码的反射部分。除非 .Net Core 引入了一些时髦的东西,但我对此表示怀疑。
    • @IvanStoev 我刚刚对此进行了肯定的测试,正如我们都怀疑的那样,EF Core 不会神奇地找出反射代码并对内存中的所有内容进行排序。
    • 不传入string orderBy,直接传入表达式(Expression&lt;Func&lt;T, object&gt;&gt; orderBy),然后做OrderBy(orderBy)
    • @IvanStoev 和 DavidG 谢谢你们 :) 对我帮助很大。
    猜你喜欢
    • 1970-01-01
    • 2012-04-26
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多