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

发布于 2024-12-02 09:29:34 字数 2643 浏览 1 评论 0原文

我想我正式有点疯狂了:)我已经使用 Linq to XML 进行了一些工作,但由于速度问题,我不得不重新设计和转换数据并将其放入数据库中。现在我正在重新编写我的管道代码以考虑 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);
    }

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

任何有助于理解这一点的帮助将不胜感激。

I think i am officially going slightly crazy :) i have had something working with Linq to XML but becuase of speed issues i have had to rework and transform the data an place it in a DB instead. Now i am reworking my plumbing code to take into account Linq2Sql but the method sub querying the returned method results that was working with the XML provider just doesnt seem to want to work now?


UPDATE

I have found that my console app that i am using to display the results is doing some funny things. For instance if i call the methods in this order:

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

The availability works but the getRoomTypes doesnt return roomTypes, if i swap them around then the opposite happens, the room types are returned but the availabilility then returns false, so that is why i was getting odd results, i just do not know why this would happen?


For instance my repository returns this:

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

my top level method call does this

    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();
    }

this works when i output it to the screen in a console

    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();
    }

But when i call the following, the rooms collection is 0, but i know that the method returns rooms based on the same query as i outputted it before when i directly call the method above.

    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);
    }

this also happens for a couple of other methods where other objects are not returned when i try and sub query like this, I am trying not to repeat myself with the same code, is there something i should know or am not doing?

Any help in understanding this would be greatly appreciated.

Rob

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

此岸叶落 2024-12-09 09:29:34

那么您的函数 GetRoomAvailability() 在某些情况下返回正确,在某些情况下返回正确?

追踪它并使用一些断点来查看哪里不同怎么样?

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

So your function GetRoomAvailability() returns correct in some cases and in some cases not?

What about tracing it down and use some breakpoints to see where it all is different?

I am not sure but why are you converting your return value from GetRoomAvailability() ToList() and then doing it when recieving it again in DoesHotelHaveAvailabilityForPeriod()?

别靠近我心 2024-12-09 09:29:34

我怀疑您遇到了问题,因为在第一个查询上调用 .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而不是列表的私有方法,可能会更好。

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()。不要在中间查询中使用它们。

I suspect you're hitting issues because you are not explicitly nor implicitly loading the navigation collections before you call .ToList() on your first query.

Try this (or something like it):

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();
}

Also remember that calling .ToList() on the query doesn't call .ToList() on the navigation items.

It would probably be even better if you created a private method that returned the IQueryable<RootType> rather than the list.

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 =>
    // ...
}

The general rule is to only call .ToList() or .ToArray() when returning to the external caller. Don't use them in intermediate queries.

冬天的雪花 2024-12-09 09:29:34

我认为有时日期时间比较存在问题。

例如,如果您尝试查找日期条目,假设 30-08-2011 并且数据库有条目 Date 30-08-2011 12:50:30 ,那么它将不会返回结果。

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

I think sometimes there is problem with DateTime comparison.

For e.g. If you try to find an entry on date, lets say 30-08-2011 and if the database has entry Date 30-08-2011 12:50:30 , then it will not return the result.

What you can try is.. just make time of the dates in sql to 00:00:00 and check if you get correct results.

风筝在阴天搁浅。 2024-12-09 09:29:34

深夜编程对任何人都没有帮助:)我是个傻瓜,根据 linq to 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();
    }

谢谢大家谁拿走了是时候看看了。

Late night programming does not help anyone :) i was being a fool and creating objects based on the object model created by the linq to SQL data context (Room, RoomType, RoomRate Etc), i was searching around and saw a snippet of code saying you cant create objects directly from a query based on your data objects (after i recieved an error) so refactored and created and mapped the model to several corresponding DTO objects and that seems to have cleared up the problem:

Example code change:

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();
    }

Thanks to everyone who took the time to look.

Rob

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文