C# 实体框架核心将不更新ICollection

C# 实体框架核心将不更新ICollection,c#,.net-core,entity-framework-core,C#,.net Core,Entity Framework Core,正在尝试对具有嵌套列表的实体执行更新。不管我做什么,我总是会犯这个错误。我试过这个:还有这个: 数据库操作预期影响1行,但实际影响0行。自加载实体后,数据可能已被修改或删除。有关了解和处理乐观并发异常的信息,请参阅 TypeName:Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException 插入新行效果很好。但不是更新 public class BuyGroup { [Key] public Guid Id { get;

正在尝试对具有嵌套列表的实体执行更新。不管我做什么,我总是会犯这个错误。我试过这个:还有这个:

数据库操作预期影响1行,但实际影响0行。自加载实体后,数据可能已被修改或删除。有关了解和处理乐观并发异常的信息,请参阅

TypeName:Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException

插入新行效果很好。但不是更新

public class BuyGroup
{
    [Key]
    public Guid Id { get; set; }

    [Required]
    [Column(TypeName = "nvarchar(150)")]
    public string Name { get; set; }

    public virtual ICollection<Item> Items { get; set; } = new List<Item>();
}

public class Item
{
    [Key]
    public Guid Id { get; set; }

    [Required]
    [Column(TypeName = "nvarchar(100)")]
    public string Name { get; set; }

    public BuyGroup BuyGroup { get; set; }
}
编辑2:

使用相同的上下文仍然不能解决我的问题:

using (var dc = _dataContext())
{
    var existing = await dc.BuyGroups.FirstOrDefaultAsync(x => x.Id == id); // same context
    if (existing != null)
    {

        existing.Items.Add(new Item{ .....}):
        dc.ByGroups.Entry(existing).State = EntityState.Modified;


    } else {
        await dc.BuyGroups.AddAsync(model);
    }
    await dc.SaveChangesAsync();
}

是否要将模型中的所有项仅分配给另一个表中的一个实体?这是一个设计错误

此外,我不确定您是否可以在一个实体中替换整个集合。您必须清除它们并添加新项目。您正在将数据库集分配给现有数据库。这绝对是不可能的

编辑
另一件事:您为“现有”创建一个新上下文,并从其他源附加一些内容。也许您的项目来自另一个上下文。它们需要附加到此dc上下文。

是否要将模型中的所有项目仅分配给另一个表中的一个实体?这是一个设计错误

此外,我不确定您是否可以在一个实体中替换整个集合。您必须清除它们并添加新项目。您正在将数据库集分配给现有数据库。这绝对是不可能的

编辑
另一件事:您为“现有”创建一个新上下文,并从其他源附加一些内容。也许您的项目来自另一个上下文。它们需要连接到此dc上下文。

这是一个长期的尝试,如果您的电脑发生爆炸,我不承担任何责任,请尝试以下方法:

public async Task<Guid> Save(Entities.BuyGroup model)
{
    using (var dc = _dataContext())
    {
        var existing = await Get(model.Id); 
        if (existing != null)
        {
            dc.ByGroups.Entry(model).State = EntityState.Modified;

        } else {
            await dc.BuyGroups.AddAsync(model);
        }
        await dc.SaveChangesAsync();
    }
}

这是一个长期的尝试,如果您的电脑发生爆炸,我不承担责任,请尝试以下方法:

public async Task<Guid> Save(Entities.BuyGroup model)
{
    using (var dc = _dataContext())
    {
        var existing = await Get(model.Id); 
        if (existing != null)
        {
            dc.ByGroups.Entry(model).State = EntityState.Modified;

        } else {
            await dc.BuyGroups.AddAsync(model);
        }
        await dc.SaveChangesAsync();
    }
}

我的印象是,由于您正在调用函数dataContext,而不是调用just dataContext的受保护实例,因此您可能正在get和save方法中创建一个新的上下文

因为,get和save方法使用单独的dbcontext,所以当您存在.Items=model.Items时;您正在使用附加到单独上下文的项

protected BuyGroup GetImplementation(MyDbContext context, int id)
{
    return await context.BuyGroups.FirstOrDefaultAsync(x => x.Id == id);
}
有很多方法可以解决这个问题,但就个人而言,我只需要创建接受dbContext的受保护方法,这样您就不必担心将实体附加到上下文

protected BuyGroup GetImplementation(MyDbContext context, int id)
{
    return await context.BuyGroups.FirstOrDefaultAsync(x => x.Id == id);
}
然后在save方法中,您只需调用:

var existing = await this.GetImplementation(dc, model.Id);
为编辑而编辑

您正在将新项目设置为“已修改”,而不是“已添加”

existing.Items.Add(new Item{ .....}):
//You shouldn't do this for added items
//dc.ByGroups.Entry(existing).State = EntityState.Modified;

我的印象是,由于您正在调用函数dataContext,而不是调用just dataContext的受保护实例,因此您可能正在get和save方法中创建一个新的上下文

因为,get和save方法使用单独的dbcontext,所以当您存在.Items=model.Items时;您正在使用附加到单独上下文的项

protected BuyGroup GetImplementation(MyDbContext context, int id)
{
    return await context.BuyGroups.FirstOrDefaultAsync(x => x.Id == id);
}
有很多方法可以解决这个问题,但就个人而言,我只需要创建接受dbContext的受保护方法,这样您就不必担心将实体附加到上下文

protected BuyGroup GetImplementation(MyDbContext context, int id)
{
    return await context.BuyGroups.FirstOrDefaultAsync(x => x.Id == id);
}
然后在save方法中,您只需调用:

var existing = await this.GetImplementation(dc, model.Id);
为编辑而编辑

您正在将新项目设置为“已修改”,而不是“已添加”

existing.Items.Add(new Item{ .....}):
//You shouldn't do this for added items
//dc.ByGroups.Entry(existing).State = EntityState.Modified;

如果您将项目设置为非虚拟项目,是否有效?否:。不起作用为什么需要1 dc.BuyGroups.Updateexisting.State=EntityState.Modified;2等待dc.SaveChangesAsync;替换dc.BuyGroups.Updateexisting.State=EntityState.Modified;存在dc.BuyGroups.updatee;我试过了。如果您将项目设置为非虚拟项目,是否有效?否:。不起作用为什么需要1 dc.BuyGroups.Updateexisting.State=EntityState.Modified;2等待dc.SaveChangesAsync;替换dc.BuyGroups.Updateexisting.State=EntityState.Modified;存在dc.BuyGroups.updatee;我试过了。没用你说不可能是什么意思?您将如何对嵌套集合执行更新?您要做的是,将整个集合扔掉,将其实际放入垃圾箱,并覆盖现有的.Items。您可以调用Add/Remove来插入或删除某些内容。集合中已经存在的元素不需要更新,它们总是最新的,因为没有两个实例。您确定您的嵌套集合不是最新的吗?因为如果一切都配置好了,这是自动完成的。您在model.Items中插入了一些内容,该项目将出现在所有相关的实体中。什么是不可能?您将如何对嵌套集合执行更新?您要做的是,将整个集合扔掉,将其实际放入垃圾箱,并覆盖现有的.Items。您可以调用Add/Remove来插入或删除某些内容。集合中已经存在的元素不需要更新,它们总是最新的,因为没有两个实例。您确定您的嵌套集合不是最新的吗?因为如果一切都配置好了,这是自动完成的。你把东西插进去
model.Items,该项将出现在所有相关实体中。不起作用。我尝试向Items集合添加一个新项,如下所示:existing.Items.Addnew Item{Id=Guid.NewGuid,Name=Test};然后Entrymodel.State=Modified。但我还是有个例外。如果我删除Addnew item,它只会更新BuyGroup类的简单道具,而不会更新Items collectionWell,太糟糕了,它不起作用,你可以试试ASP.NET核心Web API的it has方法,特别是PUT方法可能会有帮助,因为它与你想做的有一些相似之处。不起作用。我尝试向Items集合添加一个新项,如下所示:existing.Items.Addnew Item{Id=Guid.NewGuid,Name=Test};然后Entrymodel.State=Modified。但我还是有个例外。如果我删除Addnew item,只更新BuyGroup类的简单道具,而不更新Items collectionWell,太糟糕了,它不起作用,你可以尝试ASP.NET核心Web API的it has方法,特别是PUT方法可能会有帮助,因为它与你想做的有一些相似之处。但我使用相同的上下文来获取。请参阅Edit2。@ShaneKm您正在将添加的状态重写为修改后的状态,直到注释掉修改后的行状态后得到相同的异常。还尝试了State=已添加,但抛出不同的exception@ShaneKm听起来好像您多次附加到上下文。应用于上下文时,每个实体*必须具有正确的状态。请发布您的完整代码,不要遗漏细节。参见本文,但我对get使用相同的上下文。请参阅Edit2。@ShaneKm您正在将添加的状态重写为修改后的状态,直到注释掉修改后的行状态后得到相同的异常。还尝试了State=已添加,但抛出不同的exception@ShaneKm听起来好像您多次附加到上下文。应用于上下文时,每个实体*必须具有正确的状态。请发布您的完整代码,不要遗漏细节。参见此