it-swarm.com.de

Join/Where mit LINQ und Lambda

Ich habe Probleme mit einer in LINQ und Lambda geschriebenen Abfrage. Bisher bekomme ich eine Menge Fehler. Hier ist mein Code:

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 });

Ich bin neu mit LINQ, daher bin ich mir nicht sicher, ob diese Abfrage korrekt ist.

353
David

Wenn Sie mit der SQL-Syntax vertraut sind, ist die Verwendung der LINQ-Abfragesyntax viel klarer, natürlicher und erleichtert das Auffinden von Fehlern:

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 };

Wenn Sie wirklich Lambdas verwenden wollen, ist Ihre Syntax ein bisschen abwegig. Hier ist die gleiche Abfrage mit den LINQ-Erweiterungsmethoden:

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
825
Daniel Schaffer

Sie könnten zwei Wege gehen. Mit LINQPad (von unschätzbarem Wert, wenn Sie LINQ noch nicht kennen) und einer Dummy-Datenbank habe ich die folgenden Abfragen erstellt:

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

oder

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

In diesem speziellen Fall denke ich, dass die LINQ-Syntax sauberer ist (ich wechsle zwischen den beiden, je nachdem, was am einfachsten zu lesen ist).

Ich möchte jedoch darauf hinweisen, dass, wenn Sie geeignete Fremdschlüssel in Ihrer Datenbank haben (zwischen post und post_meta), Sie wahrscheinlich keinen expliziten Join benötigen, wenn Sie nicht versuchen, eine große Anzahl von Datensätzen zu laden . Ihr Beispiel scheint darauf hinzudeuten, dass Sie versuchen, einen einzelnen Beitrag und seine Metadaten zu laden. Angenommen, es gibt viele post_meta-Datensätze für jeden Beitrag, dann könnten Sie Folgendes tun:

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

Wenn Sie das n + 1-Problem vermeiden möchten, können Sie LINQ to SQL explizit mitteilen, dass alle zugehörigen Elemente auf einmal geladen werden sollen (dies ist jedoch möglicherweise ein fortgeschrittenes Thema, wenn Sie mit L2S vertraut sind). Das folgende Beispiel besagt "Wenn Sie einen Beitrag laden, laden Sie auch alle zugehörigen Einträge über den Fremdschlüssel, der durch die 'Post_metas'-Eigenschaft dargestellt wird":

var dataLoadOptions = new DataLoadOptions();
dataLoadOptions.LoadWith<Post>(p => p.Post_metas);

var dataContext = new MyDataContext();
dataContext.LoadOptions = dataLoadOptions;

var post = Posts.Single(p => p.ID == 1); // Post_metas loaded automagically

Es ist möglich, viele LoadWith-Aufrufe für einen einzigen Satz von DataLoadOptions für denselben Typ oder für viele verschiedene Typen durchzuführen. Wenn Sie diese Lots jedoch ausführen, möchten Sie vielleicht nur das Caching in Betracht ziehen.

61
Damian Powell

Ihre Tastenauswahl ist falsch. Sie sollten ein Objekt vom Typ der betreffenden Tabelle verwenden und den Schlüssel zurückgeben, der im Join verwendet werden soll. Ich denke du meinst das:

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

Sie können die where-Klausel nachträglich anwenden, nicht als Teil der Schlüsselauswahl.

32
Mark Byers

Daniel hat eine gute Erklärung der Syntaxbeziehungen, aber ich habe dieses Dokument für mein Team zusammengestellt, um es für sie ein wenig einfacher zu verstehen. Hoffe das hilft jemand  enter image description here

24
Talspaugh27

Posting, weil ich, als ich LINQ + EntityFramework startete, einen Tag lang auf diese Beispiele starrte.

Wenn Sie EntityFramework verwenden und in Ihrem Modellobjekt Meta eine Navigationseigenschaft mit dem Namen Post eingerichtet ist, ist dies sehr einfach. Wenn Sie Entity verwenden und diese Navigationseigenschaft nicht haben, worauf warten Sie noch?

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

Wenn Sie zuerst Code schreiben, müssen Sie die Eigenschaft so einrichten:

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

Ich habe so etwas gemacht;

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);
3
Mahib

Es könnte so etwas sein

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};
2
pepitomb

Diese linq-Abfrage sollte für Sie funktionieren. Es werden alle Posts mit Post-Meta abgerufen. 

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 });

Gleichwertige SQL-Abfrage 

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

1 entspricht 1 zwei verschiedenen Tabellenverbindungen

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 };
0
mtngunay