我是否可以使用Entity Framework 4 CTP5访问TPH映射中的鉴别器值

Dav*_*enn 14 code-first entity-framework-4 entity-framework-ctp5

使用Entity Framework 4 CTP5 Code First和本例

是否可以访问鉴别器值?

我想在投影中使用它

context.BillingDetails.Select(x => new { Number = x.Number, DiscrimitatorValue = /* how do I get the discriminator value? */ });
Run Code Online (Sandbox Code Playgroud)

这篇文章我明白鉴别器不能映射到属性,但有没有其他方式访问它?

Pau*_*aul 20

我可能在这个游戏上迟到了,但我刚刚给基类添加了一个getter属性,它返回了当前类型的名称:

public string DiscriminatorValue {
    get {
        return this.GetType().Name;
    }
}
Run Code Online (Sandbox Code Playgroud)

由于默认情况下EF将使用与Discriminator字段相同的值,因此它们将匹配.

  • 我在这里错过了什么吗?这在“IQueryable.Select”中不起作用,这正是OP所要求的。`NotSupportedException:LINQ to Entities 不支持指定的类型成员“DiscriminatorValue”。仅支持初始值设定项、实体成员和实体导航属性。`。 (4认同)
  • 除非你覆盖它;-) (3认同)

Dav*_*enn 8

Morteza Manavi在他的帖子评论中得到进一步的信息,简单的答案是否定的

你应该知道,鉴别器列是由Code First内部使用的,你不能从继承映射的角度读取/写入它的值.

要访问鉴别器,我必须SqlQuery对数据库执行a 或更改我的映射策略.


小智 6

在EF Core 2.1中(我没有检查过以前的版本),足以将Discriminator其作为私有集属性添加到基本抽象类中。它将被映射为足够的值。

public abstract class Entity
{
    public int Id { get; set; }
    public string Discriminator { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

EF本身将自动将适当的鉴别符值插入数据库,并将其自动设置为读取对象。

  • 关于以前的 EF 版本,我可以确认这在 EF6 中不起作用。它只会尝试创建第二个“Discriminator1”列。 (2认同)

小智 5

抛开原因不谈,我最近遇到了同样的问题,但相信这仍然与EF Framework 的 v4相关。

首先,创建一个视图,将鉴别器值选择为两列。

create view dbo.vw_BillingDetail
as
    select BillingDetailId, DiscriminatorValue, DiscriminatorValue as DiscriminatorValue2 from dbo.BillingDetail
go
Run Code Online (Sandbox Code Playgroud)

其次,在上下文创建期间将视图映射到您的实体:

modelBuilder
    .Entity<BillingDetail>()
    .HasKey(n => n.BillingDetailId)
    .Map(map =>
    {
        map.ToTable("vw_Person");
    })
Run Code Online (Sandbox Code Playgroud)

第三,使用视图中的列之一为派生类定义鉴别器映射:

.Map<MyDerivedBillingDetail>(map =>
{
    map.Requires("DiscriminatorValue2").HasValue("YourValue");
})
Run Code Online (Sandbox Code Playgroud)

最后,为视图中的另一个鉴别器列定义一个 getter 和一个私有 setter,并设置DatabaseGenerated注释Computed以防止 EF 更新/插入此字段:

class BillingDetail
{
    public BillingDetailId { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DiscriminatorValue { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

您可以更改要保护的私有 setter 并在构建派生实体期间显式设置此值,以便鉴别器在持久化之前具有一个值:

class MyDerivedBillingDetail : BillingDetail
{
    public MyDerivedBillingDetail()
    {
        this.DiscriminatorValue = "MyValue";
    }
}
Run Code Online (Sandbox Code Playgroud)