2016-04-06 11 views
1

Ich habe zwei TabellenLinq-Abfrage für zwei Tabellen mit SUM und Gruppieren nach

Antworten

|ReplyID  |ReplyText | QuestionID | CreatedOn | 
|1   |xxxxxx |1   | 01/01/2016 | 
|2   |yyyyyy |2   | 02/01/2016 | 
|3   |zzzzzz |3   | 03/01/2015 | 

und Stimmen

|ReplyID  |VoteValue |UserId | 
|1   |1   |1  | 
|1   |1   |2  | 
|2   |-1  |3  | 
|3   |1   |4  | 

Ich versuche, ID-Wert, um zwei Tabellen auf ReplyIds gegen was ich als Controller-Parameter bekomme.

Dies ist die Linq-Abfrage, die ich mit m:

Replies = from r in db.Replies 
      join v in db.Votes on r.ReplyID equals v.ReplyId 
      where r.QuestionId == id 
      orderby r.CreatedOn descending 
      group v by v.ReplyId into g 
      select g.Key 

wo Antworten ist

public IGrouping<Reply, Vote> Replies { get; set; } 

ich diesen Fehler m:

Cannot implicitly convert type 'System.Linq.IQueryable' to System.Linq.IGrouping'

Ich bin nicht in der Lage von hier gehen . Ich brauche Sum (VoteValues) in der Tabelle "Votes" und verbinde sie mit der Tabelle "Antworten", um alle Spaltenwerte zu erhalten. Jede Hilfe wäre willkommen.

+0

Sie müssen die Abfrage tatsächlich ausführen. Ansonsten erhalten Sie keine eigentlichen Ergebnisse (IGrouping), sondern die Definition für die auszuführende Abfrage * (IQueryable). Versuchen Sie, ToList für Ihre Abfrage aufzurufen, bevor Sie sie in Ihrer Eigenschaft "Antworten" speichern. – TheRotag

+1

Definitiv ist das Abfrageergebnis nicht 'IGrouping '. –

+0

'g' ist ein Sammlungsobjekt, aber Sie wählen g.key, das ein Singleton ist. Ändern Sie g.key in nur g. – jdweng

Antwort

2

können Sie ein group join statt:

var result= from r in db.Replies 
      join v in db.Votes on r.ReplyID equals v.ReplyId into votes 
      where r.QuestionId == id 
      orderby r.CreatedOn descending 
      select new {Reply=r, Votes=votes.Sum(v=>v.VoteValue)}; 

Nach was Sie beschreiben Sie alle Spalten aus Reply und die Summe aller Stimmen bekommen müssen. Auf diese Weise können Sie Ihre Abfrage mit einem anonymen Projekt abbilden, um die Instanz Reply und die benötigte Summe zu speichern. Jetzt müssen Sie die Projektion möglicherweise in einem bekannten Typ speichern, da Sie das Ergebnis dieser Abfrage an einen Controller übergeben müssen. In diesem Fall schlage ich eine benutzerdefinierte Klasse erstellen (auch als DTO bekannt):

public class ReplySum 
{ 
    public Reply Reply {get;set;} 
    public int Votes{get;set;} 
} 

Und jetzt können Sie Ihre Abfrage auf diese Weise projizieren:

IQueryable<ReplySum> query =from r in db.Replies 
          join v in db.Votes on r.ReplyID equals v.ReplyId into votes 
          where r.QuestionId == id 
          orderby r.CreatedOn descending 
          select new ReplySum{Reply=r, Votes=votes.Sum(v=>v.VoteValue)}; 

Eine andere Sache, die Sie beachten müssen, ist materialisieren Ihre Anfrage bevor das Ergebnis zu Ihrer Sicht passieren:

var result=query.ToList();//Or ToArray 
+0

Natürlich - unser Favorit beitreten :) +1 –

+0

lol, ja, das ist richtig;) – octavioccl

+0

Danke für die Erklärung. Eine perfekte Antwort! – ashhad

1

Ihre Anfrage kann mit Lambda-Ausdruck einfacher sein:

var result = db.Replies.Select(i => new 
        { 
         VoteCount = i.Votes.Sum(j => j.VoteValue), 
         Reply = i 
        }) 
        .ToList(); 
Verwandte Themen