在实体框架中左转空值上的联接



我需要使用实体框架在 C# 项目中执行 10 个左联接。我已经检查了至少 10 个不同的页面和堆栈溢出帖子,了解如何执行此操作。他们都没有工作。

我当前的联接如下所示:

from tbl1 in context.tblName1
join varOne in context.tblName2 on tbl1.paramOne equals varOne.paramOne into j1
from jResOne in j1.DefaultIfEmpty()

我收到错误消息:

"强制转换为值类型'System.Int32'失败,因为具体化值为 null - 结果类型的泛型参数或查询必须使用可为 null 的类型。">

我被引导相信应该通过".DefaultIfEmpty()">

如何解决此问题?

@David Browne 关于 EF 中的导航属性与联接是正确的。但这里的问题是不同的(与连接操作无关,但与处理结果无关),并且包含在异常消息中:

强制转换为值类型"System.Int32"失败,因为具体化值为null - 结果类型的泛型参数或查询必须使用可为 null 的类型

这意味着投影 (select) 试图从左侧外连接的某些右侧分配一个不可为空的类型值。在 LINQ to Objects 中,这将是一个简单的NullReferenceException。但是,LINQ to Entities 将查询转换为 SQL,数据库(尤其是 SQL)自然支持NULL值,即使对于不可为空的列也是如此。因此,EF 能够成功执行 SQL,但是当涉及到需要具体化结果(即将其放入匿名/特定类成员)时,db 查询返回null而相应的属性是不可为空的类型,EF 无法继续并引发异常,要求您通过将其转换为可为空的类型来解决它, 或将其转换为某个默认值等 - 这取决于你,EF 无法做出该决定。

假设TableBint Property,并且您有一个这样的查询:

var query = from a in db.TableA
from b in db.TableB.Where(b => b.Key == a.Key).DefaultIfEmpty()
select new { Property = b.Property };

结果Property的 C# 隐含类型是int,因此当查询结果包含与a不匹配的b时,您将获得上述异常(从 C# 的角度来看,bnull,但从 SQL 方面b.Property将是NULL)。

为了解决它,您可以将其提升为可为空的类型:

Property = (int?)b.Property

或某个默认值

Property =  b != null ? b.Property : 0

根据您的需求。并且对任何不可为空的值类型(如intdecimalDateTime等)执行类似的操作(string是一个引用类型,所以它没有这样的问题(可以保存null值))。

需要使用实体框架在 C# 项目中执行 10 个左联接

这是极不可能的。 在 LINQ 中使用导航属性而不是联接向实体表示查询几乎总有一种更好、更简单的方法。

相反,只需在导航属性中导航以投影相关值。

最新更新