首页 > 解决方案 > 强制 Linq 实体使用内部连接 ​​(EF 6)

问题描述

我有这样的 Linq 语句:

IQueryable ActiveContract = (
    from c in context.Contracts
    join a in context.Abonents on c.AbonentID equals a.ID
    where a.ID != null && c.Hidden != true && c.Status == activeContractStatus)

它生成以下查询:

SELECT 
    ...Contract properties...
    FROM [dbo].[Contracts] AS [Extent1]
    WHERE ([Extent1].[AbonentID] IS NOT NULL) AND (1 <> [Extent1].[Hidden]) AND ([Extent1].[Status] = @p__linq__0)

我已经阅读了这个答案:强制 linq 执行内部连接 ,但在我的情况下Contracts.AbonentID是可以为空的,不幸的是:

  1. 中的所有其他属性Abonents都可以为空,除了ID
  2. 拥有一个Abonent除了Abonent.ID为空之外的所有属性是完全正常的(在业务逻辑中)(所以我不能在for 子句中添加任何not null检查)。whereAbonents
  3. 我只需要与 Abonents 相关的合同。
  4. 有很多情况Contracts.AbonentID会导致无处可去(没有Abonent这样的情况ID)。

有没有办法生成类似的东西:

SELECT 
    ...Contract properties...
    FROM [dbo].[Contracts] AS [Extent1]
    INNER JOIN [dbo].[Abonents] AS [Extent2] ON [Extent1].AbonentID = [Extent2].ID
    WHERE ([Extent2].[ID] IS NOT NULL) AND (1 <> [Extent1].[Hidden]) AND ([Extent1].[Status] = @p__linq__0)

强制检查 Abonents 存在?

例如,如果我需要通过合同号码查找有效合同的所有电话号码(不幸的是,不是唯一的,因为 DB 中可能有很多合同具有相同的号码,但隐藏、按状态不活动或只是孤儿(abonent缺少那个id)),我会像这样使用smth

List<long> phoneNumbers = (context.Contracts.ActiveContracts().Where(c => c.No == contractNoToFind).Phone.OrderByDescending(p => p.Date).Select(p => p.Number);

我想说明一次“ActiveContract”是什么,并在整个 DAL 中使用它。

UPD 1: 我忘了提到 LINQ 查询是 IQueryable 的一部分,所以事实上,我当时没有选择任何东西。此外,这就是为什么存储查询也不是解决方案的原因。编辑了问题。很抱歉给您带来不便。

标签: c#entity-frameworklinqentity-framework-6

解决方案


由于您使用的是内部联接,因此您不需要检查 where a.ID != null 因为 a.ID == null 的记录将被自动省略。

所以你可以做你的 where 部分


 where c.Hidden != true && c.Status == activeContractStatus

如果您仍然对 sql 不满意,只需添加此

 select c.No, a.Id).ToList().Select(i=>i.No);

我没有看到你的课程,因为你没有发布它们,但我想这也可以工作

var contNo = context.Contracts
     .Where(c=> c.AbonentId!= null &&  c.Hidden != true && c.Status == activeContractStatus)
    .Select(c=> c.No);

推荐阅读