我有一个看起来像这样的课:
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; }
}
答案 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。发送实体的问题在于,在以后的开发中,某些开发人员“信任”该实体并将其添加为未经验证的实体,或者将其附加到要持久保存的上下文中,太容易了。