如何手动帮助DbContext了解这种情况下的更改?

时间:2018-11-30 03:52:49

标签: c# entity-framework entity-framework-6

首先,我已经有了解决该问题的方法,但这是一种重放属性设置,而不是直接使用更改跟踪API的方法(通过访问DbEntityEntry甚至是ObjectStateManager

因此,我想知道在这种情况下如何直接使用更改跟踪api。这里是涉及的类:

public class TestContext : DbContext
{
    public virtual DbSet<Class> Classes { get; set; }
    public virtual DbSet<Person> Persons { get; set; }
}

public class Class
{
    public Class()
    {
        Persons = new HashSet<Person>();
    }
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual HashSet<Person> Persons { get; set; }
}
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int ClassId { get; set; }
    [ForeignKey(nameof(ClassId))]
    [Required]
    public virtual Class Class { get; set; }       
}

这里的场景适用于分离的DbContext,这意味着它托管在某些远程服务上,而模型数据就是我们输入的全部数据。

//suppose we have an existing (loaded before from db) person here
//now on client side, we set its Class to a new instance
//and hope that it should be created after saving
person.Class = new Class { Name = "D" };
person.ClassId = 0;

//now on remote server side, we have the input person
//This is NOT working
using(var tc = new TestContext()){
    tc.Persons.Attach(person);
    tc.Classes.Add(person.Class);
    tc.SaveChanges();
}

上面的远程代码不起作用,实例Class可以很好地保存,但是仍然抛出异常(在行tc.SaveChanges()处),抱怨委托人和受抚养人之间存在不一致。我了解新创建的Class应该将其自动生成的Id同步到ClassId的{​​{1}}属性(保存后仍为person)。

因此,除非您需要对0进行两次调用,否则第一个调用是首先保存SaveChanges,然后再将第二个调用{{1}更新为Class的{​​{1}} }},如下所示:

ClassId

那当然不是一个好的解决方案。一个很好的解决方案(正如我在开始时提到的那样),但是它没有直接使用变更跟踪api。它只是尝试在附加person之后重播更改,如下所示:

SaveChanges

上面的代码看起来更好,并且可以正常工作。但它看起来也有点黑。

我正在寻求直接使用变更跟踪API的好的解决方案,而不是像上面的最后一小段代码那样令人讨厌。

1 个答案:

答案 0 :(得分:1)

尝试设置实体状态:

using (var context = new TestContext())
{
    context.Entry(person).State = EntityState.Modified;
    context.Entry(person.Class).State = EntityState.Added;
    context.SaveChanges();
}