【发布时间】:2020-11-28 19:22:49
【问题描述】:
我有一个 EF Core 代码优先项目并创建了下表
[Table("Activity")]
public class Activity : BaseModel
{
[Key]
public int Id { get; set; }
public int ActivityId { get; set; }
public TransactionType Type { get; set; }
public virtual ActivityItem Item { get; set; }
}
ActivityItem 是一个不映射到自己的表的抽象类,但我有三个独立的模型都继承自它。
//Not its own table in the database
public abstract class ActivityItem
{}
[Table("ClassA")]
public class ClassA : ActivityItem
{
public int Id {get; set;}
}
[Table("ClassB")]
public class ClassB : ActivityItem
{
public int Id {get; set;}
}
[Table("ClassC")]
public class ClassC : ActivityItem
{
public int Id {get; set;}
}
在这个特定的例子中,我明确避免使用 Table-Per-Hierarchy 方案,因为我需要 ClassA、ClassB 和 ClassC,因为数据库中有自己的唯一表。
每当我从Activity 表中查询条目时,我都会使用Type 属性来指示Item 是否是ClassA、ClassB 或ClassC 的实例。
当我形成查询以填充Item 导航属性时,我是否仍然可以使用Include 方法?
当前解决方案
var activity = _context.Activity.Where(...).FirstOrDefault();
if (activity.Type == "ClassA")
activity.Item = _context.ClassA.First(p => p.Id == activity.ActivityId);
else if (activity.Type == "ClassB")
activity.Item = _context.ClassB.First(p => p.Id == activity.ActivityId);
else if (activity.Type == "ClassC")
activity.Item = _context.ClassC.First(p => p.Id == activity.ActivityId);
所需的解决方案
var activity = _context.Activity.Include(p => p.Item).Where(...).FirstOrDefault();
我知道当您使用Include 方法时,EF Core 会在相关表上编写联接查询,但在我的情况下,没有相关表,因为ActivityItem 未在数据库中表示。有没有一种方法可以根据我的自定义 Type 字段明确指定要加入的表,而不使用 Table-Per-Hierarchy 方案?
【问题讨论】:
-
如果你想在一个查询中获取数据,你必须对每个表进行左连接,这有点违背了
ActivityId和Type的目的。相反,您可以为每个可使用相应导航属性为空的表设置一个 FK,然后您将能够将它们全部包含在内,并且您必须找出不为空的类型。基本上,关系数据库不能完全模拟继承。 -
或者,您可能需要考虑一种解决方案,其中您有一个活动表,其中包含确定每个活动之间存在差异的信息。
标签: c# linq entity-framework-core ef-core-3.1