Wie man assoziierte Entitäten zählt, ohne sie in Entity Framework zu holen
Ich hab mich schon gewundert, über diese für eine Weile jetzt, so dachte ich, es wäre Wert, mit meinem ersten Stack-Überlauf post Fragen stellen.
Vorstellen, ich habe eine Diskussion mit einer zugehörigen Liste der Nachrichten:
DiscussionCategory discussionCategory = _repository.GetDiscussionCategory(id);
discussionCategory.Diskussionen ist eine Liste der Diskussion Personen, die aktuell nicht geladen ist.
Was ich will, ist in der Lage sein zu Durchlaufen und die Diskussionen in einem discussionCategory und sagen, wie viele Nachrichten sich in jede Diskussion, ohne das abrufen der message-Daten.
Wenn ich versucht habe, bevor ich gehabt haben, zu laden, die Diskussionen und die Nachrichten, so dass ich tun könnte etwas wie diese:
discussionCategory.Discussions.Attach(Model.Discussions.CreateSourceQuery().Include("Messages").AsEnumerable());
foreach(Discussion discussion in discussionCategory.Discussions)
{
int messageCount = discussion.Messages.Count;
Console.WriteLine(messageCount);
}
Ist das ziemlich ineffizient, um mich, wie ich bin, Holen potenziell Hunderte von Nachrichtentexten aus der Datenbank und halten Sie im Speicher, wenn alle, die ich tun möchte, ist zählen Ihre Anzahl für Präsentations-Zwecke.
Habe ich einige Fragen, die Berührungspunkte zu diesem Thema, aber Sie schien es nicht zu unmittelbar.
Vielen Dank im Voraus für alle Gedanken, die Sie möglicherweise auf dieses Thema.
Update - Etwas mehr code, wie verlangt:
public ActionResult Details(int id)
{
Project project = _repository.GetProject(id);
return View(project);
}
Dann in der view (nur um es zu testen):
Model.Discussions.Load();
var items = from d in Model.Discussions select new { Id = d.Id, Name = d.Name, MessageCount = d.Messages.Count() };
foreach (var item in items) {
//etc
Ich hoffe das macht mein problem etwas klarer. Lassen Sie mich wissen, wenn Sie mehr brauchen, code-details.
InformationsquelleAutor der Frage Oligarchia | 2010-01-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einfach; nur Projekt auf a POCO (oder anonyme) Typ:
Wenn man sich die generierten SQL, wirst du sehen, dass die
Count()
erfolgt durch die DB-server.Beachten Sie, dass dies funktioniert in beide EF 1 und EF 4.
InformationsquelleAutor der Antwort Craig Stuntz
Wenn Sie mithilfe von Entity Framework 4.1 oder höher verwenden, können Sie:
Quelle: http://msdn.microsoft.com/en-US/data/jj574232
InformationsquelleAutor der Antwort Ricardo
Ich weiß, das ist eine alte Frage, aber es scheint ein ständiges problem und keine der oben genannten Antworten bieten eine gute Möglichkeit, den Umgang mit SQL-Aggregate in den Listen-Ansichten.
Ich gehe davon aus, dass gerade POCO-Modellen und den Ersten Code wie in den Vorlagen und Beispiele. Während der SQL-View-Lösung ist schön, aus Sicht des DBAs, es re-präsentiert die Herausforderung code-und Datenbank-Strukturen parallel. Für einfache SQL-Aggregat-Abfragen, sehen Sie nicht viel Geschwindigkeit gewinnen aus einer Sicht. Was Sie wirklich brauchen, um zu vermeiden, mehrere (n+1) Datenbank-Abfragen, wie in den obigen Beispielen. Wenn Sie 5000 Muttergesellschaften und Sie zählen untergeordneten Entitäten (z.B. Nachrichten pro Diskussion), das ist 5001 SQL-Abfragen.
Können Sie die Rückgabe auch alle jene zählt, die in einer einzigen SQL-Abfrage. Hier ist, wie.
Hinzufügen eines Platzhalter-Eigenschaft, um Ihre Klasse-Modell mit der
[NotMapped]
Daten die annotation aus derSystem.ComponentModel.DataAnnotations.Schema
namespace. Dies gibt Ihnen einen Ort zum speichern der berechneten Daten, ohne tatsächlich eine Spalte hinzufügen Ihrer Datenbank oder zu projizieren, um unnötige Modelle Anzeigen.In Ihrem Controller, Holen Sie sich die Liste der übergeordneten Objekte.
Erfassung der Zählungen in einem Wörterbuch. Dies erzeugt eine einzelne SQL-GROUP BY-Abfrage mit allen parent-IDs und Kind-Objekt ermittelt. (Vorausgesetzt
DiscussionID
ist der FK inMessages
.)Schleife durch die übergeordneten Objekte, sehen Sie die Anzahl aus dem Wörterbuch, und speichern Sie in der Platzhalter-Eigenschaft.
Wieder Ihre Diskussionsliste.
Verweis auf die
MessageCount
- Eigenschaft in der Ansicht.Ja, Sie konnte nur Zeug, das Wörterbuch in der ViewBag und tun die lookup-direkt in die Ansicht, aber das trübt deine Sicht mit code, die nicht brauchen, dort zu sein.
In das Ende, ich wünschte, EF hatte eine Art, das zu tun", faul zu zählen". Das problem mit den beiden faul und das explizite laden Sie laden der Objekte. Und wenn Sie laden müssen, um zu zählen, das ist ein problem. Faul zu zählen würde nicht lösen das n+1 problem in den Listen-Ansichten, aber es wäre sicher schön, in der Lage sein zu rufen
@item.Messages.Count
aus dem Blick, ohne sich sorgen über potenziell laden Tonnen von unerwünschten Objekt-Daten.Hoffe, das hilft.
InformationsquelleAutor der Antwort Neil Laslett
Ich habe keine direkte Antwort, sondern kann nur darauf Sie auf den folgenden Vergleich zwischen NHibernate und dem EF 4.0, die zu suggerieren scheint, dass es auch in EF 4.0 es gibt keine out of the box Unterstützung für das erste zählt, der eine verknüpfte Entität Sammlung ohne abrufen der Sammlung.
http://ayende.com/Blog/archive/2010/01/05/nhibernate-vs.-entity-framework-4.0.aspx
Habe ich von Ihnen positiv bewertet werden und spielte Ihre Frage. Hoffentlich wird jemand Glockenspiel mit eine brauchbare Lösung.
InformationsquelleAutor der Antwort Brian Hasden
Habe ich über das gleiche Problem beim Umgang mit mehreren Mappern einschließlich der EF und DevExpress XPO (die nicht einmal erlauben, eine Einheit zum zuordnen mehrerer Tabellen). Was, wie ich finde, die beste Lösung ist im Grunde verwenden Sie die EDMX-und T4-Vorlagen für die Generierung von aktualisierbaren sichten in SQL-Server (mit instead of-Trigger), so dass Sie low-level-Kontrolle über die sql-damit Sie tun können, unteranfrage in der select-Klausel verwenden Sie alle Arten von komplexen Verknüpfungen, um Daten und so weiter.
InformationsquelleAutor der Antwort Sheldmandu
Wenn dies nicht eine einmalige und finden Sie selbst benötigen zu zählen, eine Reihe von verschiedenen zugeordneten Entitäten, einen Datenbank-view kann eine einfachere (und möglicherweise besser geeigneten) Wahl:
Erstellen Sie Ihre Datenbank-view.
Angenommen, Sie möchten alle von der original-Entität-Eigenschaften sowie der dazugehörigen message count:
(Wenn Sie Entity Framework Code First-Migrationen finden Sie unter diese SO beantworten auf, wie zum erstellen einer Ansicht.)
In EF, verwenden Sie einfach stattdessen die Ansicht von der ursprünglichen Einheit:
InformationsquelleAutor der Antwort Dunc