【问题标题】:How to Improve on this Entity Framework Query如何改进此实体框架查询
【发布时间】:2023-03-03 09:56:02
【问题描述】:

我有以下实体:

  • 申请人:人
  • 电话号码
  • 电话类型

申请人来自PersonApplicant 有许多 PhoneNumbers(最多三个)。每个PhoneNumber只有1个PhoneType

public class Applicant : Person
{    
    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
}

public class PhoneNumber 
{                        
    public int PersonId { get; set; }

    [Required]
    [MaxLength(17)]
    public string Number { get; set; }    

    public int PhoneTypeId { get; set; }            

    public virtual PhoneType PhoneType { get; set; }

}

public class PhoneType 
{     
    [Required]
    [MaxLength(24)]
    public string Name { get; set; }

    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
}

在我看来,我正在使用的两个查询可以合并并消除 foreach 循环,但我在第一个查询中已经有大量连接,我不确定如何合并它们。这个问题是一个两部分的问题:

  1. 如何合并这两个查询和
  2. 如果我不合并查询,如何改进PhoneNumber / PhoneType 查询。

目标是返回一个带有PhoneNumbers 列表的Applicant,每个PhoneNumber 带有一个PhoneType。为清楚起见,类型为:家庭、办公室和移动。

/*------------------------------------------*/
/* Obtain the Applicant                     */
/*------------------------------------------*/
IQueryable<Applicant> applicantQuery = 
      DbContext.Applicants.Where(a => a.CreatedBy == userId)
               .Include(applicant => applicant.Address)
               .Include(applicant => applicant.Address.StateProvince)
               .Include(applicant => applicant.PhoneNumbers)                                                
               .Include(applicant => applicant.HomeChurch)
               .Include(applicant => applicant.HomeChurch.Address)
               .Include(applicant => applicant.HomeChurch.Address.StateProvince)
               .Include(applicant => applicant.TripApplication);

Applicant applicant = applicantQuery.FirstOrDefault<Applicant>();

if (applicant != null && applicant.PhoneNumbers != null)
{
    IQueryable<PhoneType> phoneTypeQuery = DbContext.Set<PhoneType>();
    List<PhoneType> phoneTypes = phoneTypeQuery.ToList<PhoneType>();

    foreach (PhoneNumber ph in applicant.PhoneNumbers)
    {
        ph.PhoneType = (phoneTypes.Where(pt => pt.Id == ph.PhoneTypeId)).First();
    }
}

提前感谢您提供的任何帮助。

【问题讨论】:

    标签: sql-server linq linq-to-sql entity-framework-core


    【解决方案1】:

    EF Core 支持通过将 Include()ThenInclude() 结合来加载多个级别,更多信息 here

    要加载电话和电话类型,您的查询应该如下所示(为了清楚起见,我删除了其余的关系):

    var applicant = DbContext.Applicants.Where(a => a.CreatedBy == userId)
            .Include(applicant => applicant.PhoneNumbers)                                                
            .ThenInclude(phone => phone.PhoneType)
            .FirstOrDefault();
    

    【讨论】:

    • 谢谢 E-Bat。我会试一试的。
    • 再次感谢您。我不仅让它发挥作用,而且在这个过程中学到了一项新技术。
    • @Andy,很高兴为您提供帮助,改进您的应用程序的下一步是使用异步方法,例如 FirstOrDefautlAsync() ;)
    • 是的,我知道。我在写 BusinessLogicLayer 和 RepositoryLayer 的时候很懒。
    • 你让我感到内疚。整个存储库层以及业务逻辑层现在是同步的。
    猜你喜欢
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    相关资源
    最近更新 更多