【问题标题】:Type Inference failed in a call to 'join' on nullable and non-nullable int类型推断在可空和不可空 int 上调用“加入”失败
【发布时间】:2018-06-28 17:46:56
【问题描述】:

在我的 Linq 中,我正在尝试对可空字段进行内部连接。 Employee 和 Department 有关系,Department 可能有一个 EmployeeID 或者可能有一个 null。那么,如果我只想要满足内部联接的记录(null EmployeeIDs 没有结果),我的联接将是什么:

var result = from emp in employees
             join dept in departments
             on new { Source = emp.EmployeeID }
             equals new { Source = dept.EmployeeID };

我遇到了一个异常:

join 子句中的一个表达式的类型不正确。 类型推断在调用“加入”时失败。

谢谢

【问题讨论】:

    标签: c# linq entity-framework nullable non-nullable


    【解决方案1】:

    比较 Int?和 Int,将 .Value 附加到可为空的属性:

    var result = from emp in employees
                 join dept in departments
                 on new { Source = emp.EmployeeID }
                 equals new { Source = dept.EmployeeID.Value };
    

    【讨论】:

    • 重要的是要注意,您必须命名添加“.Value”的那个,因为自动名称将是“Value”而不是“EmployeeID”。您可以(但不需要)为没有“.Value”的名称添加名称。所以对于这个例子,on new{emp.EmployeeID} equals new {EmployeeID = dept.EmployeeID.Value} 可以正常工作
    【解决方案2】:

    如果你反转你的加入并在里面放一点where呢?

    var result = from department in departments
                 where department.EmployeeID != null
                 join employee in employees
                 on department.EmployeeID.Value equals employee.EmployeeID
                 select new { employee, department };
    

    【讨论】:

    • 它怎么可能工作,仍然 emp.EmployeeID 是一个不可为空的字段,而 dept.EmployeeID 是一个可空的字段,我什至检查了你的代码,但没有运气,仍然是同样的错误。我们不能将可为空的 int 连接到 int
    • @asbjornu:您需要将 dept.EmployeeID 更改为 dept.EmployeeID.Value
    • @MSingh:那么您的代码与ideone.com/4F8X2 的代码不同吗?我想应该是,因为您仍然遇到错误。
    • 从你给出的链接来看,我太不知所措了,我无话可说谢谢你,你简直太棒了,这段代码和写的有区别在那个链接中,无论如何非常感谢
    • 这只是一个提示:为什么你使用“on new”和“equals new”,对于单个比较器,你不需要使用语句“new”,只使用“on”和“等于”,on department.EmployeeID.Value equals employee.EmployeeID
    【解决方案3】:

    https://social.msdn.microsoft.com/Forums/en-US/bf98ec7a-cb80-4901-8eb2-3aa6636a4fde/linq-join-error-the-type-of-one-of-the-expressions-in-the-join-clause-is-incorrect-type-inference?forum=linqprojectgeneral的另一个链接中找到有用的答案

    要连接多值键,您需要在 'equals' 的两侧构造一个相同类型的匿名类型。匿名类型初始值设定项表达式从您提供的表达式中推断成员的类型和名称。在您的情况下,成员的名称不同,因此类型最终不同,因此 C# 无法确定两者之间的共同类型。

    在新的 { VC.Make, VC.Model } 上等于新的 { MD.MakeID, MD.RefNum }

    应该是

    新的 { VC.Make, CV.Model } 等于新的 { Make = MD.MakeID, Model = MD.RefNum }

    在初始化程序中使用 name = value 语法,您可以指定编译器在创建类型时使用的名称。如果所有成员类型和名称都相同,则匿名类型是相同的类型。

    【讨论】:

    • 当“仅重新排序查询”会稀释理解并需要更多工作时,这一点尤其重要。如果您在 where 子句中检查 null,您可以只使用 .Value 作为可空列,然后您必须像这里所说的那样专门命名对象属性!
    【解决方案4】:

    检查emp.EmployeeIDdept.EmployeeID 上的类型。如果他们不同,您可能会错过演员表。

    类似:

    on new { Source = emp.EmployeeID }
    equals new { Source = **(int)**dept.EmployeeID };
    

    看起来emp.EmployeeID 属于int 类型,而dept.EmployeeID 属于nullable<int> 类型。

    【讨论】:

      【解决方案5】:

      我遇到了同样的问题,我的 charge_codes.CompanyId 可以为空,但我的 order_items.CompanyId 不能为空。

      所以我必须将我的收费代码变成他们自己的异常类型,并使其不能为空。

      var chargeCodes = from s in db.Charge_Codes
      where s.CompanyID != null
      select new { CompanyID = (int)s.CompanyID, 
                   Charge_CodeID = s.Charge_CodeID, 
                   Revenue_Code_Id = (int)s.Revenue_CodeID, };
      
      
      
      //now my chargeCodes contains an anonymous with a non nullable CompanyID and 
      //a non nullable Revenue_CodeID 
      
      //use chargeCodes here
      var query = from oi in db.Order_Items
      join cc in chargeCodes on 
      new {oi.CompanyID, oi.Charge_CodeID} equals new {cc.CompanyID, cc.Charge_CodeID}
      

      【讨论】:

      • 谢谢!我有一个类似的问题,其中 id 字段是一个表中的 varchar 和另一个表中的数字。转换为异常类型修复了它。
      【解决方案6】:

      在我的场景中,我在使用多列的连接时遇到了这个错误。属性名称不同,其中一个也可以为空。我所做的只是为这些属性创建一个名称并在可为空的值上添加“.Value”,以便 LINQ 连接可以正确关联这些属性。

      var query = from y in Context.Table1
              join y in Context.Table2 on new { Field1 = x.Field1.Value, Field2 = x.Field2 }
              equals new { Field1 = y.Field1DiffName, Field2 = y.Field2 }
      

      希望对遇到此问题的人有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-01
        • 2021-02-17
        • 1970-01-01
        • 1970-01-01
        • 2016-04-24
        • 1970-01-01
        相关资源
        最近更新 更多