我懒得加载这些属性吗?

时间:2011-07-25 16:20:59

标签: c# linq entity-framework

我们正在使用Entity Framework 4.1进行数据访问,同时构建对象,我们开始向自己提问 关于数据库应用程序的繁琐程度。现在,我们真正开始关注的一个项目如下:

public MasterPreAward()
{
   public int ID 
   public int MemberID 
   public int CycleID

   public virtual Cycle 
   public virtual Member 
   public virtual Status
   public virtual ICollection<DataTracking> DataTrackings
   public virtual ICollection<ReviewerAssignment> Reviewers
 }

MasterPreAward是来自数据库的生成实体,具有Cycle,Member,Status的导航属性以及DataTrackings的两个集合 评审。我们想知道的是,Entity Framework是如何根据这些项加载子对象并将我们在后续模型中使用的数据带回来的? 如您所见,我们传入MasterPreAward对象,然后访问基于MasterPreAward加载的子属性。

public ViewHeaderSummary(MasterPreAward masterPreAward)
{
   MasterPreAwardId = masterPreAward.ID;
   ClientId = masterPreAward.Cycle.Project.Program.ClientID;
   ApplicationId = masterPreAward.MemberID;
   ProgramId = masterPreAward.Cycle.Project.ProgramID;
   ProjectId = masterPreAward.Cycle.ProjectID;
   EventTypeId = masterPreAward.DataTrackings.FirstOrDefault(x=>x.Finished==true
                      && x.EventTypeID==(int)FormEvents.Application).EventTypeID;
   CycleId = masterPreAward.CycleID;
   FormId = masterPreAward.Cycle.CycleForms.FirstOrDefault().FormID;
}

我们想知道的是,这是访问这些属性的最佳方式,还是应该考虑以不同的方式进行此类工作?

2 个答案:

答案 0 :(得分:3)

我认为默认设置是独立地延迟加载每个嵌套集合,这可能会导致大量数据库流量。

验证生成的SQL的最佳方法是启动SQL事件探查器并确认查询数。

您可以通过调用.Include方法强制EF热切地加载相关实体。有关详细信息,请参阅here

答案 1 :(得分:2)

您似乎不会查询完整实体,只会查询一堆标量值。在我看来,这将是一个很好的候选者,可以在单个数据库往返中收集所有需要的值:

    var result = dbContext.MasterPreAwards
        .Where(m => m.ID == masterPreAward.ID)
        .Select(m => new
        {
            ClientId = m.Cycle.Project.Program.ClientID,
            ProgramId = m.Cycle.Project.ProgramID,
            ProjectId = m.Cycle.ProjectID,
            EventTypeId = m.DataTrackings.Where(d => d.Finished
                && x.EventTypeID==(int)FormEvents.Application)
                .Select(d => d.EventTypeID).FirstOrDefault(),
            FormId = m.Cycle.CycleForms.Select(c => c.FormID).FirstOrDefault()
        })
        .Single();

    MasterPreAwardId = masterPreAward.ID;
    ClientId = result.ClientID;
    ApplicationId = masterPreAward.MemberID;
    ProgramId = result.ProgramID;
    ProjectId = result.ProjectID;
    EventTypeId = result.EventTypeId;
    CycleId = masterPreAward.CycleID;
    FormId = result.FormID;

如您所见,您需要DbContext来运行此类查询。

懒惰地加载所有相关实体的原始方式将导致5个数据库查询(我CycleProjectProgramDataTrackingsCycleForms)。最糟糕的是对DataTrackings.FirstOrDefaultCycleForms.FirstOrDefault的查询,这些查询实际上会首先将完整集合从数据库加载到内存中,然后在内存中执行FirstOrDefault加载的集合只返回一个元素,然后只使用一个属性。

编辑:查询ApplicationIdCycleId没有必要,代码已更改。)