Entity Framework Lookup table update / create
本问题已经有最佳答案,请猛点这里访问。
我有这个创建方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | [HttpPost] [Route("")] /// <summary> /// Create a team /// </summary> /// <param name="model">The team model</param> /// <returns>The modified team model</returns> public async Task<IHttpActionResult> Create(TeamBindingViewModel model) { // If our model is invalid, return the errors if (!ModelState.IsValid) return BadRequest(ModelState); // Get all our colours var colours = await this.colourService.GetAllAsync(); // Create our new model var team = new Team() { Name = model.Name, Sport = model.Sport }; // For each colour, Add to our team team.Colours = colours.Where(m => model.Colours.Any(c => c.Id == m.Id)).ToList(); // Create our team this.service.Create(team); // Save our changes await this.unitOfWork.SaveChangesAsync(); // Assign our Id to our model model.Id = team.Id; // Return Ok return Ok(model); } |
如您所见,创建团队时,我需要将颜色添加到查找表中。为此,我从数据库中获取颜色,然后根据作为模型一部分传递的颜色对它们进行过滤。
这告诉实体框架,这些颜色不是新的实体,因此它只是在查阅表格中创建一个引用,而不是创建新的颜色。
现在我想对更新方法做同样的事情。
我试过这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | [HttpPut] [Route("")] /// <summary> /// Update a team /// </summary> /// <param name="model">The team model</param> /// <returns>The modified team model</returns> public async Task<IHttpActionResult> Update(TeamBindingViewModel model) { // If our model is invalid, return the errors if (!ModelState.IsValid) return BadRequest(ModelState); // Get our current team var team = await this.service.GetAsync(model.Id,"Colours"); // Get all our colours var colours = await this.colourService.GetAllAsync(); // Make changes to our team team.Name = model.Name; team.Sport = model.Sport; // For each colour in our team colours but not in our model colours, remove foreach (var colour in team.Colours) if (!model.Colours.Any(c => c.Id == colour.Id)) team.Colours.Remove(colour); // For each colour that has to be added, add to our team colours if (model.Colours != null) foreach (var colour in model.Colours) if (!team.Colours.Any(c => c.Id == colour.Id)) team.Colours.Add(colours.Where(m => m.Id == colour.Id).SingleOrDefault()); // Update the team this.service.Update(team); // Save our changes await this.unitOfWork.SaveChangesAsync(); // Return Ok return Ok(model); } |
但它不起作用。我有一个错误说明:
Collection was modified; enumeration operation may not execute.
< /块引用>
我知道这是在谈论颜色,但我不知道如何绕过它。
也许有人也遇到过类似的问题并设法解决了?
不能同时迭代集合并更改它。如果你真的想这样做,你必须把所有的值存储到一个不会被修改的地方。最简单的方法是在迭代通过之前对集合使用
ToArray() 或ToList() 。
1
2
3
4
5
6
7
8
9
10
11
12 ...
// For each colour in our team colours but not in our model colours, remove
foreach (var colour in team.Colours.ToList()) // <<== note change here
if (!model.Colours.Any(c => c.Id == colour.Id))
team.Colours.Remove(colour);
// For each colour that has to be added, add to our team colours
if (model.Colours != null)
foreach (var colour in model.Colours.ToList()) // <<== note change here
if (!team.Colours.Any(c => c.Id == colour.Id))
team.Colours.Add(colours.Where(m => m.Id == colour.Id).SingleOrDefault());
...这里的问题是,您正在更改要迭代的集合。
如果要从集合中删除(或添加)项,必须分两步执行:
选择要删除的对象 移除对象 如果您的集合是列表,则可以使用
List.RemoveAll 方法好吧,在这里的2条评论和搜索之后,我想到了这个:
1
2
3
4 // Loop through our colours and remove the ones that are not in our new colour list
for (var i = 0; i < team.Colours.Count; i++)
if (!model.Colours.Any(c => c.Id == team.Colours[i].Id))
team.Colours.RemoveAt(i);很好用。