实体框架 - 包括继承的类型
本文关键字:类型 继承 包括 框架 实体 | 更新日期: 2023-09-27 18:35:41
在我的数据模型中,我有一个基类Case
,可以有几种不同的类型:Investigation
、DisciplinaryAction
等。 这些都继承自Case
. 这就是我在实体框架中对其进行建模的方式。
public abstract class Case : BaseEntity
{
public int CaseId { get; set; }
public int PlanId { get; set; }
public int CaseTypeId { get; set; }
public CaseType CaseType { get; set; }
}
public class Investigation : Case
{
}
对于继承的类,CaseId
是主键和外键。我有一个DbSet
Cases
. 当我需要显式访问其中一个继承类型时,我使用 context.Cases.OfType<Investigation>()
. 所有这些都工作正常。
在我的CaseRepository
中,我有一种方法可以通过ID获取案例:
public Case GetById(int id)
{
var oversightCase = context.Cases
.Include(p => p.Owner)
.Include(p => p.CreatedBy)
.Include(p => p.ModifiedBy)
.FirstOrDefault(f => f.CaseId == id);
}
我的问题是,对于其中一个继承类型,我想包含另一个导航属性。 有没有办法以比这更不令人作呕的方式一般地访问继承类型并包含并非所有继承类型都具有的属性:
public Case GetById(int id)
{
var oversightCase = context.Cases
.Include(p => p.Owner)
.Include(p => p.CreatedBy)
.Include(p => p.ModifiedBy)
.Include(p => p.LinkedObjects)
.FirstOrDefault(f => f.CaseId == id);
if (oversightCase != null && oversightCase is Investigation)
{
oversightCase = context.Cases.OfType<Investigation>()
.Include(p => p.Owner)
.Include(p => p.CreatedBy)
.Include(p => p.ModifiedBy)
.Include(p => p.LinkedObjects)
.Include(p => p.Investigatee)
.FirstOrDefault(f => f.CaseId == id);
}
return oversightCase;
}
是的,当case id
与Investigation
相关时,您需要执行两个请求。像你写的那样做,不是正确的方法。因为如果id
与Investigation
相关,那么您正在对数据库执行两个大请求,每个请求执行相同的前四个连接查询。
第二个请求(在您的 if
语句块中)只是您第一个请求的扩展,因为它们共享以下代码:
.Include(p => p.Owner)
.Include(p => p.CreatedBy)
.Include(p => p.ModifiedBy)
.Include(p => p.LinkedObjects)
为避免将来出现性能问题,请执行以下操作:
首先创建一个泛型方法,如下面的代码,其中 T 必须是 Case
的子类:
public IQueryable<T> GetCaseCommonData<T>()
where T : Case
{
return context.Cases.OfType<T>
.Include(p => p.Owner)
.Include(p => p.CreatedBy)
.Include(p => p.ModifiedBy)
.Include(p => p.LinkedObjects);
}
其次,使用这样的泛型方法:
public Case GetById(int id)
{
Case oversightCase;
if (context.Cases.OfType<Investigation>().Any(f => f.CaseId == id))
{
oversightCase = GetCaseCommonData<Investigation>()
.Include(p => p.Investigatee)
.SingleOrDefault(f => f.CaseId == id);
}
else
{
oversightCase = GetCaseCommonData<Case>()
.SingleOrDefault(f => f.CaseId == id);
}
return oversightCase;
}
使用我的解决方案,像下面的ocde这样的include
执行一次:
.Include(p => p.Owner)
.Include(p => p.CreatedBy)
.Include(p => p.ModifiedBy)
.Include(p => p.LinkedObjects);
通过像我一样重构代码,检查案例 ID 是否为Investigation
类型的查询比您为相同目的编写的代码更有效:
context.Cases.OfType<Investigation>().Any(f => f.CaseId == id)