如何改进此 Entity Framework 查询
How to Improve on this Entity Framework Query
我有以下实体:
- 申请人:人
- 电话号码
- 电话类型
申请人来自Person
。 Applicant
有很多 PhoneNumber
(最多三个)。每个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 循环,但我在第一个查询中已经有大量连接,我不确定如何合并它们。这个问题是一个两部分的问题:
- 如何合并这两个查询和
- 如果我不合并查询,我如何改进
PhoneNumber
/ PhoneType
查询。
目标是 return 一个 Applicant
和一个 PhoneNumber
列表,每个 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();
}
}
提前感谢您提供的任何帮助。
EF Core 通过组合 Include() 和 ThenInclude() 支持加载多个级别,更多信息 here
要加载 Phone 以及 Phone 类型,您的查询应如下所示(为清楚起见,我删除了其余关系):
var applicant = DbContext.Applicants.Where(a => a.CreatedBy == userId)
.Include(applicant => applicant.PhoneNumbers)
.ThenInclude(phone => phone.PhoneType)
.FirstOrDefault();
我有以下实体:
- 申请人:人
- 电话号码
- 电话类型
申请人来自Person
。 Applicant
有很多 PhoneNumber
(最多三个)。每个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 循环,但我在第一个查询中已经有大量连接,我不确定如何合并它们。这个问题是一个两部分的问题:
- 如何合并这两个查询和
- 如果我不合并查询,我如何改进
PhoneNumber
/PhoneType
查询。
目标是 return 一个 Applicant
和一个 PhoneNumber
列表,每个 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();
}
}
提前感谢您提供的任何帮助。
EF Core 通过组合 Include() 和 ThenInclude() 支持加载多个级别,更多信息 here
要加载 Phone 以及 Phone 类型,您的查询应如下所示(为清楚起见,我删除了其余关系):
var applicant = DbContext.Applicants.Where(a => a.CreatedBy == userId)
.Include(applicant => applicant.PhoneNumbers)
.ThenInclude(phone => phone.PhoneType)
.FirstOrDefault();