C# .NET 7,我在尝试从 DBContext 查询数据时得到 Nullable Object must have a value

问题描述 投票:0回答:3

通过使用.NET 7,我的代码如下

    var query = from c in dbContext.Customers
                from o in dbContext.Orders.Select(o => new { Id = o.Id, Number = o.Number }).Where(o => o.CustomerId == c.Id)
               .DefaultIfEmpty()
                select new
                {
                     Customer = c,
                     Order = o 
                };
    
    var result = await query.ToListAsync();

我在 Orders.Select 语句中使用匿名类型的原因是我只想获取 2 个字段订单 ID 和订单号以加快性能,

有些客户不会有任何订单,所以在运行时,它会抛出异常 Nullable object must have a value with stack trace :

System.InvalidOperationException HResult=0x80131509
Message=Nullable 对象必须有一个值。
Source=System.Private.CoreLib StackTrace: 在 System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_NoValue() 在 Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()

你能告诉我应该改变什么来摆脱这个异常吗,谢谢你的帮助。

尝试通过以下方式检查 null,但 不起作用

  1. dbContext.Orders.Select(o => o != null ? new { Id = o.Id, Number = o.Number } : new  { Id = Guid.NewGuid(), Number = 0})

  2. dbContext.Orders.Select(o => o != null ? new Order { Id = o.Id, Number = o.Number } : (Order) null)

  3. select new { Customer  = c, Order = o != null ? o : new Order() { Id = Guid.NewGuid(), Number = 0}}

c# entity-framework-core entity-framework-6 nullable .net-7.0
3个回答
0
投票

你在 LINQ 查询中使用了 DefaultIfEmpty() 方法,它返回一个空值在这种情况下,当没有找到客户的匹配订单时,它会通过错误。 为了避免这个问题试试这个,

var query = from c in dbContext.Customers
            from o in dbContext.Orders
                .Where(o => o.CustomerId == c.Id)
                .Select(o => new { Id = o.Id, Number = o.Number })
                .DefaultIfEmpty()
            select new
            {
                Customer = c,
                Order = o?.Id != null ? new { Id = o.Id, Number = o.Number } : null
            };

var result = await query.ToListAsync();

0
投票

我会重写查询以在最终投影中执行投影:

var query = from c in dbContext.Customers
    from o in dbContext.Orders
        .Where(o => o.CustomerId == c.Id)
        .DefaultIfEmpty()
    select new
    {
        Customer = c,
        Order = o == null
            ? null
            : new
            {
                o.Id,
                o.Number
            } 
    };

但是您也可以尝试显式指定匿名成员的类型:

var query = from c in dbContext.Customers
    from o in dbContext.Orders
        .Select(o => new { Id = (int?)o.Id, Number = o.Number })
        .Where(o => o.CustomerId == c.Id)
        .DefaultIfEmpty()
    select new
    {
        Customer = c,
        Order = o 
    };

请注意,您始终可以正确设置关系并执行以下操作,而不是手动编写连接:

var list = ctx.Customers
    .Select(c => new
    {
        Customer = c,
        Orders = c.Orders.Select(o => new { o.Id, ... }).ToList()
    })
    .ToList();

0
投票
var query = from c in dbContext.Customers
           join a in dbContext.Orders on c.CustomerId equals a.CustomerId into ps
            from suborder in ps.DefaultIfEmpty()
            select new
            {
                Customer = c,
                Order = suborder //deal with null, assign some generic object or whatever you need
            };

var result = await query.ToListAsync();
Console.WriteLine(result);

我想这就是你要找的。请更改您的财产名称

© www.soinside.com 2019 - 2024. All rights reserved.