实体框架7(Beta 7)和实体跟踪

6

我试图将我的领域模型(负责业务逻辑)与我的数据模型分开,后者是EF 7用来构建架构的。

但是,我在将对领域模型所做的更改持久化到数据库方面遇到了问题。

举个例子,假设我有一个数据模型PersonTable和一个领域模型Person:

public class PersonTable
{
    public virtual Guid Id { get; set; }
    public virtual String Name { get; set; }
    public virtual String Surname { get; set; }
}

public class Person
{
    public virtual Guid Id { get; set; }
    public virtual String Name { get; set; }
    public virtual String Surname { get; set; }
    //Other Domain Methods and Constructors...
}

我希望通过这种方式将我的域名更改持久化到数据库中:

public void Update(Person p)
{
    var person = new PersonTable
    {
        Id = p.Id,
        Name = p.Name,
        Surname = p.Surname
    }
    PersonDbContext.Update(person);
    PersonDbContext.SaveChanges();
}

当我尝试应用这些更改时,我收到一个InvalidOperationException,其中说:“无法跟踪实体类型'Tables.PersonTable'的实例,因为已经正在跟踪另一个具有相同键的此类型的实例。对于新实体,请考虑使用IIdentityGenerator生成唯一键值。”我认为这与实体跟踪有关,但在EF 7中如何工作呢?我希望能够应用此模式,以便我可以分离这两个模型。
3个回答

8
// Before updating we have fetch original data row from database.
// So we need to use AsNoTracking().

var originalPerson = PersonDbContext.Person.AsNoTracking().FirstOrDefault(p => p.Id == id);

在保存时,我们需要使用以下代码。

PersonDbContext.Entry(originalPerson).Context.Update(newPersonDetail);

3
当您的 PersonDbContext 实例已经跟踪了一个与同一ID的 Person 实例时,就会发生错误。
为了调试此问题,请检查您在 PersonDbContext.ChangeTracker.Entries() 中已经跟踪了什么。我预计您会发现已经有一个与您尝试更新的那个匹配的 PersonTable.Id 条目。
为了确保您不会遇到这些冲突,请不要在多个线程或多个HTTP请求之间重复使用 PersonDbContext (如果这是Web应用程序)。

这是我的依赖注入引起的问题吗?更新方法存在于一个被注入到服务中的依赖项中,该服务还被注入到控制器(用于HTTP请求)中。 - Lutando
1
通过在查询时使用PersonDbContext.PersonTable.AsNoTracking(),成功避免了这个问题。 - Lutando
很可能是依赖注入。如果它没有被注册到正确的生命周期中,这种情况经常发生。 - natemcmaster
@Lutando:使用PersonDbContext.PersonTable.AsNoTracking()不会意味着EF现在无法利用跟踪来快速检索内存中的实体,并且每次请求该实体时都要进行显式调用吗?这对我来说似乎更像是一种退化的解决方法。相反,我不知道为什么检查EntityState.Detached不再起作用。即使实体正在跟踪下,Context.Entry(entity).State也显示它处于Detached状态!! - Vaibhav
DI设置为“Scoped”时出现了这个问题,并且ChangeTracker.Entries()中有正确数量的更改,但仍然不确定原因。 - r590
natemcmaster - 那么如何“不要在多个线程之间重用DbContext”呢? - Sam

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接