C# 更新实体时,实体框架联接表中存在多对多重复值

C# 更新实体时,实体框架联接表中存在多对多重复值,c#,.net,entity-framework,C#,.net,Entity Framework,我有以下代码优先模型: public class Model1 : DbContext { public Model1() : base("name=Model1") { } public virtual DbSet<Master> Masters { get; set; } public virtual DbSet<Slave> Slaves { get; set; } protected overri

我有以下代码优先模型:

public class Model1 : DbContext
{
    public Model1()
        : base("name=Model1")
    {
    }

    public virtual DbSet<Master> Masters { get; set; }
    public virtual DbSet<Slave> Slaves { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Master>().Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        modelBuilder.Entity<Slave>().Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

        modelBuilder.Entity<Master>().Property(e => e.Name).IsRequired();
        modelBuilder.Entity<Slave>().Property(e => e.Name).IsRequired();
    }
}

public interface IEntity
{
    int Id { get; }
}

public class Master : IEntity
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Slave> Slaves { get; set; }

    public Master()
    {
        Slaves = new EntityHashSet<Slave>();
    }

    public Master(string name)
        : this()
    {
        Id = name.GetHashCode();
        Name = name;
    }

    public void Update(IEnumerable<Slave> slaves, Model1 model)
    {
        Slaves = new EntityHashSet<Slave>(slaves.Select(s => model.Slaves.CreateOrFind(s)));
    }

    public void Update(IEnumerable<string> slaves, Model1 model)
    {
        Update(slaves.Select(s => new Slave(s)), model);
    }
}

public class Slave : IEntity
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Master> Masters { get; set; }

    public Slave()
    {
        Masters = new EntityHashSet<Master>();
    }

    public Slave(string name)
        : this()
    {
        Id = name.GetHashCode();
        Name = name;
    }
}
当我尝试对现有方法使用update方法时,会抛出DbUpdateException:

using (var model = new Model1())
{
    var m = new Master("master1");
    m.Update(new[] {"slave1", "slave2", "slave3"}, model);
    model.Masters.Add(m);
    model.SaveChanges();
}
var m = model.Masters.CreateOrFind(new Master("master1"));

m.Update(new[] {"slave1", "slave2", "slave3", "slave4"}, model);

model.SaveChanges();
其他信息:保存未公开其关系的外键属性的实体时出错。EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参见InnerException

相关内部例外情况:

违反主键约束“PK_dbo.slavemasts”。无法在对象“dbo.SlaveMasters”中插入重复密钥。重复的键值是(1928309069,-2136434452)。 声明已终止

为什么会这样?我正在检查数据库中是否已经存在实体,或者是否需要通过CreateOrFind创建实体

编辑:为了澄清,产生错误的行是:

Slaves = new EntityHashSet<Slave>(slaves.Select(s => model.Slaves.CreateOrFind(s)));
Slaves=newentityhashset(Slaves.Select(s=>model.Slaves.CreateOrFind(s));

调用SaveChanges()时引发错误。

您必须使用以前的ef配置文件,因此它将始终尝试插入相同的值,但会更新。
您可以在更新之前更新或检查ef配置文件。

我认为您必须使用以前的ef配置文件,因此它将始终尝试插入相同的值,但会进行更新。
您可以在更新之前更新或检查ef配置文件。

发现了一种解决此问题的肮脏方法。在创建新EntityHashSet之前,我调用原始SQL命令,从包含当前主Id的SlaveMasters表中删除条目

model.ExecuteSqlCommand("DELETE FROM SlaveMasters WHERE Master_Id = " + Id);
Slaves = new EntityHashSet<Slave>(slaves.Select(s => model.Slaves.CreateOrFind(s)));
model.ExecuteSqlCommand(“从SlaveMasters中删除,其中Master_Id=“+Id”);
Slaves=newentityhashset(Slaves.Select(s=>model.Slaves.CreateOrFind(s));

找到了一个不好的方法来解决这个问题。在创建新EntityHashSet之前,我调用原始SQL命令,从包含当前主Id的SlaveMasters表中删除条目

model.ExecuteSqlCommand("DELETE FROM SlaveMasters WHERE Master_Id = " + Id);
Slaves = new EntityHashSet<Slave>(slaves.Select(s => model.Slaves.CreateOrFind(s)));
model.ExecuteSqlCommand(“从SlaveMasters中删除,其中Master_Id=“+Id”);
Slaves=newentityhashset(Slaves.Select(s=>model.Slaves.CreateOrFind(s));
您所说的“ef配置文件”是什么意思?您所说的“ef配置文件”是什么意思?