2009-10-30 6 views
0

Я получаю данные из всех трех таблиц сразу, чтобы избежать латентности сети. Извлечение данных довольно быстро, но когда я Перебери результаты много времени используетсяПомощь, необходимая для оптимизации извлечения данных linq

Int32[] arr = { 1 }; 
var query = from a in arr 
      select new 
      { 
       Basket = from b in ent.Basket 
         where b.SUPERBASKETID == parentId 
         select new 
         { 
          Basket = b, 
          ObjectTypeId = 0, 
          firstObjectId = "-1", 
         }, 

       BasketImage = from b in ent.Image 
          where b.BASKETID == parentId 
          select new 
          { 
           Image = b, 
           ObjectTypeId = 1, 
           CheckedOutBy = b.CHECKEDOUTBY, 
           firstObjectId = b.FIRSTOBJECTID, 
           ParentBasket = (from parentBasket in ent.Basket 
               where parentBasket.ID == b.BASKETID 
               select parentBasket).ToList()[0], 
          }, 

       BasketFile = from b in ent.BasketFile 
          where b.BASKETID == parentId 
          select new 
          { 
           BasketFile = b, 
           ObjectTypeId = 2, 
           CheckedOutBy = b.CHECKEDOUTBY, 
           firstObjectId = b.FIRSTOBJECTID, 
           ParentBasket = (from parentBasket in ent.Basket 
               where parentBasket.ID == b.BASKETID 
               select parentBasket), 
          } 
      }; 

//Exception handling 

var mixedElements = query.First(); 
ICollection<BasketItem> basketItems = new Collection<BasketItem>(); 

//Here 15 millis has been used 
//only 6 elements were found 

if (mixedElements.Basket.Count() > 0) 
{ 
    foreach (var mixedBasket in mixedElements.Basket){} 
} 

if (mixedElements.BasketFile.Count() > 0) 
{ 
    foreach (var mixedBasketFile in mixedElements.BasketFile){} 
} 

if (mixedElements.BasketImage.Count() > 0) 
{ 
    foreach (var mixedBasketImage in mixedElements.BasketImage){} 
} 

//the empty loops takes 811 millis!! 

ответ

1

Почему вы пытаетесь проверить счет перед заявлениями foreach? Если результатов нет, foreach сразу закончит.

Ваши запросы на самом деле все отложены - они будут выполнены как и когда вы запрашиваете данные. Не забывайте, что ваш внешний запрос представляет собой запрос LINQ to Objects: он просто возвращает результат вызова ent.Basket.Where(...).Select(...) и т. Д. ... который фактически не выполняет запрос.

Ваш план выполнения всех трех запросов за один раз на самом деле не работает. Однако, запросив счетчик отдельно, вы можете выполнять запрос каждой базы данных дважды - как только вы получите счет и один раз для получения результатов.

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

Я не знаю, как получить LINQ to SQL (или LINQ to EF) для выполнения нескольких запросов в одном вызове, но этот подход, конечно же, не собирается этого делать.

одна незначительная подсказка, которая не имеет никакого значения в данном случае, но может быть полезно в LINQ к объектам - если вы хотите, чтобы выяснить, есть ли какие-либо данные в коллекции, просто использовать Any() вместо Count() > 0 - таким образом он может остановить как только он найдет что-нибудь.

1

Вы используете IEnumerable в цикле Еогеаспа. Реализации должны только готовить данные, когда их просят. Таким образом, я хотел бы предложить, что приведенный выше код доступа к данным лениво - то есть только тогда, когда вы перечислить элементы

Поместите System.Diagnostics.Stopwatch вокруг вызова Count() (который на самом деле происходит, когда вы звоните Count().) и посмотрите, берет ли это большую часть времени, которое вы видите.

Здесь я не могу комментировать, потому что вы не указываете тип ent в своем примере кода.