【问题标题】:Linq to Sql .Except not working if null in C#Linq to Sql 。除非在 C# 中为 null 时不工作
【发布时间】:2013-06-02 02:24:46
【问题描述】:

我有一个简单的查询。

它检查房间列表 - prebookedRooms

然后它检查另一个房间列表,但使用.Except 运算符从后续列表中删除任何prebookedRooms

        // Get list of rooms already booked
        var prebookedRooms = dbt.Rooms
            .Where(room => room.Rentals.Any(rental =>
                (dteFrom >= rental.check_in && dteFrom < rental.check_out)));

        // Get list of rooms
        var rooms = dbt.Rooms.Where(r => r.h_id == AccID)
            .Except(prebookedRooms)
            .GroupBy(p => p.RoomTypes).Select(g => new RatesViewModel
            {
                TypeName = g.Key.t_name,
                TypeID = g.Key.t_id,
                TypeCount = g.Count()
            })
            .ToList();

这很好用 - rooms 返回房间列表,prebookedRooms 除外。

但是,如果 prebookedRooms 没有返回任何记录(即空的“枚举未产生结果”) - 则在执行第二个查询时出现错误(var rooms = ...):

The cast to value type 'Int64' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.

是否在第二个查询中检查 prebookedRooms 是否为空,这样我可以避免此错误?

prebookedRooms 模型:

public class Room
{
    [Key]
    public long room_id { get; set; }
    public long hotel_id { get; set; }
    public long type_id { get; set; }
}

在 VS 中出现的错误是:

谢谢,

标记

【问题讨论】:

  • 在尝试.GroupBy 之前,您是否有任何理由无法拆分查询并测试dbt.Rooms.Where(r =&gt; r.h_id == AccID).Except(prebookedRooms) 的结果是否不为空?
  • 嗨 - 房间总是会返回记录 - 只有当 prebookedRooms 没有记录时,房间查询才会失败。谢谢,马克
  • 这就是我的观点 - 通过在 Except 处拆分查询,您可以在执行 GroupBy 之前检查它是否为空。
  • 我如何拆分查询?我不知道该怎么做,然后继续使用 GroupBy。

标签: c# linq linq-to-sql


【解决方案1】:

你不能直接从Except辞职并写信吗:

    var rooms = dbt.Rooms.Where(r => r.h_id == AccID)
        .Where(room => !room.Rentals.Any(rental =>
            (dteFrom >= rental.check_in && dteFrom < rental.check_out))).
        .GroupBy(p => p.RoomTypes).Select(g => new RatesViewModel
        {
            TypeName = g.Key.t_name,
            TypeID = g.Key.t_id,
            TypeCount = g.Count()
        })
        .ToList();

【讨论】:

    【解决方案2】:

    尝试使用null coalescing 运算符:??,然后得到IQueryable&lt;T&gt; 等效于Enumerable&lt;T&gt;.Empty,即Enumerable&lt;T&gt;.Empty().AsQueryable()DefaultIfEmpty 与无效房间,所以它不会发疯为空||空:

        var rooms = dbt.Rooms.Where(r => r.h_id == AccID)
            .Except(prebookedRooms ?? Enumerable.Empty<T>().AsQueryable().DefualtIfEmpty(new Room() { room_id = -1, hotel_id = -1, type_id = -1}))
            .GroupBy(p => p.RoomTypes).Select(g => new RatesViewModel
            {
                TypeName = g.Key.t_name,
                TypeID = g.Key.t_id,
                TypeCount = g.Count()
            })
            .ToList();
    

    我不知道你的类型,所以我不知道在Enumerable.Empty&lt;T&gt; 调用的通用参数中放入什么。自己添加。

    另外,记得要using System.Linq

    【讨论】:

    • 感谢您的建议。不幸的是,它没有效果(我确实添加了正确的类型 - 但 prebookedRooms 仍然“没有产生任何结果”,当第二个查询运行时,错误仍然存​​在。
    • 这很奇怪......意味着它将空集合视为null
    • 我尝试添加 ??在第二个查询中,根据您上面的更新 - 但我仍然得到同样的错误。
    • @fixit 是否有一个值永远不会在数据库中,因此您可以安全地将其传递给 DefaultIfEmpty,这样它就不会抛出那个奇怪的错误?
    • 嗨 - 我一直在检查 - preBookedRooms 将保存 long, long, long 的集合 - 例如。 1245,56,3 - 我如何将其输入 DefaultIfEmpty() - DefaultIfEmpty(1245,56,3) 是不允许的。再次感谢您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多