如何在通用情况下将现有实体附加到实体框架上下文中?

3

我想在实体框架6中使用AsNoTracking和LazyLoadingEnabled = false加载一个实体。在某些特殊情况下,我想显式重新加载某些集合。如何显式加载分离实体的集合?

我正在寻找一种通用选项,将现有实体附加到上下文中。

我的调用看起来像这样:

var myCar = await this.myCarRepositoryAccessor.GetById(this.UnitOfWork, 1).ConfigureAwait(false);
this.UnitOfWork.LoadCollection(myCar, e => e.Driver);

DataRepository中的GetById看起来像这样:

public Task<TEntity> GetById(int id)
{
    return id == 0
        ? Task.FromResult(default(TEntity))
        : this.Context.InternalSet<TEntity>().AsNoTracking()?.SingleOrDefaultAsync(p => p.Id == id);
}

UnitOfWork中的LoadCollection看起来像这样:

public void LoadCollection<TEntity, TElement>(TEntity entity, Expression<Func<TEntity, ICollection<TElement>>> navigationProperty) where TEntity : class, IEntity where TElement : class
{
    //this.context.Entry(entity).State = EntityState.Unchanged
    this.context.Entry(entity).Collection(navigationProperty).Load();
}

我尝试将实体状态设置为Unchanged,但出现以下错误消息:

附加类型为'MyCar'的实体失败,因为另一个相同类型的实体已经具有相同的主键值。当使用'Attach'方法或将实体状态设置为'Unchanged'或'Modified'时,如果图中的任何实体具有冲突的键值,则可能会发生这种情况。这可能是因为某些实体是新的,尚未接收到数据库生成的键值。在这种情况下,请使用'Add'方法或'Added'实体状态来跟踪图形,然后根据需要将非新实体的状态设置为'Unchanged'或'Modified'。


2
你尝试过在加载集合之前附加实体吗?例如: this.context.Set<TEntity>().Attach(entity); - DavidG
我想只在一些特殊情况下重新加载集合。如果我提前知道它的工作原理,那就好了。 - steven.treske
抱歉,我不明白你在说什么。 - DavidG
我想以延迟的方式加载集合。 - steven.treske
是的,这就是我的代码可以让你做到的。 - DavidG
David Code将实体附加到您的上下文中,这将允许显式加载工作。我认为当您尝试将状态设置为未更改时,您也在尝试做同样的事情。 - Munzer
1个回答

1
我猜这是因为使用了AsNoTracking(),显式加载无法与其一起使用。
如果想要使用显式加载,您应该从getbyid方法中删除它。
此外,请注意您可以使用字符串与集合一起使用,因此您可以简单地使用字符串或字符串列表,以防您有多个导航需要加载。
还值得知道的是,对于集合,您使用集合,而对于单个实体导航,您应该使用引用。
最好的做法是向您的getbyid字符串列表添加另一个参数,并将所有字符串包含在该列表中,因为include也接受字符串。

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