Iscriviti / Dove con LINQ e Lambda

Ho problemi con una query scritta in LINQ e Lambda. Finora, sto ricevendo molti errori, ecco il mio codice:

int id = 1; var query = database.Posts.Join(database.Post_Metas, post => database.Posts.Where(x => x.ID == id), meta => database.Post_Metas.Where(x => x.Post_ID == id), (post, meta) => new { Post = post, Meta = meta }); 

Sono nuovo nell’usare LINQ, quindi non sono sicuro che questa query sia corretta.

Trovo che, se hai familiarità con la syntax SQL, l’uso della syntax della query LINQ è molto più chiaro, più naturale e rende più facile individuare gli errori:

 var id = 1; var query = from post in database.Posts join meta in database.Post_Metas on post.ID equals meta.Post_ID where post.ID == id select new { Post = post, Meta = meta }; 

Se sei davvero bloccato sull’uso di lambda, la tua syntax è piuttosto complessa. Ecco la stessa query, utilizzando i metodi di estensione LINQ:

 var id = 1; var query = database.Posts // your starting point - table in the "from" statement .Join(database.Post_Metas, // the source table of the inner join post => post.ID, // Select the primary key (the first part of the "on" clause in an sql "join" statement) meta => meta.Post_ID, // Select the foreign key (the second part of the "on" clause) (post, meta) => new { Post = post, Meta = meta }) // selection .Where(postAndMeta => postAndMeta.Post.ID == id); // where statement 

Potresti andare in due modi con questo. Usando LINQPad (inestimabile se sei nuovo a LINQ) e un database fittizio, ho creato le seguenti query:

 Posts.Join( Post_metas, post => post.Post_id, meta => meta.Post_id, (post, meta) => new { Post = post, Meta = meta } ) 

o

 from p in Posts join pm in Post_metas on p.Post_id equals pm.Post_id select new { Post = p, Meta = pm } 

In questo caso particolare, penso che la syntax LINQ sia più pulita (cambio tra i due a seconda di quale sia più facile da leggere).

La cosa che vorrei sottolineare è che se hai le chiavi esterne appropriate nel tuo database, (tra post e post_meta) allora probabilmente non hai bisogno di un join esplicito a meno che tu non stia cercando di caricare un gran numero di record . Il tuo esempio sembra indicare che stai provando a caricare un singolo post ed i suoi metadati. Supponendo che ci siano molti record post_meta per ogni post, allora potresti fare quanto segue:

 var post = Posts.Single(p => p.ID == 1); var metas = post.Post_metas.ToList(); 

Se vuoi evitare il problema n + 1, allora puoi dire esplicitamente a LINQ di SQL di caricare tutti gli elementi correlati in una volta (anche se questo potrebbe essere un argomento avanzato per quando hai più familiarità con L2S). L’esempio seguente dice “quando carichi un messaggio, carica anche tutti i relativi record associati tramite la chiave esterna rappresentata dalla proprietà” Post_metas “:

 var dataLoadOptions = new DataLoadOptions(); dataLoadOptions.LoadWith(p => p.Post_metas); var dataContext = new MyDataContext(); dataContext.LoadOptions = dataLoadOptions; var post = Posts.Single(p => p.ID == 1); // Post_metas loaded automagically 

È ansible eseguire molte chiamate LoadWith su un singolo set di DataLoadOptions per lo stesso tipo o molti tipi diversi. Se si eseguono questi lotti, si potrebbe semplicemente prendere in considerazione la memorizzazione nella cache.

I selettori di chiave non sono corretti. Dovrebbero prendere un object del tipo della tabella in questione e restituire la chiave da utilizzare nel join. Penso che tu intenda questo:

 var query = database.Posts.Join(database.Post_Metas, post => post.ID, meta => meta.Post_ID, (post, meta) => new { Post = post, Meta = meta }); 

È ansible applicare la clausola where in seguito, non come parte del selettore di chiave.

Daniel ha una buona spiegazione dei rapporti di syntax, ma ho messo insieme questo documento per il mio team per renderlo un po ‘più semplice da capire per loro. Spero che questo aiuti qualcuno inserisci la descrizione dell'immagine qui

Pubblicazione perché quando ho avviato LINQ + EntityFramework, ho guardato questi esempi per un giorno.

Se si utilizza EntityFramework e si dispone di una proprietà di navigazione denominata Meta nell’impostazione dell’object modello Post , questa operazione risulta facile. Se stai utilizzando l’ quadro e non hai quella proprietà di navigazione, cosa stai aspettando?

 database .Posts .Where(post => post.ID == id) .Select(post => new { post, post.Meta }); 

Se stai eseguendo il codice per primo, configurerai la proprietà in questo modo:

 class Post { [Key] public int ID {get; set} public int MetaID { get; set; } public virtual Meta Meta {get; set;} } 

Ho fatto qualcosa del genere;

 var certificationClass = _db.INDIVIDUALLICENSEs .Join(_db.INDLICENSECLAsses, IL => IL.LICENSE_CLASS, ILC => ILC.NAME, (IL, ILC) => new { INDIVIDUALLICENSE = IL, INDLICENSECLAsse = ILC }) .Where(o => o.INDIVIDUALLICENSE.GLOBALENTITYID == "ABC" && o.INDIVIDUALLICENSE.LICENSE_TYPE == "ABC") .Select(t => new { value = t.PSP_INDLICENSECLAsse.ID, name = t.PSP_INDIVIDUALLICENSE.LICENSE_CLASS, }) .OrderBy(x => x.name); 

Potrebbe essere qualcosa di simile

 var myvar = from a in context.MyEntity join b in context.MyEntity2 on a.key equals b.key select new { prop1 = a.prop1, prop2= b.prop1}; 

Questa query di linq dovrebbe funzionare per te. Otterrà tutto il post che ha post meta.

 var query = database.Posts.Join(database.Post_Metas, post => post.postId, // Primary Key meta => meat.postId), // Foreign Key (post, meta) => new { Post = post, Meta = meta }); 

Query SQL equivalente

 Select * FROM Posts P INNER JOIN Post_Metas pm ON pm.postId=p.postId 

1 equivale a 1 due diversi join di tabella

 var query = from post in database.Posts join meta in database.Post_Metas on 1 equals 1 where post.ID == id select new { Post = post, Meta = meta };