Linq2Sql通过多个ID选择记录?

时间:2016-10-12 13:49:25

标签: c# linq-to-sql

例如,我有10000000条记录的表格,并在内存中列出 ,包含100000个ID。

如何通过这些ID选择所有记录? 显然,我可以这样做:

var ids = GetIds();
var result = from q in ctx.Records
             where ids.Contains(q.Id)
             select q;

但如果我这样做,会有两个问题:

  • 每次使用此查询时生成的SQL都会出现怪异。

  • 每行的O(N)复杂性。所以,我会在几年后收到我的结果。

我怎么能这样做?如何用linq2sql完成,或者这是不可能绕过的?

更新

  • GetIds - 此函数返回约100.000个ID。不,我不能加入它。 计算
  • 是的,我测试了它,我调试了它并且已经看到了生成的内容。它是这样的:

    SELECT * FROM Records WHERE id IN (/*one hundreds of thousand goes here O_O*/)
    

    简单数学:10.000.000 x 100.000将给出1.000.000.000.000的时间复杂度。这非常低效。

1 个答案:

答案 0 :(得分:1)

正如你所说,在内存中进行这些操作并不好。解决方案是在数据库中有另一个表,然后您的代码将是:

var ids = GetIds();
//Insert all ids into database (bulk insert)

var result = from q in ctx.Records
             join i in ctx.Ids on q.Id equals i.Id
             select q;

这样操作将在数据库中进行,您将克服in子句中项目数量的限制。

  1. id的{​​{1}}字段应该有索引(或者如果它是主键,它也已被索引)
  2. Records表的id字段也应编入索引
  3. 这种方式的联接将是Ids而不是Hash join - 相当于使用Nested Join集合作为ids而不是{{}的.Net解决方案{1}}。

    最后,要同时支持多项操作,您可以让HashSet<string>包含2列:List<string>IdsId将被提供给特定插入内容的所有OperationId,然后您的查询将如下所示:

    OperationId

    _确保Id也被编入索引 - 可以是var result = from q in ctx.Records join i in ctx.Ids on q.Id equals i.Id where i.OperationId = _the operationId given by the insert_ select q; 的相同索引,但请注意它是第一个。

    根据DBMS,您还可以将您的表格设置为OperationId - 至少对于Oracle,它会在每个连接的会话中存储数据 - 因此您可以一次插入多个会话但数据不是共享 - 因此您不需要Id