使用外键(FK)作为每层次表(TPH)的鉴别器

Jim*_*mes 26 sql-server entity-framework-4.1

[问:]是否有可能使用FK作为EF中的鉴别器,人们想出了哪些变通方法?

场景

EF对象

public class List
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<ListItem> Items { get; set; }
}

public abstract class ListItem
{
    public int Id { get; set; }
    public List List { get; set; }
    public string Text { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

数据库

EF专用(即无法更改)未使用的现有DB 具有以下字段:

List
    Id         int not null      (identity)
    Name       varchar

ListItem
    Id         int not null      (identity)
    ListId     int not null      (FK to List.Id)
    Text       varchar
Run Code Online (Sandbox Code Playgroud)

期望的结果

我希望列表的Id成为ListItem的鉴别器.ie对于列表中的每个条目,实现了一个来自ListItem的单独的类.

例如列表[Id:1]

public class PersonListItem : ListItem
{
    public int PersonId { get; set; }
    public Person Person { get; set; }
}

public class ListItemConfiguration : EntityTypeConfiguration<ListItem>
{
    Map<PersonListItem>(m => m.Requires("ListId").HasValue(1));
}
Run Code Online (Sandbox Code Playgroud)

在上述情况下,保存更改会导致SQL异常,因为EF在创建新的ListItem实例时会尝试插入List_Id .List_Id不是一个字段,我不能将ListId映射为ListItem上的属性,因为它不能用作鉴别器.

到目前为止我的解

这个问答解释了为什么他们决定不允许FK作为鉴别者.

我的解决方法,到目前为止是对其他字段添加到分贝作为鉴别器,然后将其设置为相同的值,以使用ListId使用插入触发(处理非EF插入),然后添加ListId导航属性列表项实体.

有没有人有任何建议/选择?

小智 3

最简单的解决方案在于引入一个枚举,用作表示类型的鉴别器。您提到的帖子清楚地描述了 FK 无法使用,因此您需要将其重构为可以应用的内容。它需要一些维护,但由于您还必须知道从列表项派生的类型,因此我不认为这是一个主要问题。您的其他选择是放弃 TPH 并使用 TablePerType。这样,您实际上不必引入枚举,但您将为每个派生列表项生成一个表。