【问题标题】:LINQ Contains() alternatives [duplicate]LINQ Contains() 替代方案 [重复]
【发布时间】:2020-04-08 04:00:15
【问题描述】:

我有一个int 列表,我需要从我的查询中选择所有记录,其中 id 包含在第二个列表中,如下所示:

     //my list of ids
    var ids=[myquery].select(x=> x.id)

    query = query.Where(x => ids.Contains(x.Id));

现在 LINQ 会将上述内容转换为:

SELECT *
FROM [MyTable] 
WHERE ([x].[id] IN (108,687, 689, 691, 694, 705, 703,.....)

现在 ids 列表会增长很多,我想这会破坏性能。

考虑到ids 列表将包含超过 200K 项,有什么更好的解决方案?

【问题讨论】:

  • 或许您应该使用导航属性,但这取决于 [myquery]query 是什么。
  • 您需要以某种方式发送这 200K 项。 Linq 转换为这样的 IN (...) 很好。我也有同样的需求,只是我的 ID 列表可以作为逗号分隔列表(字符串)使用,但略有不同。我最终创建了一个 CLR 函数(MS SQL Server)。

标签: c# .net entity-framework linq


【解决方案1】:

这取决于您的模型,但您可能应该使用导航属性。

鉴于您目前有这样的事情:

var ids =
   context
   .Entity1
   .Where(x => x.Property == value)
   .Select(x => x.ID)
   .ToHashSet();

var items =
   context
   .Entity2
   .Where(x => ids.Contains(x.ID))
   .ToList();

改为这样写:

var items =
   context
   .Entity2
   .Where(x => x.Entity1.Property == value)
   .ToList();

您可能需要先将此类关联添加到您的模型中。

【讨论】:

    【解决方案2】:

    我建议创建一个存储过程:

    • C# 和数据库之间没有不必要的调用(例如,您正在收集这些 200K ids
    • C# 中的代码更少。所以你的代码会更干净更清晰
    • 性能更好,因为有时 EF 会生成低效的 SQL 代码

    所以calling stored procedure 看起来像这样:

    var user = "johndoe";
    
    var blogs = context.Blogs
        .FromSqlRaw("EXECUTE dbo.GetMostPopularBlogsForUser {0}", user)
        .ToList();
    

    如果项目少于200K,则尝试使用NOT IN 运算符:

    query = query.Where(x => !ids.Contains(x.Id));
    

    SQL:

    SELECT *
    FROM [MyTable] 
    WHERE ([x].[id] NOT IN (108,687, 689, 691, 694, 705, 703,.....)
    

    【讨论】:

      猜你喜欢
      • 2014-02-15
      • 1970-01-01
      • 1970-01-01
      • 2020-09-20
      • 2018-11-14
      • 1970-01-01
      • 1970-01-01
      • 2020-01-09
      • 2010-12-24
      相关资源
      最近更新 更多