gpt4 book ai didi

c# - EF急切加载导航属性问题

转载 作者:行者123 更新时间:2023-11-30 12:22:14 26 4
gpt4 key购买 nike

我正在使用具有通用存储库模式的 EF6。最近,我在尝试一次性删除复合实体时遇到了问题。这是一个简化的场景:

public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public string Name { get; set; }

[ForeignKey("Parent")]
public int ParentId { get; set; }

public virtual Parent Parent { get; set; }
}

为了删除具有相关子项的父实体,我正在做这样的事情:

public virtual T GetById(int id)
{
return this.DBSet.Find(id);
}
public virtual void Delete(T entity)
{
DbEntityEntry entry = this.Context.Entry(entity);

if (entry.State != EntityState.Deleted)
{
entry.State = EntityState.Deleted;
}
else
{
this.DBSet.Attach(entity);
this.DBSet.Remove(entity);
}
}

首先,我通过 ID 找到父对象,然后将其传递给 delete 方法以将其状态更改为已删除。 context.SaveChanges() 最后提交删除。

这很好用。 find 方法只提取父对象并且 Delete 起作用,因为我在 Children 上启用了级联删除。

但是当我在 Child 类中添加另一个属性时:

[ForeignKey("Gender")]
public int GenderId { get; set; }

public virtual Gender Gender { get; set; }

出于某种原因,EF 开始在 Parent.Find() 方法上拉取相关的 Children。因此,我收到以下错误:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

即使恢复更改(删除 Gender 属性),问题仍然存在。我无法理解这种奇怪的行为!!

我只想删除父对象和子对象。有一些解决方案,但没有一个真正符合我的目的:

  1. 将 LazyLoading 设置为 false - this.Configuration.LazyLoadingEnabled = false;这可行,但在我的实际应用程序中,我需要此属性为真。
  2. 首先迭代所有子项并删除它们,然后删除父项。这似乎充其量是一种解决方法,而且非常冗长。
  3. 使用 Remove() 而不是仅仅将 EntityState 更改为 Deleted。我需要跟踪审计变更,以便 EntityState 在这方面提供帮助。

有人可以解释为什么 EF 正在加载相关实体,即使我没有使用它们吗?

最佳答案

问题似乎与上下文的生命周期有关。我正在使用工作单元并使用 ninject 将其注入(inject)我的服务层。

kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();

UnitOWork 类实现了 IDisposable。

public bool DeleteView(int viewId)
{
// This is a workaround. It seems ninject is not disposing the context.
// Because of that all the info (navigation properties) of a newly created view is presisted in the context.
// Hence you get a referential key error when you try to delete a composite object.
using (var context = new ApplicationDbContext())
{
var repo = new GenericRepository<CustomView>(context);
var view = repo.GetById(viewId);
repo.Delete(view);
context.SaveChanges();
}
//var model = _unitOfWork.CustomViews.GetById(viewId);
//_unitOfWork.CustomViews.Delete(model);
//_unitOfWork.Save();

return true;
}

注释的代码抛出错误,而未注释的代码(using block )有效。此调用之前的 Controller 方法加载 CustomView 实体(其结构与带有子列表的 Parent 类似)。并且可以触发后续用户操作以删除该 View 。

我认为这与未处理的上下文有关。也许这与 Ninject 或 UnitOfWork 有关,我还不能确定。 GetById() 可能会从上下文缓存或其他内容中提取整个实体。

但上述解决方法对我有用。只是把它放在那里,以便它可以帮助别人。

关于c# - EF急切加载导航属性问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41658998/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com