繁体   English   中英

使用实体框架时如何自动将所有 Enumerable 转换为 List?

[英]How to automatically convert all Enumerable to List when using Entity Framework?

我的 ASP.NET Core Web API(使用实体框架)中有这个 POST 端点:

[HttpPost]
public async Task<ActionResult<Game>> PostGame(Game game) {

  ...

  game.State = new GameState();
  game.State.Map.Rows = game.State.Map.Rows.ToList();

  ...
}

然后我有这两个类:

public class MapRow {

  public int Id { get; set; }
  public IEnumerable<MapColumn> Columns { get; set; }

  public MapRow() { }

  public MapRow(IEnumerable<MapColumn> columns) {
    Columns = columns;
  }
}

public class Map {

  public long Id { get; set; }
  public IEnumerable<MapRow> Rows { get; set; }

  public Map() { }

  public Map(IEnumerable<MapRow> rows) {
    Rows = rows;
  }
}

其中有两个需要转换为List或 Entity Framework 的Enumerable将抛出类似于以下的错误:

System.InvalidOperationException:实体类型“MapRow”上的导航属性“Columns”的类型是“SelectRangeIterator”,它没有实现 ICollection。 集合导航属性必须实现目标类型的 ICollection<>。

我通过在端点本身中调用.ToList()为我的Rows解决了这个错误。 然而,由于存在多个端点,你可以有Enumerable被相当嵌套它迅速成为不可维护不必每次将S Enumerable到一个List手动。

有没有更简单的方法可以让我自动化?

对于 EF 实体,集合的导航属性应声明为ICollection<T>而不是IEnumerable<T> 所以例如:

public class MapRow {

  public int Id { get; set; }
  public virtual ICollection<MapColumn> Columns { get; set; } = new List<MapColumn>();

  public MapRow() { }

  public MapRow(IEnumerable<MapColumn> columns) {
    Columns = columns;
  }
}

public class Map {

  public long Id { get; set; }
  public virtual IColleciton<MapRow> Rows { get; set; } = new List<MapRow>();

  public Map() { }

  public Map(IEnumerable<MapRow> rows) {
    Rows = rows;
  }
}

ICollection<T>扩展了IEnumerable<T>因此任何需要 IEnumerable 的方法都将完全满足 ICollection。 当您尝试将 IEnumerable 传递给期望 IList 或 ICollection 的内容时,情况就不同了。

将它们声明为virtual还允许 EF 将代理分配给这些属性,以在需要时协助延迟加载并且 DbContext 仍然可用。 它还有助于将属性自动初始化为新集合,以便在新建 Map 时,您可以立即开始添加行和列,而不会冒NullReferenceException的风险。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM