join 子句中的表达式之一的类型不正确。对“加入”的调用中的类型推断失败。-具有多个条件的 Linq JOIN

Posted

技术标签:

【中文标题】join 子句中的表达式之一的类型不正确。对“加入”的调用中的类型推断失败。-具有多个条件的 Linq JOIN【英文标题】:The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'Join'.- Linq JOIN with multiple condition 【发布时间】:2021-09-19 02:41:26 【问题描述】:

这可能会因为可能的重复而关闭:The type of one of the expressions in the join clause is incorrect in Entity Framework 但如果不阅读整个问题,我会要求不要关闭它。

虽然它似乎是重复的question,但如果可能,我会请求阅读并提供帮助。我已经看到了我链接的同一个问题的解决方案,它描述了属性类型和名称必须匹配。我仔细阅读了那里的解决方案,并确保我的每一个都遵循。

但是,我在代码中找不到任何属性类型和名称不匹配错误。所以我猜我还缺少其他东西。因此寻求帮助创建一个单独的问题。

所以我试图在On 子句中写LINQ JoinMultiple Conditions。我已经编写了它们以确保对象的属性具有相同的类型和名称。尽管如此,我还是遇到了臭名昭著的误导性错误 - join 子句中的表达式之一不正确。调用“加入”时类型推断失败

以下是我的代码:

              results = from i in context.Invoices.AsNoTracking()
                        join iwr in context.InvoiceWorkOrderRelations on i.ID equals iwr.InvoiceId
                        join w in context.WorkOrders on iwr.WorkOrderId equals w.ID
                        join scr in context.StationCompanyRelations 
                            on new  Company = w.CompanyID ?? -1, Station = w.RepairLocation ?? -1  equals new  Comapny = (int)?scr.CompanyID, Station= (int)?scr.StationID 
    
                        where i.IsDeleted == false
                    && (companyID == Company.SYSTEMCOMPANYID || i.CompanyId == companyID)
                        orderby i.ID descending
                        select new DTO.InvoiceQuickView
                        
                            ID = i.ID,
                            ....
                            ShopCode = scr.ShopCode
                        ;

CompanyID 和来自WorkOrders 上下文的RepairLocation 都是 int? 类型,因此,我键入转换关系表并为每个属性提供字符串名称以确保。

为了处理空值,我添加了w.CompanyID ?? -1。无论是否进行此 null 检查,错误仍然存​​在。

【问题讨论】:

【参考方案1】:

不能在linq 表达式中使用转换或直接转换函数,它必须是anonymous

join两个表有两个参数,两个字段必须在你的代码下面有相同的类型I:

 results = from i in context.Invoices.AsNoTracking()
                      join iwr in context.InvoiceWorkOrderRelations on i.ID equals iwr.InvoiceId
                      join w in context.WorkOrders on iwr.WorkOrderId equals w.ID
                      join scr in context.StationCompanyRelations
                          on new  w.CompanyID, w.RepairLocation  equals new  scr.CompanyID, scr.StationID 

                      where i.IsDeleted == false
                  && (companyID == Company.SYSTEMCOMPANYID || i.CompanyId == companyID)
                      orderby i.ID descending
                      select new DTO.InvoiceQuickView
                      
                          ID = i.ID,
                          ....ShopCode = scr.ShopCode
                      ;

行内代码

join scr in context.StationCompanyRelations
                          on new  w.CompanyID, w.RepairLocation  equals new  scr.CompanyID, scr.StationID 

编译器自动将第一个匿名 linq 表达式的第一个字段与第二个表达式中的相同字段进行比较,并将第一个匿名链接表达式的第二个字段与第二个匿名 linq 表达式的第二个字段进行比较。

如果您希望值为空时匹配,请使用DefaultIfEmpty。 下面的代码展示了如何做到这一点。

 results = from i in context.Invoices.AsNoTracking()
                      join iwr in context.InvoiceWorkOrderRelations on i.ID equals iwr.InvoiceId
                      join w in context.WorkOrders on iwr.WorkOrderId equals w.ID
                      join scr in context.StationCompanyRelations
                          on new  w.CompanyID, w.RepairLocation  equals new  scr.CompanyID, scr.StationID 
                          into lj
                      where i.IsDeleted == false
                  && (companyID == Company.SYSTEMCOMPANYID || i.CompanyId == companyID)
                      orderby i.ID descending
                     from x in lj.DefaultIfEmpty()
                      select new DTO.InvoiceQuickView
                      
                          ID = i.ID,
                          ....ShopCode = scr.ShopCode
                      ;

【讨论】:

那么,您是在建议我不能加入在一个表中可为空且在另一表中不为空的属性? 您给出的解决方案是我的第一次尝试。我在尝试你的方法时遇到了这个错误。在那之后,我搜索了一下,似乎人们是通过类型转换来完成的。请看这条评论***.com/a/19184145/3939811 我之前看过并测试过,但是编译器给出了错误。我编辑了答案。您可以将 DefaultIfEmpty() 用于空值。 在我的情况下,编译器仍然使用 DefaultEmpty() 抛出错误 问题中描述了同一个。【参考方案2】:

经过大量尝试和搜索,我找到了解决方案。感谢@Meysam Asadi,他提出了关于在 linq 中对匿名类型进行类型转换的观点,但是要添加到该语句中,类型名称也必须匹配。我发现他的解决方案的问题是两个对象的第二个属性(RepairLocation 和 StationID)不一样,这就是编译器仍然抛出相同错误的原因。

我不知道为什么其他解决方案都在建议进行类型转换。在我的情况下,主要是导致此错误的类型转换。

                    join w in context.WorkOrders on iwr.WorkOrderId equals w.ID
                    join scr in context.StationCompanyRelations on 
                       new  Company = w.CompanyID ?? -1, Station = w.RepairLocation ?? -1  equals 
                       new  Comapny = scr.CompanyID, Station= scr.StationID 

所以,在编写 linq 以在 ON 子句上连接具有多个条件的表时:-

必须匹配属性名称,并且如果一个表中的一个属性是nullable 而另一个是not null,则您必须处理可空值。

【讨论】:

所以答案实际上只是您所说的问题的答案不是重复的。 解决方案建议进行类型转换,这就是我弄错的地方。在我的情况下,类型转换(int)?抛出错误。 如果它违反了社区标准,我准备删除或关闭它。我需要帮助,而现有的解决方案似乎无法解决我的问题。并感谢@Meysam Asadi,他写了一个答案,让我明白了问题所在。无论如何感谢您的反馈。

以上是关于join 子句中的表达式之一的类型不正确。对“加入”的调用中的类型推断失败。-具有多个条件的 Linq JOIN的主要内容,如果未能解决你的问题,请参考以下文章

JOIN 子句中的 MySQL 逻辑评估是不是延迟/短路?

C#图解教程 第十九章 LINQ

通过 Excel VBA 进行 SQL 查询的复杂 JOIN 子句中的语法错误

在 JOIN 的 ON 子句中使用别名

大数据ClickHouse进阶:ClickHouse的Array Join子句

不支持 Left Join On And 子句