左外部加入实体框架(Linq)。成员实现为空

时间:2015-07-02 12:40:55

标签: c# sql-server linq entity-framework left-join

问题:

我是否可以执行左连接并验证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。结果类型的通用参数或查询必须使用可空类型。

PasteBin

找到堆栈跟踪

工作解决方案

我可以通过在最终加入之前终止数据库链接(使用slawek建议使用.ToList())来避免这些异常(即transactions1.ToList() and transactions2.ToList()。但我希望避免使用.ToList(),因为我需要使用DB表执行另一个连接,这不能在List上完成。

我的实验自SO帖子

  • 我已尝试使用UseDatabaseNullSemantics我不希望解决此问题,但至少在解决方案中提供了帮助,但结果是 Failed

1 个答案:

答案 0 :(得分:0)

您引用的错误消息:

  

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

表示您正在尝试将null的值分配给System.Decimal类型的字段。这在.Net中是非法的。 System.Decimal是值类型。与引用类型不同,它们不能是null。可以找到对引用类型与值类型的良好处理here

当.NET第一次出现时,基本上是它。后来很明显,这可能非常不方便,因此.net设计师隐藏了一个名为nullable types的新功能。这些允许绕过这个限制。在c#中,您可以通过指定值类型然后向其添加问号来引用可空类型,例如:System.Decimal?或简称decimal?decimal?类型的字段将能够容纳null

你需要告诉编译器你正在使用的类型,它无法正确地解决它。更改代码的这一行:

computed = rollout.Rollout

这样读:

computed = (decimal?)rollout.Rollout

这表示null是一个有效值,您的代码将起作用。

一般来说,它有助于花一些时间学习基础知识,之前潜入更复杂的东西,如ORM使用。如果您不了解基础知识,当某些内容破裂时,很难确定什么打破了 - 因为您没有拼图的所有部分,但是一旦您了解它们,通常答案是显而易见的