2015-03-10 3 views
7

Ho un database che contiene 3 tabelle:LINQ: C'è un modo per combinare queste query in una?

  • Cellulari
  • PhoneListings
  • PhoneConditions

PhoneListings ha un FK dalla tabella Telefoni (PhoneID), e un FK dal telefono Tabella delle condizioni (conditionID)

Sto lavorando a una funzione che aggiunge un elenco telefonico al carrello dell'utente e restituisce tutte le informazioni necessarie rmazione per l'utente. La marca e il modello del telefono sono contenuti nella tabella PHONES e i dettagli sulla condizione sono contenuti nella tabella PhoneConditions.

Attualmente sto usando 3 query per ottenere tutte le informazioni necessarie. C'è un modo per combinare tutto questo in una query?

public ActionResult phoneAdd(int listingID, int qty) 
{ 

    ShoppingBasket myBasket = new ShoppingBasket(); 
    string BasketID = myBasket.GetBasketID(this.HttpContext); 



    var PhoneListingQuery = (from x in myDB.phoneListings 
          where x.phonelistingID == listingID 
          select x).Single(); 

    var PhoneCondition = myDB.phoneConditions 
          .Where(x => x.conditionID == PhoneListingQuery.phonelistingID).Single(); 

    var PhoneDataQuery = (from ph in myDB.Phones 
          where ph.PhoneID == PhoneListingQuery.phonePageID 
          select ph).SingleOrDefault(); 

} 
+0

qual è il tuo ragionamento per la combinazione? –

+0

Semplicemente così posso ottenere tutte le informazioni di cui ho bisogno da un singolo oggetto, invece di dover fare riferimento ai Tre diversi oggetti. Potrebbe essere eccessivo, ma immagino che imparare a farlo sarebbe utile. – user1698144

+0

È possibile utilizzare join anche https://msdn.microsoft.com/en-us/library/vstudio/bb534675(v=vs.100).aspx – Peyman

risposta

5

Si potrebbe proiettare il risultato in una classe anonima, o di una tupla, o anche un'entità a forma personalizzata in una sola riga, ma le prestazioni complessive del database non potrebbe essere migliore:

var phoneObjects = myDB.phoneListings 
     .Where(pl => pl.phonelistingID == listingID) 
     .Select(pl => new 
     { 
      PhoneListingQuery = pl, 
      PhoneCondition = myDB.phoneConditions 
      .Single(pc => pc.conditionID == pl.phonelistingID), 
      PhoneDataQuery = myDB.Phones 
      .SingleOrDefault(ph => ph.PhoneID == pl.phonePageID) 
     }) 
     .Single(); 

    // Access phoneObjects.PhoneListingQuery/PhoneCondition/PhoneDataQuery as needed 

Ci sono anche sovraccarichi leggermente più compatti delle estensioni LINQ e SingleOrDefault che prendono come parametro un predicato, che aiuta a ridurre leggermente il codice.

Modifica

Come alternativa a molteplici richiami effettuati nell'ambito del ORM DbContext, o fare espliciti manuali Join s, se si imposta navigation relationships tra entità nel modello tramite il navigabile join tasti (di solito le chiavi esterne in le tabelle sottostanti), è possibile specificare la profondità di prendere con un carico ansioso, utilizzando Include:

var phoneListingWithAssociations = myDB.phoneListings 
     .Include(pl => pl.PhoneConditions) 
     .Include(pl => pl.Phones) 
     .Single(pl => pl.phonelistingID == listingID); 

che restituirà il grafico entità phoneListingWithAssociations

(Supponendo chiavi esterne PhoneListing.phonePageID => Phones.phoneId e PhoneCondition.conditionID => PhoneListing.phonelistingID)

2

Si dovrebbe essere in grado di tirare il tutto in una query con join, credo.

Ma come sottolineato, non si può ottenere molta velocità da questo, poiché si sta solo selezionando la prima partita e poi procedendo, senza fare realmente confronti interiori.

Se sai che esistono almeno un punto di dati in ogni tabella, allora potresti anche tirare tutto allo stesso tempo. se non poi aspettare con le "sotto-query" è bello come fatto da StuartLC.

var Phone = (from a in myDB.phoneListings 
     join b in myDB.phoneConditions on a.phonelistingID equals b.conditionID 
     join c in ph in myDB.Phones on a.phonePageID equals c.PhoneID 
     where 
     a.phonelistingID == listingID 
     select new { 
     Listing = a, 
     Condition = b, 
     Data = c 
     }).FirstOrDefault(); 

FirstOrDefault perché errore di lancio singolo se esiste più di un elemento.