如何在实体框架中访问数据集中的列表?

时间:2019-06-02 09:15:41

标签: c# entity-framework

我有一个看起来像这样的课:

public class Player
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int TeamId { get; set; }

    public List<PlayerStatRecord> PlayerStats { get; set; }
}

但是每当我尝试通过以下方式使用实体框架访问玩家统计信息时:

public async Task<bool> AddPlayerRecord(PlayerStatRecord record)
{
    _context.Players.PlayerStats.Add(record);

    var result = await _context.SaveChangesAsync();

    return result == 1;
}
无法识别

PlayerStats属性。为什么会这样?

DbContext看起来像这样:

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions options) : base(options) { }

    public DbSet<PlayerStatRecord> PlayerStats { get; set; }
    public DbSet<Player> Players { get; set; }
}

1 个答案:

答案 0 :(得分:0)

好的,您应该考虑更改此代码的几个问题:

public async Task<bool> AddPlayerRecord(PlayerStatRecord record)
{
    _context.Players.PlayerStats.Add(record);
    var result = await _context.SaveChangesAsync();
    return result == 1;
}

首先:

_context.Players.PlayerStats.Add(record);

您正在接受PlayerStat实体,但随后尝试通过Players DbSet集合将其添加到PlayerStats。通常,您可以通过DbContext的PlayerStats DbSet添加一个PlayerStat,也可以将其添加到单个Player实体。

例如:

_context.PlayerStats.Add(record);

或:

var player = _context.Players
    .Include(x => x.PlayerStats)
    .Single(x => x.PlayerId = record.PlayerId);
player.PlayerStats.Add(record);

第二:您应该在您的控制器方法中接受来自客户端的实体,并且当然不要相信它们是准确,完整或以任何方式有效的。可以拦截Web请求并修改其有效负载。即使在加载页面时从记录中发送数据,也不要相信数据会返回。也不要混淆跟踪实体返回的数据。不是。这是共享实体结构的POCO数据,但不是跟踪的实体。

相反,您应该始终将POCO视图模型传递到Web客户端,或从Web客户端传递POCO视图模型,然后在可能应用更改之前,针对 real 数据验证传递的信息。例如:将通过的Record视为视图模型:

public async Task<bool> AddPlayerRecord(PlayerStatRecord record)
{
   // ToDo: Verify the current logged in session is active, and that the logged in 
   // user can modify the provided Player ID.

   // Look up the player by ID. Throws ex. if player not found.
   var player = _context.Players
       .Include(x => x.PlayerStats)
       .Single(x => x.PlayerId == record.PlayerId);
   // Look up any related information.
   var statistic = _context.Statistics.Single(x => x.StatisticId = record.StatisticId);
   // Validate any data that was provided to ensure it was complete.
   if(!record.IsComplete)
      Throw new ArgumentException("The provided player statistic was not valid.");

   // Populate a new player statistic entity, associate our references, and add it to 
   // the applicable player record.
   player.PlayeerStats.Add(new PlayerStatRecord 
   { 
      Statistic = statistic,
      // copy over other values and references...
   });
   var result = await _context.SaveChangesAsync();
   return result == 1;
}

但是,在确认数据完整并允许之后,该方法应接受PlayerStatViewModel或仅接受构造玩家状态记录所需的ID和值,而不是接受PlayerStatRecord。发送实体的问题在于,在以后的开发中,某些开发人员“信任”该实体并将其添加为未经验证的实体,或者将其附加到要持久保存的上下文中,太容易了。