18

使用 Entity Framework 4 CTP5 Code First 和这个例子

是否可以访问鉴别器值?

我想在像这样的投影中使用它

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

这篇文章中,我了解到鉴别器不能映射到属性,但是还有其他访问它的方法吗?

4

7 回答 7

24

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

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

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

于 2013-06-11T16:44:39.323 回答
13

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

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

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

于 2018-07-26T11:59:42.653 回答
8

Morteza Manavi 在他的帖子评论中提供了更多信息后,简单的答案是否定的

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

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

于 2011-01-04T14:42:21.717 回答
5

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

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

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");
})

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

class BillingDetail
{
    public BillingDetailId { get; set; }

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

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

class MyDerivedBillingDetail : BillingDetail
{
    public MyDerivedBillingDetail()
    {
        this.DiscriminatorValue = "MyValue";
    }
}
于 2015-12-10T18:08:23.890 回答
3

扩展 @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);
});

如果您需要构建可组合的查询,例如,对鉴别器进行分组等,这非常有用。

于 2018-10-18T21:53:38.913 回答
1

为什么不改用以下查询?

 var q = con.BillingDetails.OfType<BankAccount>().ToList();
于 2010-12-24T14:12:17.737 回答
0

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

在 DBContext 中:

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

在基类中:

public string Type { get; private set; }
于 2021-07-23T11:49:22.207 回答