Помощь, необходимая для оптимизации извлечения данных linq
-
22-07-2019 - |
Вопрос
Я извлекаю данные из всех 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!!
Решение
Почему вы пытаетесь проверить счет до выражений foreach? Если результатов нет, foreach просто завершится немедленно.
Ваши запросы фактически все откладываются - они будут выполняться как и когда вы запрашиваете данные. Не забывайте, что ваш самый внешний запрос - это запрос LINQ to Objects: он просто возвращает результат вызова ent.Basket.Where (...). Select (...)
и т. Д ... который на самом деле не выполняет запрос.
Ваш план выполнить все три запроса за один раз фактически не работает. Однако, запрашивая счетчик отдельно, вы, возможно, выполняете каждый запрос к базе данных дважды - один раз просто для получения счетчика и один раз для результатов.
Я настоятельно рекомендую вам избавиться от " оптимизаций " в этом коде, который делает его намного более сложным и медленным , чем просто написание самого простого кода, который вы можете.
Я не знаю ни одного способа заставить LINQ to SQL (или LINQ to EF) выполнить несколько запросов за один вызов - но этот подход, безусловно, не собирается это делать.
Еще один второстепенный совет, который не имеет значения в этом случае, но может быть полезен в LINQ to Objects - если вы хотите узнать, есть ли какие-либо данные в коллекции, просто используйте вместо этого Any ()
из Count () > 0
- таким образом он может остановиться, как только найдет что-нибудь.
Другие советы
Вы используете IEnumerable
в цикле foreach. Реализации должны подготовить данные только тогда, когда они запрашиваются. Таким образом, я бы предположил, что приведенный выше код лениво обращается к вашим данным - то есть, только когда вы перечисляете элементы (что на самом деле происходит, когда вы вызываете Count ()
.)
Поместите System.Diagnostics.Stopwatch
вокруг вызова Count ()
и посмотрите, занимает ли это большую часть времени, которое вы видите.
Я не могу комментировать дальше, потому что вы не указываете тип ent
в своем примере кода.