Помощь, необходимая для оптимизации извлечения данных linq - PullRequest
0 голосов
/ 30 октября 2009

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

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!!

Ответы [ 2 ]

1 голос
/ 30 октября 2009

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

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

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

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

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

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

1 голос
/ 30 октября 2009

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

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

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

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