2011-10-14 14 views
13

Esistono numerosi post relativi a LINQ e join multipli. Non ho tuttavia trovato alcuna soluzione per il join che vorrei fare.LINQ to Entity: condizioni multiple join

L'equivalente SQL sarebbe qualcosa di simile a questo:

SELECT * FROM table1 a 
LEFT JOIN table2 b ON a.col1 = b.key1 AND 
a.col2 = b.key2 AND 
b.from_date <= now() AND 
b.deleted = 0; 

Ecco una delle numerose query LINQ ho tentato

var query = (from x in context.table1 
      join y in context.table2 on new {x.col1, x.col2} equals {b.key1, b.key2} 
      into result 
      from result...... 

Come posso aggiungere le condizioni di additonal dalla data e cancellate bandiera? Se uso. In condizioni, questo viene trattato come join interno, non come join sinistro.

risposta

32

Un altro modo potrebbe essere come

var query = (from x in context.table1 
      join y in context.table2 on 
      new { 
        Key1 = x.col1, 
        Key2 = x.col2 
        Key3 = true, 
        Key4 = true 
       } 
      equals 
      new { 
        Key1 = y.key1, 
        Key2 = y.key2, 
        Key3 = y.from_date< DateTime.Now, 
        Key4 = !y.deleted 
       } 
      into result 
from r in result.DefaultIfEmpty() 
select new {x.Something, r.Something} 
1

Non è possibile filtrare il primo set di risultati con una seconda query?

var query = (from x in context.table1 
      join y in context.table2 on new {x.col1, x.col2} equals {b.key1, b.key2} 
      into result 
query = from x in query 
     where ... 

Questo funzionerebbe?

11

LINQ supporta sia la sintassi join e il più vecchio ANSI-82 DOVE sintassi. Utilizzando il più tardi, si potrebbe fare quello che cercate da con

var nowTime = DateTime.Now; 
var query = from a in context.table1 
      from b in context.table2 
      where a.col1 == b.key1 
       && a.col2 == b.key2 
       && b.from_date < nowTime 
       && b.deleted == false 
      select ???; 

In alternativa, è possibile utilizzare un ibrido di dove e aderire. (Rendetevi conto che l'ordine nella query LINQ non ha bisogno di imitare quello che si fa in SQL e l'ordine è più flessibile.)

var nowTime = DateTime.Now; 
var query = from b in context.table2 
      where b.from_date < nowTime 
       && b.deleted == false 
      join a on new {b.key1, b.key2} equals new {a.col1, a.col2} 
      select ???; 
0

Ho avuto problemi con la denominazione di immobili a oggetto anonimo:

var subscriptions = context.EmailSubscription.Join(context.EmailQueue, 
        es => new { es.Id, 9 }, 
        eq => new { eq.EmailSubscriptionId, eq.EmailTemplateId }, 
        (es, eq) => new { es.Id, eq.Id } 
       ).ToList(); 

Il compilatore non era felice, quindi la risposta sopra mi aiuta a capire cosa c'è che non va e qui è la mia soluzione di lavoro. Mi ci è voluto un po 'di tempo per trovare uno stupido errore :):

var subscriptions = context.EmailSubscription.Join(context.EmailQueue, 
        es => new { EmailSubscriptionId = es.Id, EmailTemplateId = 9 }, 
        eq => new { eq.EmailSubscriptionId, eq.EmailTemplateId }, 
        (es, eq) => new { es.Id, eq.Id } 
       ).ToList();