【问题标题】:Select records that does not exist in another table in Entity Framework选择实体框架中另一个表中不存在的记录
【发布时间】:2014-02-13 22:25:12
【问题描述】:

我有两个表 - “客户”表和“黑名单”客户表。当我将客户列入黑名单时,我将 customerid 作为外键放入黑名单表。

我想要的是获取不在黑名单表中的 CusId 和 Name。

如何编写这个实体框架 C#?

Customer
---------
(CusId,Name,Telephone,Email)

Blacklist
---------
(CusId)

【问题讨论】:

  • 我是 EF 新手,我已经尝试过各种方法。他们都没有工作。所以请帮我解决这个问题。

标签: c# entity-framework


【解决方案1】:

你想要的是如下内容:

db.Customers
    .Where(c => !db.Blacklists
        .Select(b => b.CusId)
        .Contains(c.CusId)
    );

EF 很乐意将其转换为运行良好的子查询。

此模式适用于静态列表(创建IN(a, b, c) 表达式)以及其他表。您可以使用它来检查是否在列表中。

如果你想测试它并查看它生成的 SQL,我强烈推荐 LINQPad(它是免费的)。这就是我一直用来在 LINQ 中测试小想法的方法。

【讨论】:

  • 您能否提供上述声明的“详细”版本(如下面的 Tim 提供的答案)?那真的很有帮助。或者,如果您知道一个可以从一个转换到另一个的地方会更好:)
  • 如何添加另一个 Where 子句?例如 Where Customer.Email =='a@a.com' ??
  • 非常慢:如果 Blacklists 表有 100 万条记录,它将无法工作,因为它总是会给出超时错误
  • 短版:db.Customers.Where(c=>!db.Blacklists.Any(b=>b.CusId==c.CusId))。但是,Entity Framework 会生成相同的 SQL 表达式。
【解决方案2】:

这样的事情怎么样:

var subselect = (from b in BlackList select b.CusId).ToList();

var result = from c in Customer where !subselect.Contains(c.CusId) select c;

【讨论】:

  • 你有什么理由愿意以这种方式而不是蒂莫西分享的方式做事?
  • @PeterMajeed 好吧,我不确定,但 Tim 只获取一次 BlackList。 Timothys BlackList 包含在 Where 中(但可能是 EF 对其进行了优化,因此它也只获取一次)
  • 我做的快速检查表明,对于我的代码,BlackList 表是作为WHERE NOT EXISTS (SELECT NULL AS [Empty] FROM [Blacklist] ... 添加的,因此它甚至不会检索它,SQL 完成了所有工作并且它得到了很好的优化。
  • 对不起,伙计们。我只是将上述内容作为我以前使用过的东西提供。当我发布我的答案时,我还没有看到任何其他答案。
  • @TimRolen 各位好伙伴,有时您的解决方案很方便,而且绝对有效。很高兴知道 EF 会将其转换为 WHERE CusId NOT IN (1, 2, 3, 4) 类型的语句。对于短列表或有额外逻辑来过滤最佳解决方案的列表,我自己也经常使用它。
【解决方案3】:

Any() 是最好的表现:

db.Customers.Where(c => !db.Blacklists.Any(b => b.CusId == c.Id));

如果您还需要黑名单的 ,请使用 join 条件:b.CusId == c.Id

【讨论】:

    【解决方案4】:

    如果在表 BlackList 中你有一个 Customer 列表你可以执行类似的操作

     IEnumerable<Customer> model = (from c in db.Customer
                                    from b in c.BlackList.DefaultIfEmpty()
                                     where b.CusID== null
                                      select new Customer
                                       {
                                            CusId= c.OrderID
                                        }).ToList();
    

    【讨论】:

      【解决方案5】:

      我使用的这个查询,效果很好:

      var query = _context.Customer.Where(x => x.Id == id && !x.BlackList.Any(z => x.Id == x.CustId)).ToList();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-19
        • 1970-01-01
        • 2015-08-27
        • 1970-01-01
        • 1970-01-01
        • 2016-06-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多