实体框架(Linq)中的左外部联接.成员实体化为Null



问题:

我可以执行左联接并验证null ed元素吗终止数据库链接?如果是,我该怎么做?

试用代码

var transactions1 = (from tran in ctx.transactions
    group tran.Amount by new { tran.UserID, tran.LeaveID } into leave
    select new { UserID = leave.Key.UserID, LeaveID = leave.Key.LeaveID, Balance = leave.Sum() });
var transactions2 = (from tran in ctx.transactions
    where tran.Type == type && tran.FiscalYear == fiscal
    group tran.Amount by new { tran.UserID, tran.LeaveID } into leave
    select new { UserID = leave.Key.UserID, LeaveID = leave.Key.LeaveID, Rollout = leave.Sum() });
var computed = (from balance in transactions1
               join join_rollout in transactions2 on new { balance.UserID, balance.LeaveID } equals new { join_rollout.UserID, join_rollout.LeaveID } into rolls
               from rollout in rolls.DefaultIfEmpty()
               select new
               {
                   UserID = balance.UserID,
                   LeaveID = balance.LeaveID,
                   computed = rollout.Rollout
               }).ToList();

目标

我正在尝试使用linq左联接两个表。正如人们所猜测的,第二个表的一些值可能导致null。如果我使用三元运算符来验证null ed值,则应用程序将抛出以下异常

DbIsNullExpression的参数必须引用基元、枚举或引用类型。

在PastBin 中查找堆栈跟踪

如果我删除三元验证,应用程序将抛出以下异常

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

在PasteBin 中查找堆栈跟踪

工作解决方案

我可以通过在最终联接(即transactions1.ToList() and transactions2.ToList()(之前终止DB链接(使用slawek建议的.ToList()(来避免这些异常。但是,我希望避免使用.ToList(),因为我需要对数据库表执行另一个联接,而这在列表上是无法完成的。

自SO发布以来我的实验

  • 我尝试过使用UseDatabaseNullSemantics,但我没想到它会解决,但至少有助于解决问题,但结果是Failed

您引用的错误消息:

转换为值类型"System.Decimal"失败,因为物化值为null。结果类型的泛型参数或者查询必须使用可为null的类型。

表示您正试图将null的值附加到System.Decimal类型的字段中。这在.Net中是非法的。System.Decimal是一种值类型。与引用类型不同,这些不能是null。关于参考类型与值类型的一个很好的处理方法可以在这里找到。

当.NET第一次出现的时候,基本上就是这样。后来,很明显,这可能非常不方便,所以.NET的设计者增加了一个新功能,称为可为null的类型。这些可以绕过上述限制。在c#中,通过指定一个值类型,然后添加一个问号来引用一个可为null的类型,比如System.Decimal?或简称decimal?decimal?类型的字段将能够容纳null

你需要告诉编译器你正在使用的类型,它自己无法正确地计算出来。更改代码的这一行:

computed = rollout.Rollout

读起来像这样:

computed = (decimal?)rollout.Rollout

这将表明null是一个有效值,并且您的代码将正常工作。

一般来说,这有助于花一些时间学习基础知识,然后深入了解更复杂的内容,如ORM的使用。如果你不知道基本知识,当某个东西坏了时,很难识别出是什么东西坏了——因为你不知道拼图的所有部分,但一旦你知道了,答案往往是显而易见的。

最新更新