Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF急切地加载导航属性问题_C#_Asp.net Mvc_Entity Framework_Entity Framework 6_Eager Loading - Fatal编程技术网

C# EF急切地加载导航属性问题

C# EF急切地加载导航属性问题,c#,asp.net-mvc,entity-framework,entity-framework-6,eager-loading,C#,Asp.net Mvc,Entity Framework,Entity Framework 6,Eager Loading,我将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

我将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; }
}
首先,我通过ID找到父对象,然后将其传递给delete方法,将其状态更改为deleted。context.SaveChanges()最终提交删除操作

这很有效。find方法只拉起父对象,Delete工作,因为我在子对象上启用了cascadeondelete

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

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

public virtual Gender Gender { get; set; }
出于某种原因,EF开始在Parent.Find()方法上提取相关的子级。因此,我得到以下错误:

操作失败:无法更改关系,因为一个或多个外键属性不可为null。对关系进行更改时,相关外键属性设置为空值。如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象

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

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

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

  • 有人能解释为什么EF在我不使用相关实体的情况下仍在加载它们吗?

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

    kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
    
    kernel.Bind().To().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;
        }
    
    public bool DeleteView(int-viewId)
    {
    //这是一个解决方法。ninject似乎没有处理上下文。
    //因此,新创建的视图的所有信息(导航属性)都显示在上下文中。
    //因此,在尝试删除复合对象时,会出现引用键错误。
    使用(var context=new ApplicationDbContext())
    {
    var repo=新的一般报告(上下文);
    var view=repo.GetById(viewId);
    回购。删除(查看);
    SaveChanges();
    }
    //var model=_unitOfWork.CustomViews.GetById(viewId);
    //_unitOfWork.CustomView.Delete(模型);
    //_unitOfWork.Save();
    返回true;
    }
    
    注释后的代码抛出错误,而未注释的代码(使用block)有效。此调用之前的控制器方法加载CustomView实体(该实体的结构类似于父实体,具有子实体列表)。并且可以触发后续的用户操作来删除该视图

    我认为这与未处理的上下文有关。也许这和Ninject或UnitOfWork有关,我还没能确定这一点。GetById()可能正在从上下文缓存或其他地方提取整个实体


    但是上面的解决方法对我很有效。只是把它放在那里,这样可以帮助别人。

    当你恢复时,你也恢复了数据库吗?你的问题可能和DB有关,是的。我删除了数据库并重新创建了它。是否需要先加载实体?您可以通过创建一个新实例、设置id、将其附加到上下文,然后调用
    delete
    来删除它。恢复更改的事实让我产生怀疑。您确定这不是由于调试器检查
    子项从而加载行而导致的吗?@Rob非常感谢。我觉得自己像个白痴。实际上是调试器在示例应用程序中加载属性,但在我的实际应用程序中,问题不同。你的评论给了我一个新的调查方向。谢谢在我的真实应用程序中,请求之间的上下文似乎没有被破坏。在以前的请求中,有问题的实体已在上下文中完全加载,而删除请求似乎实际上是从缓存中提取的。我将添加一个详细解释的答案。使用Autofac-针对生命周期、范围、处理和工作单元(根据请求)的更成熟、更容易理解的解决方案。换句话说,整个帖子是不正确的,与EF没有任何共同点,但模式、注射等。我认为一旦赏金到期,这个问题应该删除,因为它只是误导,我看不出它如何能帮助别人。
    
    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;
        }