Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/88.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# 如何将LINQ查询划分为小组以避免超时过期异常?_C#_Sql_Linq - Fatal编程技术网

C# 如何将LINQ查询划分为小组以避免超时过期异常?

C# 如何将LINQ查询划分为小组以避免超时过期异常?,c#,sql,linq,C#,Sql,Linq,我有如下LINQ查询 HashSet<Guid> temp1 ; // Getting this value through another method var Ids = temp1.Except((from temp2 in prodContext.Documents where temp1.Contains(temp2.id) select temp2.id)).ToList

我有如下LINQ查询

HashSet<Guid> temp1 ; // Getting this value through another method

var Ids = temp1.Except((from temp2 in prodContext.Documents 
                        where temp1.Contains(temp2.id) 
                        select temp2.id)).ToList();   
HashSet temp1;//通过其他方法获取此值
var id=temp1.Except((来自prodContext.Documents中的temp2
其中temp1.Contains(temp2.id)
选择temp2.id)).ToList();
这里,
temp1
有大约40k个值。我有时会遇到超时错误,如何使用while或任何其他循环来划分此查询,以便它不会给我超时错误。 我尝试在连接字符串和数据库上下文中设置连接超时,但没有任何效果


请给出任何建议

这是一种不寻常的操作,很可能是一种查询,可以由应用程序而不是数据库在内存中更有效地执行。与其尝试将集合中的所有id值发送到DB,让它查找具有这些id的所有项目,然后将它们全部发送回您,不如获取所有文档id并在应用程序端对其进行过滤

var documentIds = prodContext.Documents.Select(doc => doc.id);
var Ids = temp1.Except(documentIds).ToList();   
现在,根据您拥有的文档数量,即使在理论上也可能超时。如果需要,则需要对所有文档ID的获取进行分页。可以使用以下方法对任何查询进行分页,以避免一次获取整个结果集:

public static IEnumerable<IEnumerable<T>> Paginate<T>(
    this IQueryable<T> query,
    int pageSize)
{
    int page = 0;
    while (true)
    {
        var nextPage = query.Skip(page * pageSize)
            .Take(pageSize)
            .ToList();
        if (nextPage.Any())
            yield return nextPage;
        else
            yield break;
        page++;
    }
}

这里有一种结合分页和缓存的方法

这样,它一次只缓存一个页面大小,以防止内存过载和超时。我希望这能奏效

int pageSize = 1000;

HashSet<Guid> temp1;

List<Guid> idsFromTable = new List<Guid>();

var Ids = temp1.ToList();
for(int i = 0; true; i++)
{
    //Cache the table locally to prevent logic running while selecting on page size
    idsFromTable.AddRange(prodContext.Documents.Skip(pageSize * i).Take(pageSize).Select(x=> x.id));

    if(idsFromTable.Any())
    {
        //Then use the cached list instead of the datacontext
        Ids = Ids.Except(idsFromTable).ToList();
        idsFromTable.Clear(); 
    }
    else
        break;
}
int pageSize=1000;
散列集temp1;
List idsFromTable=新列表();
var id=temp1.ToList();
for(int i=0;true;i++)
{
//本地缓存表,以防止在选择页大小时逻辑运行
idsFromTable.AddRange(prodContext.Documents.Skip(pageSize*i).Take(pageSize).Select(x=>x.id));
if(idsFromTable.Any())
{
//然后使用缓存列表而不是datacontext
Ids=Ids.Except(idsFromTable.ToList();
idsFromTable.Clear();
}
其他的
打破
}

与Servy的答案类似,您可能希望尝试对查询进行分页,而不是将它们全部拉入。这项工作的效率取决于您使用的数据库,我在Informix上确实从中获得了一些好处。在这种情况下,逻辑如下所示

HashSet<Guid> ids... //Got from another method
List<Guid> validIds = new List<Guid>();

const Int32 BUFFERSIZE = 1000;
var validationBuffer = new List<Guid>(BUFFERSIZE);

foreach(var g in ids)
{
    validationBuffer.Add(g)
    if(validationBuffer.Count == BUFFERSIZE)
    {
         validIds.AddRange(
             prodContext.Documents
                 .Select(t => t.id)
                 .Where(g => validationBuffer.Contains(g)));
         validationBuffer.Clear();
    }
}

//Do last query
validIds.AddRange(
    prodContext.Documents
        .Select(t => t.id)
        .Where(g => validationBuffer.Contains(g)));

var missingIds = ids.Except(validIds);
哈希集ID//从另一种方法得到的
List validIds=新列表();
const Int32 BUFFERSIZE=1000;
var validationBuffer=新列表(BUFFERSIZE);
foreach(id中的变量g)
{
validationBuffer.Add(g)
if(validationBuffer.Count==BUFFERSIZE)
{
瓦利迪兹·阿德兰奇(
B.背景文件
.选择(t=>t.id)
其中(g=>validationBuffer.Contains(g));
validationBuffer.Clear();
}
}
//做最后一个查询
瓦利迪兹·阿德兰奇(
B.背景文件
.选择(t=>t.id)
其中(g=>validationBuffer.Contains(g));
var missingIds=id.Except(validis);

@Christos感谢您的快速回复。我试过了,但它给了我同样的错误。“超时已过期。操作完成前超时时间已过,或者服务器没有响应。”@Christos:无法在您的答案下添加注释,因此在此回复,谢谢您的回复。我正在考虑另一种方法。1)如果要从数据库中提取所有数据,至少在具体化查询之前选择ID,则不需要其他列。2) 如果要花时间从数据库中获取所有ID,则无需使用
where
;它的唯一目的是避免获取它们并将它们带入内存。在
中包含除第一个集合中不存在的
之外的项目将不会起任何作用,无需花费时间首先主动删除它们。3) 如果提取表中的所有项通常都会超时,那么您仍然可以分页。我改进了linq查询,但是,如果从一开始就缓存列表,而不是在linq查询中动态加载数据,则可能会提高性能。@Taugenichts:我试过并获取了引发了“System.OutOfMemoryException”类型的异常。“错误。。无论如何,谢谢你的建议,很不幸,你没有多余的记忆。希望下面的答案能够更好地使用分页,因为它不会同时被缓存。如果您仍然没有解决方案,请告诉我。否则请尝试此方法。我想这就行了。也谢谢你的分页想法,谢谢。我将尝试此方法页面在哪里递增?这不会只返回元素的第一个“页面大小”吗?OP有很多文档。查询该表N次,其中N是您拥有的组数,这将是非常昂贵的,特别是考虑到您对所有这些项执行的实际操作不是特别有效的操作。每个单独的查询都可能很有可能超时,如果没有超时,整个操作几乎肯定要花费比需要的时间多得多的时间。@Servy我处理类似问题的经验是,它可能是相反的,主要问题是两个解决方案都是次优的,人们必须在典型的id集上尝试这两种方法,并选择哪一种更快/更省时out@Servy还考虑给定大小n的分页,或者用简单的查询(文档计数)/N查询来命中数据库,或者用更复杂的查询(ID计数)/N来命中数据库,所以从本质上讲,这是一个文档填充、网络速度、查询速度、本地id填充和分页大小之间的优化问题
HashSet<Guid> ids... //Got from another method
List<Guid> validIds = new List<Guid>();

const Int32 BUFFERSIZE = 1000;
var validationBuffer = new List<Guid>(BUFFERSIZE);

foreach(var g in ids)
{
    validationBuffer.Add(g)
    if(validationBuffer.Count == BUFFERSIZE)
    {
         validIds.AddRange(
             prodContext.Documents
                 .Select(t => t.id)
                 .Where(g => validationBuffer.Contains(g)));
         validationBuffer.Clear();
    }
}

//Do last query
validIds.AddRange(
    prodContext.Documents
        .Select(t => t.id)
        .Where(g => validationBuffer.Contains(g)));

var missingIds = ids.Except(validIds);