Linq To Entities Query - PullRequest
       2

Linq To Entities Query

4 голосов
/ 25 января 2012

Рассмотрим следующий запрос:

var profilelst =
    (
        from i in dbContext.ProspectProfiles
        where i.CreateId == currentUser
        select new ProspectProfile
        {
            ProspectId = i.ProspectId,
            Live = i.Live,
            Name = i.Name,
            ServiceETA = i.Opportunities.OrderByDescending(t => t.FollowUpDate)
                .FirstOrDefault()
                .ServiceETA.ToString(),
            FollowUpDate = i.Opportunities.OrderByDescending(t => t.FollowUpDate)
                .FirstOrDefault()
                .FollowUpDate
        }
    )
    .ToList();

return profilelst.OrderByDescending(c=>c.FollowUpDate)
        .Skip(0).Take(endIndex)
        .ToList();

Здесь, в этом запросе, пожалуйста посмотрите на FollowUpDate и ServiceType, они оба я извлек из таблицы Opportunity, есть ли другой способ обойти эти оба ..

Отношение «один ко многим» в таблицах: ProspectProfile -> Opportunities

Является ли написанный мною запрос в порядке, или есть другой способ обойти это, что можно сделать более простым способом.

Ответы [ 2 ]

4 голосов
/ 25 января 2012

Единственное, что вы можете улучшить, - это избегать повторного заказа, изменив свой код следующим образом:

var profilelst
  = dbContext.ProspectProfiles
             .Where(i => i.CreateId == currentUser)
             .Select(i => 
                    {
                        var opportunity
                           = i.Opportunities
                              .OrderByDescending(t => t.FollowUpDate)
                              .First();
                        return new ProspectProfile
                        {
                            ProspectId = i.ProspectId,
                            Live = i.Live, 
                            Name = i.Name,
                            ServiceETA = opportunity.ServiceETA.ToString(),
                            FollowUpDate = opportunity.FollowUpDate
                        }
                    }).ToList();

return profilelst.OrderByDescending(c => c.FollowUpDate).Take(endIndex).ToList();

Я сделал несколько изменений в вашем исходном запросе:

  1. Я изменилэто использовать синтаксис цепочек методов.На мой взгляд, читать намного проще.
  2. Я удалил ненужные Skip(0).
  3. Самое большое изменение в Select части:
    1. Iизменил FirstOrDefault на First, потому что вы все равно получаете доступ к свойствам возвращаемого значения.Это создаст описательное исключение, если никакой возможности не существует.Это лучше, чем то, что у вас было: в вашем случае это бросило бы NullReferenceException.Это плохо, NullReferenceExceptions всегда указывает на ошибку в вашей программе и не носит описательный характер.
    2. Я переместил часть, которая выбирает возможность, из инициализатора, поэтому нам нужно выполнить сортировку только один раз вместодважды.
1 голос
/ 26 января 2012

В вашем запросе довольно много проблем:

  • Вы не можете проецировать в сущность (select new ProspectProfile).LINQ to Entities поддерживает проекции только на анонимные типы (select new) или другие типы, которые не являются частью вашей модели данных сущностей (select new MySpecialType)

  • ToString() для числовых илиТип DateTime не поддерживается в LINQ to Entities (ServiceETA.ToString())

  • FirstOrDefault().ServiceETA (или FollowUpdate) вызовет исключение, если коллекция Opportunities пуста иServiceETA - это тип значения, не допускающий значения NULL (например, DateTime), поскольку EF не может материализовать какое-либо значение в такую ​​переменную.

  • Использование .ToList() после выполнения первого запросазапрос в базу данных и загрузить полный результат.Ваша последующая Take происходит в памяти в полном списке, а не в базе данных.(Вы эффективно загружаете весь список результатов из базы данных в память, а затем выбрасываете все объекты, кроме первого Take ru.

Чтобы решить все четыре проблемы, вы можете попробоватьследующее:

var profilelst = dbContext.ProspectProfiles
    .Where(p => p.CreateId == currentUser)
    .Select(p => new
    {
        ProspectId = p.ProspectId,
        Live = p.Live,
        Name = p.Name,
        LastOpportunity = p.Opportunities
           .OrderByDescending(o => o.FollowUpDate)
           .Select(o => new
           {
               ServiceETA = o.ServiceETA,
               FollowUpDate = o.FollowUpDate
           })
           .FirstOrDefault()
    })
    .OrderByDescending(x => x.LastOpportunity.FollowUpDate)
    .Skip(startIndex)  // can be removed if startIndex is 0
    .Take(endIndex)
    .ToList();

Это даст вам список анонимных объектов. Если вам нужен результат в списке вашей сущности ProspectProfile, вы должны скопировать значения после этого запроса. Обратите внимание, что LastOpportunity можетбыть null в результате, если ProspectProfile не имеет Opportunities.

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