2016-11-29 3 views
2

Ich habe eine Abfrage Entity Framework, das wie folgt aussieht:Entity Framework Zählung Kind Entitäten

public object GetMatchupByVideoId(int id) 
{ 
    var videoMatchup = _DBContext.Videos 
     .Where(v => v.VideoID == id) 
     .Select(v => new { 
      id = v.MatchupID, 
      players = v.Matchup.Players.Select(mp => new 
      { 
       character = new { 
        name = mp.Character.Name, 
        votes = v.Matchup.MatchupVotes 
         .Where(mv => mv.CharacterID == mp.CharacterID) 
       }, 
       outcome = mp.Outcome 
      }) 
     }); 

    return videoMatchup; 
} 

Diese Abfrage im Wesentlichen gibt mir ein matchup von Zeichen mit ihren jeweiligen Stimmen. Wenn Sie sich die votes Eigenschaft ansehen, werden Sie sehen, dass sie nur die Stimmen basierend auf der CharacterID herausfiltert. Das funktioniert so, wie ich es mir vorstelle.

Ich möchte jedoch einen Schritt weiter gehen und tatsächlich die Anzahl der Stimmen für jedes Zeichen erhalten. Also, wenn ich meine Abfrage so etwas wie dies zu ändern:

public object GetMatchupByVideoId(int id) 
{ 
    var videoMatchup = _DBContext.Videos 
     .Where(v => v.VideoID == id) 
     .Select(v => new { 
      id = v.MatchupID, 
      players = v.Matchup.Players.Select(mp => new 
      { 
       character = new { 
        name = mp.Character.Name, 
        votes = v.Matchup.MatchupVotes 
         .Where(mv => mv.CharacterID == mp.CharacterID) 
         .Count() 
       }, 
       outcome = mp.Outcome 
      }) 
     }); 

    return videoMatchup; 
} 

ein .Count() am Ende der Abfrage in votes Hinzufügen, erhalte ich eine Fehlermeldung:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] 
     Request starting HTTP/1.1 GET http://localhost:5000/api/videos/1/matchup application/json 
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1] 
     Executing action method Mindgame.Controllers.VideosController.GetMatchupByVideoId (mindgame-api) with arguments (1) - ModelState is Valid 
info: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1] 
     Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext. 
fail: Microsoft.AspNetCore.Server.Kestrel[13] 
     Connection id "0HL0OILHK80GT": An unhandled exception was thrown by the application. 
Microsoft.Data.Sqlite.SqliteException: SQLite Error 1: 'no such column: v.Matchup.MatchupID'. 
    at Microsoft.Data.Sqlite.Interop.MarshalEx.ThrowExceptionForRC(Int32 rc, Sqlite3Handle db) 
    at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior) 
    at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, String executeMethod, IReadOnlyDictionary`2 parameterValues, Boolean closeConnection) 
    at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues) 
    at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable.Enumerator.BufferlessMoveNext(Boolean buffer) 
    at Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.<_ShapedQuery>d__3`1.MoveNext() 
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) 
    at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) 
    at Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter.WriteObject(TextWriter writer, Object value) 
    at Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter.<WriteResponseBodyAsync>d__9.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeResultAsync>d__32.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeResultFilterAsync>d__31.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeAllResultFiltersAsync>d__29.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeResourceFilterAsync>d__23.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeAsync>d__18.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.<Invoke>d__3.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame`1.<RequestProcessingAsync>d__2.MoveNext() 
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] 
     Request finished in 787.4541ms 200 application/json; charset=utf-8 

Den Punkt von Interesse an diesem Fehler Nachricht ist hier:

SQLite Error 1: 'no such column: v.Matchup.MatchupID'. 

ich bin nicht sicher, warum ich diese Fehlermeldung erhalten, wenn die vorherige Abfrage ohne .Count() gearbeitet. Außerdem verwende ich in meiner Abfrage überhaupt nicht v.Matchup.MatchupID. Ich kann mir nur vorstellen, dass dies etwas ist, was der zugrunde liegende SQL macht.

Hier sind meine Modelle für Video, Player, ‚Matchup , and MatchupVote`:

public class Video 
{ 
    [JsonPropertyAttribute("id")] 
    public int VideoID { get; set; } 
    [ForeignKeyAttribute("Game")] 
    public int GameID { get; set; } 
    public Game Game { get; set; } 
    [ForeignKeyAttribute("Matchup")] 
    public int MatchupID { get; set; } 
    public Matchup Matchup { get; set; } 
    [ForeignKeyAttribute("User")] 
    public int UserID { get; set; } 
    public User User { get; set; } 
    public string YoutubeID { get; set; } 
    public string Description { get; set; } 
    public string Title { get; set; } 
} 

public class Player 
{ 
    [JsonPropertyAttribute("id")] 
    public int PlayerID { get; set; } 
    public int CharacterID { get; set; } 
    public Character Character { get; set; } 
    public Players.Outcomes Outcome { get; set; } 
} 

public class Matchup 
{ 
    [JsonPropertyAttribute("id")] 
    [Required] 
    public int MatchupID { get; set; } 
    public List<MatchupVote> MatchupVotes { get; set; } 
    public List<Player> Players { get; set; } 
} 

public class MatchupVote 
{ 
    [JsonPropertyAttribute("id")] 
    public int MatchupVoteID { get; set; } 
    [ForeignKeyAttribute("Character")] 
    public int CharacterID { get; set; } 
    [ForeignKeyAttribute("Matchup")] 
    public int MatchupID { get; set; } 
    public Matchup Matchup { get; set; } 
} 

Also, meine Frage ist, wie kann ich die .Count() Methode wie folgt verwenden, um eine Zählung der Stimmen zu bekommen Ich möchte für jedes Zeichen in meiner Abfrage?

Ich verwende .NET Core und Entity Framework Core für dieses Projekt.

+0

Ihre Tabellenstruktur? Video Klasse und Spieler Klasse! Aktualisieren Sie den Beitrag damit – Aravind

+0

@Aravind I aktualisiert. – Sethen

+0

Hier beziehen Sie sich auf einen Fremdschlüssel in Spielklasse und Benutzerklasse. Überprüfen Sie, ob Sie die umgekehrte Navigationseigenschaft in diesen beiden Klassen konfiguriert haben. Wenn möglich, aktualisieren Sie sie – Aravind

Antwort

3

Hier ist die Antwort aus den Kommentaren, falls jemand darüber stolpert.

_DBContext.MatchupVotes.Where(mv => mv.CharacterID == mp.CharacterID).Count() 

Soweit Leistung, ich glaube nicht, dass es einen Unterschied machen, wie die zugrunde liegende SQL einen Distinct Count tut, die gefiltert wird. Ich würde den Profiler überprüfen, wenn Sie sich sehr um die Leistung sorgen, aber da es sich um eine gefilterte Anzahl handelt, würde ich nicht glauben, dass es einen Leistungseinbruch geben würde, verglichen mit dem, was Sie versuchten.

Verwandte Themen