【问题标题】:decimal? with Left outer join gets null reference in LINQ十进制?左外连接在 LINQ 中获取空引用
【发布时间】:2019-02-22 12:09:49
【问题描述】:

我正在尝试在 LINQ 中为两个 vars 执行左外连接,但在选择所需的列时,我在想要 Nullable decimal 的地方收到 Object reference not set to an instance of an object 错误。

    var FLS = (from ee in SumTillFYEnd 
                        join es in SumTillFYStart on ee.Account equals es.Account into temp
                        from t in temp.DefaultIfEmpty()                             
                        select new
                        {  
                            Account = ee.Account, // As of here it works
                            BeginDr = (t.DrStartCF == 0) ? (decimal?) null : t.DrStartCF // Here I get error Object reference not set to an instance of an object.
                        });

有时 SumTillFYEnd 有时 SumTillFYStart 变为空。我想加入应该使用默认值,以防任何一个或两个都为空。

【问题讨论】:

  • t == null替换t.DrStartCF == 0
  • LINQ 总是显示为空
  • 你不能以IQueryable 的形式运行LINQ 查询,作为一个整体,它会被翻译成SQL 吗?
  • 在我的情况下不,我正在将一个长 sql 存储过程重写到 LINQ。

标签: linq asp.net-core-2.1 ef-core-2.1


【解决方案1】:

问题是试图将null 转换为decimal?。您永远不能直接将null 转换为另一种类型,无论是否可以为空。这将始终导致NullReferenceException。你想要的是default。换句话说,替换:

(decimal?)null

default(decimal?)

【讨论】:

  • 这里 t 为空,这就是访问 t.DrStartCF 给我 NullRef 的原因。我找不到为什么 t 为空的方式
  • 实际上你可以null转换为任何可以为空的类型。
【解决方案2】:

我使用默认类解决了这个问题。

我看到的原因是小数不能为空,因此它需要设置默认值0decimal.MinValue

所以,你需要有SumTillFYStart 的默认类,比如

var defaultSumTillFYStart = new SumTillFYStart { Account = string.Empty, DrStartCF =0};

在上下文中,然后在您的代码中替换

from t in temp.DefaultIfEmpty()

有了这个

from t in temp.DefaultIfEmpty(defaultSumTillFYStart)

我在下面编写了一个 linqPad,但用于不同的子集;我认为它会帮助某人:

void Main()
{
    List<Debtor> debtors = new List<Debtor>();
    List<SecurityHolding> holdings = new List<SecurityHolding>();

    //Initialize Debtor
    debtors.Add(new Debtor(){
        AccountId = "J1",
        OutstandingValue = 501.95M
    });

    debtors.Add(new Debtor(){
        AccountId = "J2",
        OutstandingValue = 75.68M
    });

    debtors.Add(new Debtor(){
        AccountId = "J3",
        OutstandingValue = 100.01M
    });

    //Initialize Security Holding
    holdings.Add(new SecurityHolding(){
        AccountId = "J2",
        SecurityHoldingValue = 100M
    });

    holdings.Add(new SecurityHolding(){
        AccountId = "J3",
        SecurityHoldingValue = 200M
    });


    var defaultHolding = new SecurityHolding { AccountId= string.Empty, SecurityHoldingValue = 0};

    var result = (from d in debtors
                   join p in holdings
                   on d.AccountId equals p.AccountId into temp
                   from t in temp.DefaultIfEmpty(defaultHolding)
                   select new
                   {
                        AccountId = d.AccountId,
                        OutstandingValue = d.OutstandingValue,
                        HoldingValue = (decimal?)t.SecurityHoldingValue
                   });

    result.Dump();
}

// Define other methods and classes here
public class Debtor
{
    public string AccountId {get;set;}
    public decimal OutstandingValue {get;set;}
}

public class SecurityHolding
{
    public string AccountId {get;set;}
    public decimal SecurityHoldingValue {get;set;}
}

这里是输出:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-13
    • 2015-03-06
    • 2012-04-19
    • 2011-08-10
    • 1970-01-01
    • 2011-04-27
    • 2011-08-04
    • 2011-03-25
    相关资源
    最近更新 更多