【问题标题】:Entity Framework count child entities实体框架计数子实体
【发布时间】:2016-11-29 20:35:25
【问题描述】:

我有一个如下所示的实体框架查询:

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

这个查询本质上给了我一个字符与他们各自投票的匹配。如果您查看votes 属性,您会发现它只是根据CharacterID 过滤掉选票。这符合我的预期。

但是,我想更进一步,实际计算每个角色的票数。因此,如果我将查询更改为以下内容:

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

votes的查询末尾添加.Count(),我得到一个错误:

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

此错误消息的关注点在这里:

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

如果前面的查询在没有 .Count() 的情况下工作,我不确定为什么会收到此错误。此外,我的查询中根本没有使用v.Matchup.MatchupID。我只能想象这是底层 SQL 正在做的事情。

这是我的VideoPlayer、'Matchup, andMatchupVote` 的模型:

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

所以,我的问题是,如何使用 .Count() 这样的方法来计算查询中每个字符的投票数?

我在这个项目中使用 .NET Core 和 Entity Framework Core。

【问题讨论】:

  • 你的表结构?视频课和播放器课!用它更新帖子
  • @Aravind 我更新了。
  • 这里指的是游戏类和用户类中的外键。检查您是否在这两个类中配置了反向导航属性。如果可能,更新它们
  • @Aravind 你问我是否在另一个模型上设置了GameUser 导航属性?
  • 没有。如果你对一个字段使用外键属性,那么对应的表应该有一个属性,它可以使用它返回到这个 v 表。

标签: c# asp.net .net entity-framework asp.net-web-api


【解决方案1】:

这是来自 cmets 的答案,以防有人偶然发现。

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

就性能而言,我认为这不会产生影响,因为底层 SQL 正在执行过滤的不同计数。如果您非常关心性能,我会检查分析器,但由于它是一个过滤计数,我认为与您尝试的相比不会对性能造成影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-18
    相关资源
    最近更新 更多