Domanda

Sto recuperando i dati da tutte e 3 le tabelle contemporaneamente per evitare la latenza della rete. Il recupero dei dati è piuttosto veloce, ma quando eseguo il ciclo tra i risultati viene utilizzato molto tempo

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!!
È stato utile?

Soluzione

Perché ti preoccupi di controllare i conteggi prima delle dichiarazioni foreach? Se non ci sono risultati, la foreach finirà immediatamente.

Le tue query in realtà vengono tutte rinviate: verranno eseguite come e quando richiedi i dati. Non dimenticare che la tua query più esterna è una query LINQ to Objects: sta solo restituendo il risultato della chiamata ent.Basket.Where (...). Seleziona (...) ecc ... che in realtà non esegue la query.

Il tuo piano per eseguire tutte e tre le query in una volta sola non funziona davvero. Tuttavia, chiedendo il conteggio separatamente, potresti effettivamente eseguire ogni query del database due volte, una volta solo ottenendo il conteggio e una volta per i risultati.

Ti consiglio vivamente di sbarazzarti delle " ottimizzazioni " in questo codice che lo rende molto più complicato e più lento rispetto alla semplice scrittura del codice più semplice che puoi.

Non conosco alcun modo per fare in modo che LINQ to SQL (o LINQ to EF) esegua più query in una singola chiamata, ma questo approccio certamente non lo farà.

Un altro suggerimento minore che è irrilevante in questo caso, ma può essere utile in LINQ to Objects - se vuoi scoprire se ci sono dati in una raccolta, usa invece Any () di Count () > 0 - in questo modo può fermarsi non appena trova qualcosa.

Altri suggerimenti

Stai usando IEnumerable nel ciclo foreach. Le implementazioni devono preparare i dati solo quando richiesti. In questo modo, suggerirei che il codice sopra acceda pigramente ai tuoi dati, vale a dire solo quando si enumerano gli elementi (cosa che accade effettivamente quando si chiama Count () .)

Metti un System.Diagnostics.Stopwatch attorno alla chiamata su Count () e vedi se ci vuole gran parte del tempo che vedi.

Non posso commentare ulteriormente qui perché non specifichi il tipo di ent nell'esempio di codice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top