Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过IQueryable分批枚举_C#_Entity Framework_System.reactive - Fatal编程技术网

C# 通过IQueryable分批枚举

C# 通过IQueryable分批枚举,c#,entity-framework,system.reactive,C#,Entity Framework,System.reactive,我正在使用实体框架核心创建IQueryable。 我想找到一种方法,一次只获取一个页面的结果(比如一次10个结果),然后将其公开为IEnumerable(或者类似于IObservable的东西)。我还想确保这是尽可能高效的内存,换句话说,如果页面大小是10,那么一次内存中只有10个实体。最后,我希望数据库调用是异步的,这使得这更困难 下面是一些伪代码,其中“ToPagingEnumerable”是我想从另一个库中创建或使用的方法: IQueryable<T> query = dbCo

我正在使用实体框架核心创建IQueryable。 我想找到一种方法,一次只获取一个页面的结果(比如一次10个结果),然后将其公开为IEnumerable(或者类似于IObservable的东西)。我还想确保这是尽可能高效的内存,换句话说,如果页面大小是10,那么一次内存中只有10个实体。最后,我希望数据库调用是异步的,这使得这更困难

下面是一些伪代码,其中“ToPagingEnumerable”是我想从另一个库中创建或使用的方法:

IQueryable<T> query = dbContext.SomeTable;
IEnumerable<T> results = query.ToPagingEnumerable(pageSize: 10);
ConvertAndSaveResults(results);
IQueryable query=dbContext.SomeTable;
IEnumerable results=query.topagineNumerable(页面大小:10);
ConvertAndSaveResults(结果);
这里有一个快速失败的尝试,它不会起作用,因为您不能将“yield”与“async”结合起来:

公共静态IEnumerable ToPagingEnumerable(
这是可靠的消息来源,
整数大小)
{
var-skip=0;
var cached=wait source.Take(size.ToListAsync();
while(cached.Any())
{
foreach(缓存中的var项)
{
收益回报项目;
}
skip+=cached.Count;
cached=wait source.Skip(Skip).Take(size.toListSync();
}
}
我简要地看了一下反应流(),这似乎与我想要完成的类似

我认为另一种选择是使用Rx(反应式)并创建一个可观察对象,从IQueryable中获取一页结果(比如10行),将其提供给订阅者,然后获取另一页(比如另外10行),并将其提供给订阅者


我只是对这两个库都不太了解,不知道如何使用它们来实现我的目标,或者是否有更简单或不同的方法。

您好,您可以使用此扩展方法

public static class QuerableExtensions
{
    public static IQueryable<TEntity> ToPage<TEntity>(this IQueryable<TEntity> query, PagingSettings pagingSettings) where TEntity : class
    {
        if (pagingSettings != null)
        {
            return query.Skip((pagingSettings.PageNumber - 1)*pagingSettings.PageSize).Take(pagingSettings.PageSize);
        }
        return query;
    }
    public static IQueryable<T> OrderByField<T>(this IQueryable<T> query, SortingSettings sortingSettings)
    {
        var exp = PropertyGetterExpression<T>(sortingSettings);

        var method = sortingSettings.SortOrder.Equals(SortOrder.Asc) ? "OrderBy" : "OrderByDescending";

        var types = new[] { query.ElementType, exp.Body.Type };

        var callExpression = Expression.Call(typeof(Queryable), method, types, query.Expression, exp);
        return query.Provider.CreateQuery<T>(callExpression);
    }


}
要像这样使用它,您必须在进行分页之前订购您的设备

     public async Task<SimplePagedResult<TEntityDto>> GetAllPagedAsync<TEntityDto>(PagingSettins request) where TEntityDto : class
    {
        var projectTo = Set(); // Here is DBSet<TEnitity>


        var entityDtos = projectTo.OrderByField(new SortingSettings());

        if (request.PagingSettings != null)
            entityDtos = entityDtos.ToPage(request.PagingSettings);

        var resultItems = await entityDtos.ToListAsync();

        var result = MakeSimplePagedResult(request.PagingSettings, resultItems);
        return result;
    }
公共异步任务GetAllPagedAsync(PagingSettings请求),其中tentityTo:class
{
var projectTo=Set();//这是DBSet
var entityDtos=projectTo.OrderByField(新的排序设置());
if(request.PagingSettings!=null)
entityDtos=entityDtos.ToPage(请求.分页设置);
var resultItems=await entityDtos.ToListAsync();
var result=MakeSimplePagedResult(request.PagingSettings,resultItems);
返回结果;
}
结果是什么

    public class SimplePagedResult<T>
{
    public IEnumerable<T> Results { get; set; }
    public int CurrentPage { get; set; }
    public int PageSize { get; set; }
}
公共类SimplePagedResult
{
公共IEnumerable结果{get;set;}
public int CurrentPage{get;set;}
公共int PageSize{get;set;}
}

为什么要多次运行查询

那就:

var results  = source.ToAsyncEnumerable().Buffer(10);

以下是一种不使用扩展方法成批处理
IQueryable
的方法:

var batchSize = 5000;

var myqueryable = // GetQueryable();

var count = myqueryable.Count();
var processed = 0;

while (processed < count)
{
    var take = batchSize <= count - processed ? batchSize : count - processed;

    var batchToProcess = myqueryable.Skip(processed).Take(take);

    //Do your processing, insert, what have you...

    processed += take;
}

这个答案对你有帮助吗?我希望数据库调用是异步的,但如果从一个上下文使用
IQueryable
,您将无法并行运行这些调用。
var results  = source.ToAsyncEnumerable().Buffer(10);
var batchSize = 5000;

var myqueryable = // GetQueryable();

var count = myqueryable.Count();
var processed = 0;

while (processed < count)
{
    var take = batchSize <= count - processed ? batchSize : count - processed;

    var batchToProcess = myqueryable.Skip(processed).Take(take);

    //Do your processing, insert, what have you...

    processed += take;
}
var myqueryable = // GetQueryable();

//var pageCount = (int)Math.Ceiling(myqueryable.Count() * 1D / PageSize);

int skip = PageNumber * PageSize - PageSize;

return myqueryable.Skip(skip).Take(PageSize);