[英]How to automatically convert all Enumerable to List when using Entity Framework?
I have this POST endpoint in my ASP.NET Core Web API (with 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();
...
}
Then I have these two classes:然后我有这两个类:
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;
}
}
Which has two Enumerable
s that need to be converted to a List
or Entity Framework will throw an error similar to this:其中有两个需要转换为List
或 Entity Framework 的Enumerable
将抛出类似于以下的错误:
System.InvalidOperationException: The type of navigation property 'Columns' on the entity type 'MapRow' is 'SelectRangeIterator' which does not implement ICollection. System.InvalidOperationException:实体类型“MapRow”上的导航属性“Columns”的类型是“SelectRangeIterator”,它没有实现 ICollection。 Collection navigation properties must implement ICollection<> of the target type.集合导航属性必须实现目标类型的 ICollection<>。
I solved this error for my Rows
by calling .ToList()
in the endpoint itself.我通过在端点本身中调用.ToList()
为我的Rows
解决了这个错误。 However since there are multiple endpoints and you can have Enumerable
s that are quite nested it's quickly becoming unmaintainable having to convert every Enumerable
to a List
manually.然而,由于存在多个端点,你可以有Enumerable
被相当嵌套它迅速成为不可维护不必每次将S Enumerable
到一个List
手动。
Is there an easier way that would allow me to automate this?有没有更简单的方法可以让我自动化?
For EF entities, navigation properties for collections should be declared as ICollection<T>
rather than IEnumerable<T>
.对于 EF 实体,集合的导航属性应声明为ICollection<T>
而不是IEnumerable<T>
。 So for instance:所以例如:
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>
extends IEnumerable<T>
so any method expecting IEnumerable will be perfectly content with ICollection. ICollection<T>
扩展了IEnumerable<T>
因此任何需要 IEnumerable 的方法都将完全满足 ICollection。 It's a different story when you try passing an IEnumerable to something expecting IList or ICollection.当您尝试将 IEnumerable 传递给期望 IList 或 ICollection 的内容时,情况就不同了。
Declaring them as virtual
also allows for EF to assign proxies to these properties to assist with lazy loading if they are needed and the DbContext is still available.将它们声明为virtual
还允许 EF 将代理分配给这些属性,以在需要时协助延迟加载并且 DbContext 仍然可用。 It also helps to auto-initialize the properties to a new collection so that when new-ing up a Map, you can immediately start adding Rows and Columns without risking NullReferenceException
s.它还有助于将属性自动初始化为新集合,以便在新建 Map 时,您可以立即开始添加行和列,而不会冒NullReferenceException
的风险。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.