C# 实体框架查找表更新/创建

C# 实体框架查找表更新/创建,c#,entity-framework,C#,Entity Framework,我有一个创建方法: [HttpPost] [Route("")] /// <summary> /// Create a team /// </summary> /// <param name="model">The team model</param> /// <returns>The modified team model</returns> public async Task<IHttpActionResult&g

我有一个创建方法:

[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);
}
[HttpPost]
[路线(“”)
/// 
///组建一个团队
/// 
///团队模式
///改进的团队模型
公共异步任务创建(TeamBindingViewModel模型)
{
//如果我们的模型无效,请返回错误
如果(!ModelState.IsValid)
返回请求(ModelState);
//得到我们所有的颜色
var colors=wait this.colorservice.GetAllAsync();
//创建我们的新模型
var团队=新团队()
{
Name=model.Name,
运动型
};
//对于每种颜色,添加到我们的团队中
team.colors=colors.Where(m=>model.colors.Any(c=>c.Id==m.Id)).ToList();
//创建我们的团队
这个。服务。创建(团队);
//保存我们的更改
等待此消息。unitOfWork.SaveChangesSync();
//将我们的Id分配给我们的模型
model.Id=team.Id;
//返回Ok
返回Ok(型号);
}
如您所见,创建团队时,我需要将颜色添加到查找表中。为此,我从数据库中获取颜色,然后根据作为模型一部分传递的颜色对它们进行过滤

这告诉实体框架这些颜色不是新的实体,因此它只是在查找表中创建一个引用,而不是创建新的颜色

现在我想对update方法执行同样的操作

我试过这个:

[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);
}
[HttpPut]
[路线(“”)
/// 
///更新团队
/// 
///团队模式
///改进的团队模型
公共异步任务更新(TeamBindingViewModel模型)
{
//如果我们的模型无效,请返回错误
如果(!ModelState.IsValid)
返回请求(ModelState);
//让我们现在的团队
var team=wait this.service.GetAsync(model.Id,“colors”);
//得到我们所有的颜色
var colors=wait this.colorservice.GetAllAsync();
//改变我们的团队
team.Name=model.Name;
team.Sport=model.Sport;
//对于我们团队颜色中的每种颜色,但不是我们的车型颜色,请删除
foreach(团队中的var颜色。颜色)
如果(!model.colors.Any(c=>c.Id==color.Id))
团队。颜色。移除(颜色);
//对于必须添加的每种颜色,请添加到我们的团队颜色中
如果(model.colors!=null)
foreach(型号中的var颜色。颜色)
如果(!team.colors.Any(c=>c.Id==color.Id))
添加(colors.Where(m=>m.Id==color.Id).SingleOrDefault());
//更新团队
本.服务.更新(团队);
//保存我们的更改
等待此消息。unitOfWork.SaveChangesSync();
//返回Ok
返回Ok(型号);
}
但它不起作用。我得到一个错误声明:

收集被修改;枚举操作不能执行

我知道它在谈论颜色,但我不知道如何避开它


也许有人遇到过类似的问题并设法解决了它?

这里的问题是您正在更改正在迭代的集合

如果要从集合中删除(或添加)项,必须分两步执行:

  • 选择要删除的对象
  • 移除对象

  • 如果您的集合是一个列表,则可以使用方法

    您不能在遍历集合的同时对其进行更改。如果您真的想这样做,您必须将所有值存储到某个不被修改的地方。最简单的方法是在迭代之前对集合使用
    ToArray()
    ToList()

    ...
    // 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());
    ...
    
    。。。
    //对于我们团队颜色中的每种颜色,但不是我们的车型颜色,请删除
    
    foreach(team.colors.ToList()中的var color)/好的,在对此处进行了2次评论并进行了一些搜索之后,我得出了以下结论:

    // 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);
    
    //循环浏览我们的颜色,删除不在新颜色列表中的颜色
    对于(var i=0;ic.Id==team.colors[i].Id))
    团队。颜色。移除(i);
    

    这非常有效。

    您能给我举个例子吗,我无法让它工作此代码是错误的,如果删除任何元素,将跳过集合中的某些项目。例如:您有
    var arr=[“a”、“b”、“c”]
    ,并且在第一次迭代(
    i=0
    )中删除位置0处的元素(元素
    “a”
    )。在此之后,所有数组元素将向上移动一个位置,并且数组将是
    [“b”,“c”]
    。因此,在下一次迭代(
    i=1
    )中,您将检查位置1处的元素,它将是
    “c”
    而不是
    “b”
    。这是错误的。要解决这个问题,你必须从底部向顶部移动。我可以看到你在说什么,但我已经测试过了。我选择了前三项,然后将其保存到数据库中。然后我编辑了记录,取消选择了第一个项目,选择了另一个项目,效果很好。因此,我再次编辑了它,取消了所有选择,选择了一组新的颜色,它仍然有效。尝试同时删除数组中一个接一个的两种颜色(比如说第一种和第二种),你就会明白我的意思。第二种颜色将被跳过,并且不会被删除。或-尝试以下操作1)添加所有颜色并更新;2) 删除所有颜色并更新;你会发现每2种颜色都不会被去除好的,你是对的。你能发布一个如何解决这个问题的代码示例,这样我就可以把你的标记为答案了吗?我已经做了。