методы подзапроса с linq не возвращают все объекты - PullRequest
2 голосов
/ 30 августа 2011

Я думаю, что я официально схожу с ума :) У меня было кое-что, работающее с Linq для 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);
    }

это также происходит для пары других методов, где другие объекты не возвращаются при попыткеи подзапрос, как это, я пытаюсь не повторять себя с тем же кодом, есть что-то, что я должен знать или не делаю?

Любая помощьв понимании это будет с благодарностью.

Роб

Ответы [ 4 ]

0 голосов
/ 30 августа 2011

Позднее ночное программирование никому не помогает :) Я был дураком и создавал объекты на основе объектной модели, созданной контекстом данных linq to SQL (Room, RoomType, RoomRate Etc), я искал вокруг и увидел фрагмент кода, говорящего о том, что вы не можете создавать объекты непосредственно из запроса, основанного на ваших объектах данных (после того, как я получил ошибку), поэтому реорганизовал и создал модель, сопоставив ее с несколькими соответствующими объектами 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();
    }

Спасибо всем, кто нашел время, чтобы посмотреть.

Rob

0 голосов
/ 30 августа 2011

Я подозреваю, что вы сталкиваетесь с проблемами, потому что вы не явно или неявно загружаете коллекции навигации, прежде чем вызывать .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() только при возврате к внешнему абоненту.Не используйте их в промежуточных запросах.

0 голосов
/ 30 августа 2011

Я думаю, что иногда возникает проблема со сравнением DateTime.

Например, если вы пытаетесь найти запись по дате, скажем, 30-08-2011, и если в базе данных есть дата Date 30-08-201112:50:30, тогда он не вернет результат.

То, что вы можете попробовать, это просто ... просто укажите время в sql до 00:00:00 и проверьте, получите ли вы правильные результаты.

0 голосов
/ 30 августа 2011

То есть ваша функция GetRoomAvailability() в некоторых случаях верна, а в некоторых - нет?

А как насчет отслеживания и использования некоторых точек останова, чтобы увидеть, где все это отличается?

Я не уверен, но почему вы конвертируете возвращаемое значение из GetRoomAvailability() ToList (), а затем делаете это при получении его снова в DoesHotelHaveAvailabilityForPeriod()?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...