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

目录

背景

IEnumerable批量/分页帮助程序类

批量详细模型

实用程序/帮助程序类

使用List

使用实体框架

SQL Server的Db连接字符串设置

IQueryable,IDbSet

SQL或DbRawSqlQuery


背景

上周,我使用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. 获得topSQL top)数据。请在我们要处理的大型列表中的每个项的场景中使用此项,并且在处理之后,该项将不再可用于下一批次查询。
using System; 
using System.Collections.Generic; 
using System.Linq;

public static class EnumerableHelper
{
    /// <summary>
    /// Total list detail with current page data
    /// </summary>
    public static List<T> Batch<T>(this IEnumerable<T> source, int pageNo, int pageSize, out BatchListDetail details) where T : class
    {
        List<T> list = new List<T>();
        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;
    }

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

    /// <summary>
    /// 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.
    /// </summary>
    public static bool Batch<T>(this IEnumerable<T> source, int size, out List<T> result) where T : class
    {
        result = source.Take(size).ToList();
        return result.Any();
    }
}

使用List

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

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

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

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

/*get batch data, process and do same until all processed*/
var query = sourceList.Where(x => !x.IsActive);
List<People> resultList;
while (query.Batch(3, out resultList))
{
    foreach (var item in resultList)
    {
        item.IsActive = true;
    }
}

使用实体框架

SQL ServerDb连接字符串设置

  1. app.config文件中更改连接字符串
  2. 在包管理器控制台中键入Update-Database
<connectionStrings>
    <!--For local development-->
    <!--<add name="DbPms" connectionString="Data Source=(local);Initial Catalog=PMS;Integrated Security=True" providerName="System.Data.SqlClient" />-->
    <add name="DbPms" connectionString="Data Source=DESKTOP-GSTET0K\MSSQLSERVER2014;Initial Catalog=PMS;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>

现在我们很好地连接到我们的本地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();

IQueryableIDbSet

这里我们使用Entity Framework IQueryableIDbSet 对象测试实用程序类。

/*table*/
BatchListDetail details;
/*page wise data*/
List<People> batch = db.People.Batch(1, 3, out details).ToList();
/*full list to multiple paged list*/
List<List<People>> 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<People> resultList;
while (query.Batch(3, out resultList))
{
    foreach (var item in resultList)
    {
        item.IsActive = true;
    }
    db.SaveChanges();                   /*save to db*/
}

/*all data*/
List<People> list = db.People.ToList();

SQLDbRawSqlQuery

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

/*sql query to model*/
BatchListDetail modelDetails;
/*page wise data*/
List<PeopleModel> modelBatch = db.Peoples().Batch(1, 3, out modelDetails).ToList();
/*full list to multiple paged list*/
List<List<PeopleModel>> 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<PeopleModel> 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<PeopleModel> modelList = db.Peoples().ToList();

说明

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值