问题:
我可以执行左联接并验证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的使用。如果你不知道基本知识,当某个东西坏了时,很难识别出是什么东西坏了——因为你不知道拼图的所有部分,但一旦你知道了,答案往往是显而易见的。