linq的子查询方法不返回所有对象

时间:2011-08-29 23:10:47

标签: c# linq linq-to-sql

我认为我正式变得有点疯狂:)我有一些与Linq合作的东西,但由于速度问题,我不得不重做并将数据转换为数据库中的数据。现在我正在重新设计我的管道代码以考虑Linq2Sql,但是查询返回的方法结果的方法是否与XML提供程序一起使用似乎现在似乎不想工作?


更新

我发现我用来显示结果的控制台应用程序正在做一些有趣的事情。例如,如果我按此顺序调用方法:

        var available = manager.DoesHotelHaveAvailabilityForPeriod("BTHA", start, end, 10);
        var results = manager.GetRoomTypesForPeriod("BTHA", start, end);

可用性有效,但是getRoomTypes没有返回roomTypes,如果我交换它们然后相反的情况发生,房间类型被返回但是可用性然后返回false,所以这就是为什么我得到奇怪的结果,我只是不知道为什么会这样呢?


例如我的存储库返回:

   public LinqAvailabilityRepository()
    {
        var context = new AvailabilityDataContext();
        _typesTable = context.GetTable<RoomType>();
    }

我的顶级方法调用会执行此操作

    public List<RoomType> GetRoomTypes(string hotelCode)
    {
        var results = from rt in _repository.RoomTypes
                      where rt.Rooms.Any(r => r.HotelCode == hotelCode)
                      select rt;

        return results.ToList();
    }

当我在控制台中将其输出到屏幕时,这是有效的

    public List<RoomType> GetRoomAvailability(string hotelCode, DateTime startDate, DateTime endDate, int daysRequired)
    {
        var items = GetRoomTypes(hotelCode);

        var results = items.Select(rt =>
            new RoomType
            {
                id = rt.id,
                Code = rt.Code,
                Description = rt.Description,
                Name = rt.Name,
                Rooms = rt.Rooms.Select(r =>
                    new Room
                    {
                        id = r.id,
                        RoomRates = r.RoomRates.Where(rr => rr.EffectiveDate >= startDate &&
                            rr.EffectiveDate <= endDate).ToEntitySet()
                    })
                    .Where(r => r.RoomRates.Count == daysRequired)
                    .OrderByDescending(r => r.RoomRates.Count()).ToEntitySet()
            });

        return results.ToList();
    }

但是当我调用以下内容时,房间集合为0,但我知道该方法基于与我之前输出的相同查询返回房间时直接调用上述方法。

    public bool DoesHotelHaveAvailabilityForPeriod(string hotelCode, DateTime startDate, DateTime endDate, int daysRequired)
    {
        var items = GetRoomAvailability(hotelCode, startDate, endDate, daysRequired).ToList();

        return ((from i in items
                where i.Rooms.Count == daysRequired
                select i).Count() > 0);
    }

这也发生在其他一些方法中,当我尝试这样的子查询时没有返回其他对象,我试图不重复自己使用相同的代码,是否有我应该知道或不做的事情?

非常感谢任何理解这一点的帮助。

罗布

4 个答案:

答案 0 :(得分:0)

所以你的函数GetRoomAvailability()在某些情况下返回正确,在某些情况下没有?

如何追踪它并使用一些断点来查看它们的不同之处?

我不确定,但为什么要从GetRoomAvailability() ToList()转换您的返回值,然后在DoesHotelHaveAvailabilityForPeriod()中再次接收它时执行此操作?

答案 1 :(得分:0)

我怀疑您遇到了问题,因为在第一次查询中调用.ToList()之前,您没有明确或隐式加载导航集。

试试这个(或类似的东西):

public List<RoomType> GetRoomTypes(string hotelCode)
{
    var results = from rt in _repository.RoomTypes.Include("Rooms.RoomRates")
                  where rt.Rooms.Any(r => r.HotelCode == hotelCode)
                  select rt;

    return results.ToList();
}

另请注意,在查询中调用.ToList()不会在导航项上调用.ToList()

如果您创建了一个返回IQueryable<RootType>而不是列表的私有方法,那可能会更好。

private IQueryable<RoomType> QueryRoomTypes(string hotelCode)
{
    var results = from rt in _repository.RoomTypes.Include("Rooms.RoomRates")
                  where rt.Rooms.Any(r => r.HotelCode == hotelCode)
                  select rt;

    return results;
}

public List<RoomType> GetRoomTypes(string hotelCode)
{
    return this.QueryRoomTypes(hotelCode).ToList();
}

public List<RoomType> GetRoomAvailability(string hotelCode, DateTime startDate, DateTime endDate, int daysRequired)
{
    var items = this.QueryRoomTypes(hotelCode);

    var results = items.Select(rt =>
    // ...
}

一般规则是仅在返回外部呼叫者时调用.ToList().ToArray()。不要在中间查询中使用它们。

答案 2 :(得分:0)

我认为有时DateTime比较存在问题。

例如如果你试图在日期找到一个条目,让我们说30-08-2011,如果数据库有条目日期30-08-2011 12:50:30,那么它将不会返回结果。

您可以尝试的是..只需将sql中的日期时间设置为00:00:00并检查您是否得到了正确的结果。

答案 3 :(得分:0)

深夜编程对任何人都没有帮助:)我是一个傻瓜,根据linq到SQL数据上下文(Room,RoomType,RoomRate等)创建的对象模型创建对象,我正在四处搜索并看到一个片段代码说你不能直接从基于数据对象的查询创建对象(在我收到错误之后),因此重构并创建并将模型映射到几个相应的DTO对象,这似乎已经解决了问题:

示例代码更改:

public List<RoomTypeDTO> GetRoomAvailability(string hotelCode, DateTime startDate, DateTime endDate, int daysRequired)
{
        var items = GetRoomTypesForPeriod(hotelCode, startDate, endDate);

        var results = items.Select(rt =>
            new RoomTypeDTO
            {
                id = rt.id,
                Code = rt.Code,
                Description = rt.Description,
                Name = rt.Name,
                Rooms = rt.Rooms.Select(r =>
                    new RoomDTO
                    {
                        id = r.id,
                        RoomRates = r.RoomRates.Where(rr => rr.EffectiveDate >= startDate &&
                            rr.EffectiveDate <= endDate).ToList()
                    })
                    .Where(r => r.RoomRates.Count == daysRequired)
                    .OrderByDescending(r => r.RoomRates.Count()).ToList()
            });

        return results.ToList();
    }

感谢所有花时间看的人。

罗布