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