首先,我已经有了解决该问题的方法,但这是一种重放属性设置,而不是直接使用更改跟踪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的好的解决方案,而不是像上面的最后一小段代码那样令人讨厌。
答案 0 :(得分:1)
尝试设置实体状态:
using (var context = new TestContext())
{
context.Entry(person).State = EntityState.Modified;
context.Entry(person.Class).State = EntityState.Added;
context.SaveChanges();
}