繁体   English   中英

LINQ2SQL select 行基于大 where

[英]LINQ2SQL select rows based on large where

我正在使用 LINQ2SQL 在 SQL(精简版)数据库中搜索一堆 int32。

我的主要问题是我有一个很大的 int32 列表(数千个),我想要 DB 中的所有记录,其中 DB 中的 id 字段与我的任何 int32 匹配。 目前我一次选择一行,有效地搜索索引数千次。

我该如何优化呢? 临时表?

听起来您可以使用 Contains 查询:

int[] intArray = ...;
var matches = from item in context.SomeTable 
              where intArray.Contains(item.id) 
              select item;

要搜索数千个值,您的选择是:

  • 将 XML 块发送到存储过程(复杂,但可行)
  • 创建一个临时表,批量上传数据,然后加入它(可能导致并发问题)
  • 执行多个查询(即将您的一组 ID 分成一千个左右的块并使用 BrokenGlass 的解决方案)

我不确定您可以使用 Compact Edition 做什么。

将您的整数插入 SQL 表中,然后执行以下操作:

var items = from row in table
            join intRow in intTable on row.TheIntColumn equals intRow.IntColumn
            select row;

编辑 1 和 2:更改了答案,因此他加入了 2 个表,没有 collections。

我的偏好是为搜索编写一个存储过程。 如果您在要搜索的字段上有一个索引,那么当要处理的行数增加时,这将使您的生活变得更加轻松。

您将遇到的复杂性是编写可以从输入参数执行 IN 子句的 select 语句。 您需要有一个表值 function 将字符串(Id 的)转换为列并在 IN 子句中使用该列。 喜欢:

Select *
From SomeTable So
Where So.ID In (Select Column1 From dbo.StringToTable(InputIds))

在厌倦了编写手动批处理代码之后,我想出了这个 linq 解决方案。 它并不完美(即批次并不完全完美),但它解决了问题。 当您不允许编写存储过程或 sql 函数时非常有用。 适用于几乎所有 linq 表达式。

享受:

    public static IQueryable<TResultElement> RunQueryWithBatching<TBatchElement, TResultElement>(this IList<TBatchElement> listToBatch, int batchSize, Func<List<TBatchElement>, IQueryable<TResultElement>> initialQuery)
    {
        return RunQueryWithBatching(listToBatch, initialQuery, batchSize);
    }

    public static IQueryable<TResultElement> RunQueryWithBatching<TBatchElement, TResultElement>(this IList<TBatchElement> listToBatch, Func<List<TBatchElement>, IQueryable<TResultElement>> initialQuery)
    {
        return RunQueryWithBatching(listToBatch, initialQuery, 0);
    }

    public static IQueryable<TResultElement> RunQueryWithBatching<TBatchElement, TResultElement>(this IList<TBatchElement> listToBatch, Func<List<TBatchElement>, IQueryable<TResultElement>> initialQuery, int batchSize)
    {
        if (listToBatch == null)
            throw new ArgumentNullException("listToBatch");

        if (initialQuery == null)
            throw new ArgumentNullException("initialQuery");

        if (batchSize <= 0)
            batchSize = 1000;

        int batchCount = (listToBatch.Count / batchSize) + 1;

        var batchGroup = listToBatch.AsQueryable().Select((elem, index) => new { GroupKey = index % batchCount, BatchElement = elem }); // Enumerable.Range(0, listToBatch.Count).Zip(listToBatch, (first, second) => new { GroupKey = first, BatchElement = second });

        var keysBatchGroup = from obj in batchGroup
                                     group obj by obj.GroupKey into grouped
                                     select grouped;

        var groupedBatches = keysBatchGroup.Select(key => key.Select((group) => group.BatchElement));

        var map = from employeekeysBatchGroup in groupedBatches
                  let batchResult = initialQuery(employeekeysBatchGroup.ToList()).ToList() // force to memory because of stupid translation error in linq2sql
                  from br in batchResult
                  select br;

        return map;
    }

用法:

using (var context = new SourceDataContext())
{
    // some code
    var myBatchResult = intArray.RunQueryWithBatching(batch => from v1 in context.Table where batch.Contains(v1.IntProperty) select v1, 2000);
    // some other code that makes use of myBatchResult
}

然后要么使用结果,要么展开到列表,或者你需要的任何东西。 只要确保您不会丢失 DataContext 引用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM