0

我有一个 LINQ 查询,它在调用 ToList() 时在运行时引发 InvalidOperationException,如果可能的话,我试图找出解决方法,而不必将连接分解为单独的 where 子句。

在下面的示例中,有问题的行是 3 和 4。loan_id 是不可为空的十进制类型,ti_disb_id 是不可为空的短类型。当我将它们拆分为单独的语句时,调用 ToList() 时也不例外。然而,它似乎更有意义,所以如果有一个解决方案,我很想听听。:)

        var baseQuery = (from a in context.ti_disbursements
                         join b in context.disbursement_schedule
                             on new {a.loan_id, a.ti_disb_id} equals
                                new {b.loan_id, b.ti_disb_id} into ab
                             from b in ab.DefaultIfEmpty()
                         join c in context.business_associates
                             on a.ba_id equals c.ba_id into ac
                             from c in ac.DefaultIfEmpty()
                         join d in context.investor_loan
                             on b.loan_id equals d.loan_id into ad
                             from d in ad.DefaultIfEmpty()
                         join e in context.loan_information
                             on d.loan_id equals e.loan_id into ae
                             from e in ae.DefaultIfEmpty()
                         join f in context.loan_balances
                             on e.loan_id equals f.loan_id into af
                             from f in af.DefaultIfEmpty()
                         join g in context.ti_information
                             on e.loan_id equals g.loan_id into ag
                             from g in ag.DefaultIfEmpty()
                         select new
                         {
                             loan_id = a.loan_id,
                             ti_disb_id = a.ti_disb_id,
                             ti_freq_id = a.ti_freq_id,
                             ti_disbursements_stop_code = a.ti_stop_code,
                             tax_account_number = a.tax_account_number,
                             ti_disb_due_dt = b.ti_disb_due_dt,
                             ti_expire_dt = b.ti_expire_dt,
                             ti_disb_amt = b.ti_disb_amt,
                             schedule_id = b.schedule_id,
                             ba_name = c.ba_name,
                             inv_bank_cd = d.inv_bank_cd,
                             inv_cd = d.inv_cd,
                             inv_group_cd = d.inv_group_cd,
                             loan_name = e.loan_name,
                             prin_bal = f.prin_bal,
                             ti_bal = f.ti_bal,
                             ti_information_stop_code = g.ti_stop_cd,
                             non_escrowed_type = a.non_escrowed_type,
                             ba_type_id = a.ba_type_id,
                             bill_received_dt = a.bill_received_dt,
                         });

异常消息:

用户代码未处理 InvalidOperation 异常

转换为值类型“Int16”失败,因为具体化值为空。结果类型的泛型参数或查询必须使用可为空的类型。

提前非常感谢!

4

3 回答 3

1

继续 Garrison 的评论,我建议您使用上下文 Log 属性。打开 a StreamWriter,并分配给context.Log。它将为您提供在数据库上运行的确切 SQL 查询,您可以运行它并查看问题出在哪里。

于 2013-06-04T23:03:08.257 回答
1

您可能想再看看您的数据库。例外情况是其中一条短裤以 null (a.ti_disb_ida.ti_disb_id) 的形式返回。如有必要,您可以if在查询中放置一条语句或使用空合并运算符。

我认为更改new {a.loan_id, a.ti_disb_id}new { loan = a.loan_id, disb = a.ti_disb_id ?? 0}将解决您的问题。空合并运算符基本上是说如果此值为空,则使用提供的默认值。为了使用它,需要赋值(我试过只是做a.ti_disb_id ?? 0,但它不会编译),这就是我输入属性名称的原因。参考文档在这里

于 2013-06-04T23:05:43.277 回答
0

所以,长话短说,经过多次调试,我发现问题在于我使用的是 LEFT JOIN 行为而不是 INNER JOIN 行为。

具体来说,对 DefaultIfEmpty() 的调用正在创建导致 schedule_id 的空值的行,它的类型是不可为空的 short (Int16),从而导致异常。通过取出这些 DefaultIfEmpty() 调用,不包括坏行,问题就解决了,因为 schedule_id 永远不会收到空值。

于 2013-06-05T17:20:55.587 回答