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

时间:2010-12-24 11:06:18

标签: entity-framework-4 code-first entity-framework-ctp5

使用Entity Framework 4 CTP5 Code First和this example

是否可以访问鉴别器值?

我想在像

这样的投影中使用它
context.BillingDetails.Select(x => new { Number = x.Number, DiscrimitatorValue = /* how do I get the discriminator value? */ });

this post我知道鉴别器不能映射到属性,但有没有其他方法可以访问它?

7 个答案:

答案 0 :(得分:20)

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

public string DiscriminatorValue {
    get {
        return this.GetType().Name;
    }
}

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

答案 1 :(得分:8)

来自Morteza Manavi in the comments of his post的进一步信息后,简单的答案是否

  

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

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

答案 2 :(得分:4)

除了理由之外,我最近遇到了同样的问题但认为这仍然与v4 of the EF Framework相关。

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

create view dbo.vw_BillingDetail
as
    select BillingDetailId, DiscriminatorValue, DiscriminatorValue as DiscriminatorValue2 from dbo.BillingDetail
go

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

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

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

.Map<MyDerivedBillingDetail>(map =>
{
    map.Requires("DiscriminatorValue2").HasValue("YourValue");
})

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

class BillingDetail
{
    public BillingDetailId { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DiscriminatorValue { get; private set; }
}

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

class MyDerivedBillingDetail : BillingDetail
{
    public MyDerivedBillingDetail()
    {
        this.DiscriminatorValue = "MyValue";
    }
}

答案 3 :(得分:4)

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

public abstract class Entity
{
    public int Id { get; set; }
    public string Discriminator { get; private set; }
}

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

答案 4 :(得分:1)

为什么不使用以下查询?

 var q = con.BillingDetails.OfType<BankAccount>().ToList();

答案 5 :(得分:0)

扩展@Michael Black对Entity Framework Core 2.1的回答(较早吗?已在2.1.4中进行测试)

您可以使用任何所需的属性名称,数据库字段名称和数据类型。

创建属性:

[Column("foo_type_id")]
class Foo {
    public FooTypesEnum TypeId {get; set;}
}

然后在您的上下文类中通过modelBuilder使用流利的API:

modelBuilder.Entity<Foo>(b => {
    b.HasDiscriminator(foo => foo.TypeId)
        .HasValue<SubFooA>(FooTypesEnum.SubFooA)
        .HasValue<SubFooB>(FooTypesEnum.SubFooB);
});

如果您需要构建可组合的查询(例如,对鉴别符进行分组等),这真的很有用。

答案 6 :(得分:0)

您可以使用您为 EF Core 中的鉴别器指定的名称添加一个属性。示例:

在 DBContext 中:

...HasDiscriminator<string>("Type")..

在基类中做:

public string Type { get; private set; }