连接子句中的一个表达式的类型不正确。调用 '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

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

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

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

所以我试图在 On 子句中用 Multiple Conditions 编写 LINQ Join。我已经编写它们以确保对象的属性具有相同的类型和名称。尽管如此,我还是收到了臭名昭著的误导性错误 - 连接子句中的一个表达式的类型不正确。调用 '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
                        };

CompanyIDWorkOrders 上下文中的 RepairLocation 都是 int 类型?因此,我输入了关系 table 并为每个 属性 只是为了确定。

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

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

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 { 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 表达式的第一个字段与第二个表达式中的相同字段进行比较,并将第一个匿名 link 表达式的第二个字段与第二个匿名 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
                      };

经过大量尝试和搜索,我找到了解决方案。感谢@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 子句 上加入具有多个条件的 tables 时:-

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