Pregunta

Estoy obteniendo datos de las 3 tablas a la vez para evitar la latencia de la red. Obtener los datos es bastante rápido, pero cuando paso por los resultados se usa mucho tiempo

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!!
¿Fue útil?

Solución

¿Por qué te molestas en comprobar los recuentos antes de las declaraciones foreach? Si no hay resultados, el foreach terminará inmediatamente.

En realidad, todas sus consultas se aplazan; se ejecutarán cuando solicite los datos. No olvide que su consulta más externa es una consulta LINQ to Objects: solo devuelve el resultado de llamar a ent.Basket.Where (...). Seleccione (...) etc. que en realidad no ejecuta la consulta.

Su plan para hacer las tres consultas de una vez no está funcionando realmente. Sin embargo, al solicitar el recuento por separado, en realidad puede estar ejecutando cada consulta de base de datos dos veces, una vez solo obteniendo el recuento y una vez por los resultados.

Le sugiero que elimine las "optimizaciones". en este código, que lo hacen mucho más complicado y más lento que simplemente escribir el código más simple que pueda.

No conozco ninguna forma de hacer que LINQ to SQL (o LINQ to EF) ejecute múltiples consultas en una sola llamada, pero este enfoque ciertamente no lo hará.

Otra sugerencia menor que es irrelevante en este caso, pero que puede ser útil en LINQ to Objects: si desea averiguar si hay datos en una colección, use Any () en su lugar de Count () > 0 - de esa manera puede detenerse tan pronto como se encuentre algo.

Otros consejos

Estás usando IEnumerable en el bucle foreach. Las implementaciones solo tienen que preparar los datos cuando se solicitan. De esta manera, sugeriría que el código anterior esté accediendo a sus datos de manera perezosa, es decir, solo cuando enumera los elementos (lo que realmente sucede cuando llama a Count () .)

Coloque un System.Diagnostics.Stopwatch alrededor de la llamada a Count () y vea si eso toma la mayor parte del tiempo que está viendo.

No puedo hacer más comentarios aquí porque no especificas el tipo de ent en tu muestra de código.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top