为啥实体框架核心加载实体的关系而不添加包含

Posted

技术标签:

【中文标题】为啥实体框架核心加载实体的关系而不添加包含【英文标题】:Why is Entity Framework core loading entity's relations without adding include为什么实体框架核心加载实体的关系而不添加包含 【发布时间】:2020-02-17 05:34:36 【问题描述】:

我在 .net 核心项目中使用 EF 核心。从 ef 上下文中获取数据后,对象的实体(一对多等)会自动加载。

这是我的代码:

 public TimeSheetActivity Get(int id)
 
     DataSets.TimeSheetActivity dbActivity = db.TimeSheetActivities
                                               .Include(k => k.ProjectFile)
                                               .Include(k => k.MeasurementUnit)
                                               .Include(k => k.TypeOfWork)
                                               .Include(k => k.TimeSheetProject)
                                               .FirstOrDefault(k => k.ID == id);

     return dbActivity == null ? null : _mapper.Map<TimeSheetActivity>(dbActivity);
 


public Project GetActivityProject(int id)

    //db.SaveChanges();

    TimeSheetActivity activity = Get(id);

    if (activity == null)
    
        return null;
    

    var dbTimeSheetProject = db.TimeSheetProjects.First(k => k.ID == activity.TimeSheetProjectId);

    var dbProject = db.Projects.First(k => k.ID == dbTimeSheetProject.ProjectId);
    // PROBLEM HERE >> dbProject is loading all entities related
    return _mapper.Map<Project>(dbProject);


问题在上面标记并在Projects上下文中注释,这里是项目类:

public class Project
    
        public int ID  get; set; 
        public string Title  get; set; 
        public string Description  get; set; 
        public DateTime DateAdded  get; set; 

        public int? ParentId  get; set; 
        public int? DepartmentId  get; set; 
        public int? CompanyId  get; set; 


        public virtual Department Department  get; set; 
        public virtual Company Company  get; set; 

        public virtual Project Parent  get; set; 

        public virtual List<Project> Activities  get; set; 
        public virtual List<TimeSheetProject> TimeSheetProjects  get; set; 
        public virtual List<ProjectFile> ProjectFiles  get; set; 

    

调试捕获:

【问题讨论】:

在这种情况下,您不能依赖监视窗口。东西是按需加载的,观看它是一种需求。因此,无法查看是否加载了某些内容。如果您想确定,最好检查发送到 SQL-Server 的查询,以查看包含的内容。 当你使用virtual 关键字表示EF load company LazyLoad @Holger 我在编译代码行后加载手表,所以它会产生实际的 db 对象结果。另外,automapper 抛出异常,因为它无法转换所有填充的实体.. @AmirNorouzpour 我删除了 virtual 关键字,没有任何改变 不,不可能查看任何“实际的数据库结果”,监视窗口本身正在向您的数据库发送进一步的查询,并重新加载您想查看的所有内容。即使这样,您“中断所有线程”调试窗口也可以运行您的代码。如果对象是在一个查询(使用包含)或多个查询(使用延迟加载)中加载的,您只能在 SQL 命令中看到。您想强制或避免加载所有对象吗?看起来您使用包含强制执行,所有内容都已加载,然后您抱怨所有内容都已加载。 【参考方案1】:

我认为问题是这样的(摘自文档):

Entity Framework Core 将自动修复先前加载到上下文实例中的任何其他实体的导航属性。因此,即使您没有明确包含导航属性的数据,如果之前加载了部分或所有相关实体,该属性仍可能会被填充。

https://docs.microsoft.com/en-us/ef/core/querying/related-data#eager-loading

【讨论】:

这可能是个有趣的案例 感谢您指出问题,我通过添加额外的 linq 表达式 asNoTracking() 来修复它【参考方案2】:

关于@cristi71000 的回答,情况就是这样。我的解决方案是添加AsNoTracking() 如下:

var dbProject = db.Projects.AsNoTracking()...

【讨论】:

以上是关于为啥实体框架核心加载实体的关系而不添加包含的主要内容,如果未能解决你的问题,请参考以下文章

为啥向核心数据实体添加双重属性会导致远距离相关实体中的属性冲突出现 NSInternalInconsistencyException?

为啥添加单个实体后我的核心数据需要很长时间才能保存?

实体框架,查询包含上下文更改的dbset,而不调用保存更改

实体之间的核心数据关系

C#实体框架:添加/插入记录并选择他而不保存更改[重复]

我的核心数据实体在哪里?