您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 1浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

使用实体框架或C#中的任何IEnumerable列出批处理/分页

寒冰屋 发布时间:2019-05-23 13:18:41 ,浏览量:1

目录

背景

IEnumerable批量/分页帮助程序类

批量详细模型

实用程序/帮助程序类

使用List

使用实体框架

SQL Server的Db连接字符串设置

IQueryable,IDbSet

SQL或DbRawSqlQuery

  • ListBatchAndPage_vs2017.zip - 12 KB
背景

上周,我使用Entity Framework处理了大型数据对象列表。由于数据量很大,我不得不将它们分成多个小批量,并根据需要处理每个项。今天我将共享一个实用程序/帮助程序类来有效地批量/页面化源IEnumerable对象。

IEnumerable批量/分页帮助程序类 批量详细模型

该模型将提供所有必要的批处理/分页详细信息。即我们可以使用此模型将分页数据绑定到前端。

public class BatchListDetail
{
    public int PageNo { get; set; }
    public int PageSize { get; set; }
    public int TotalItem { get; set; }

    public int TotalPage
    {
        get
        {
            var value = PageSize > 0 
                        ? (int)Math.Ceiling(TotalItem / (double)PageSize)
                        : 0;
            return value;
        }
    }
    public bool HasPreviousPage
    {
        get
        {
            var value = PageNo > 1;
            return value;
        }
    }
    public bool HasNextPage
    {
        get
        {
            var value = PageNo < TotalPage;
            return value;
        }
    }
}
实用程序/帮助程序类

在这个帮助类中,我们将获得三种不同的扩展方法

  1. 获取给定页码的分页/批量数据。
  2. 从给定的页码开始,获取多页面列表中的所有数据。
  3. 获得top(SQL top)数据。请在我们要处理的大型列表中的每个项的场景中使用此项,并且在处理之后,该项将不再可用于下一批次查询。
using System; 
using System.Collections.Generic; 
using System.Linq;

public static class EnumerableHelper
{
    /// 
    /// Total list detail with current page data
    /// 
    public static List Batch(this IEnumerable source, int pageNo, int pageSize, out BatchListDetail details) where T : class
    {
        List list = new List();
        details = new BatchListDetail();

        if (pageNo < 1)
        {
            throw new ArgumentOutOfRangeException("pageNo minimum value should be 1.");
        }
        if (pageSize < 1)
        {
            throw new ArgumentOutOfRangeException("pageSize pageSize value should be 1.");
        }
        int totalItem = source == null ? 0 : source.Count();
        if (totalItem == 0)
        {
            return list;
        }

        /*batch list details*/
        details.PageNo = pageNo;
        details.PageSize = pageSize;
        details.TotalItem = totalItem;

        /*resut*/
        list = pageNo == 1
            ? source.Take(pageSize).ToList()
            : source.Skip((pageNo - 1) * pageSize).Take(pageSize).ToList();
        return list;
    }

    /// 
    /// Total list to multiple split list
    /// 
    public static IEnumerable Batchs(this IEnumerable source, int startingFromPage, int size) where T : class
    {
        BatchListDetail details;
        do
        {
            yield return source.Batch(startingFromPage, size, out details);
            ++startingFromPage;
        }
        while (details.HasNextPage);
    }

    /// 
    /// Use in a scenario when we are going to process each item of a large list, batch wise.
    /// Need to process the item in a way so that, after processing this will not be available on next batch query anymore.
    /// 
    public static bool Batch(this IEnumerable source, int size, out List result) where T : class
    {
        result = source.Take(size).ToList();
        return result.Any();
    }
}
使用List

这里我们用List / IList对象测试帮助程序类

/*list*/
List sourceList = Data.Peoples(TotalItem);
/*queryable*/
//IQueryable sourceList = Data.Peoples(TotalItem).AsQueryable();

/*page wise data*/
BatchListDetail details;
List batch = sourceList.Batch(1, 3, out details).ToList();

/*full list to multiple paged list*/
List batchs = sourceList.Batchs(1, 3).ToList();

/*get batch data, process and do same until all processed*/
var query = sourceList.Where(x => !x.IsActive);
List resultList;
while (query.Batch(3, out resultList))
{
    foreach (var item in resultList)
    {
        item.IsActive = true;
    }
}
使用实体框架 SQL Server的Db连接字符串设置
  1. 在app.config文件中更改连接字符串
  2. 在包管理器控制台中键入Update-Database

    
    
    

现在我们很好地连接到我们的本地SQL Server。让我们在我们的数据库中填充一些样本数据用于测试目的

Db db = new Db();
db.People.RemoveRange(db.People);               /*remove old data*/
db.SaveChanges();
db.People.AddRange(Data.Peoples(TotalItem));    /*add new data*/
db.SaveChanges();
IQueryable,IDbSet

这里我们使用Entity Framework 和IQueryable,IDbSet 对象测试实用程序类。

/*table*/
BatchListDetail details;
/*page wise data*/
List batch = db.People.Batch(1, 3, out details).ToList();
/*full list to multiple paged list*/
List batchs = db.People.Batchs(1, 3).ToList();
/*get batch data, process and do same until all processed*/
var query = db.People.Where(x => !x.IsActive);
List resultList;
while (query.Batch(3, out resultList))
{
    foreach (var item in resultList)
    {
        item.IsActive = true;
    }
    db.SaveChanges();                   /*save to db*/
}

/*all data*/
List list = db.People.ToList();
SQL或DbRawSqlQuery

现在让我们用DbRawSqlQuery(SQL查询结果对象)  尝试测试帮助程序类

/*sql query to model*/
BatchListDetail modelDetails;
/*page wise data*/
List modelBatch = db.Peoples().Batch(1, 3, out modelDetails).ToList();
/*full list to multiple paged list*/
List modelBatchs = db.Peoples().Batchs(1, 3).ToList();
/*get batch data, process and do same until all processed*/
var modeQuery = db.Peoples().Where(x => x.IsActive);
List modelResultList;
while (modeQuery.Batch(3, out modelResultList))
{
    foreach (var item in modelResultList)
    {
        People people = db.People.Find(item.Id);
        people.IsActive = false;
    }
    db.SaveChanges();                   /*save to db*/
}

/*all data*/
List modelList = db.Peoples().ToList();

说明

  •  在处理大型数据集时,yield return是您最好的朋友
  • 其他可用的配料解决方案
    • https://github.com/troygoode/PagedList
    • https://github.com/morelinq/MoreLINQ
    • https://stackoverflow.com/a/34665432/2948523

 

原文地址:https://www.codeproject.com/Tips/4114424/List-Batching-Paging-With-Entity-Framework-or-Any

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.1275s