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

发布于 2024-10-09 05:39:55 字数 635 浏览 4 评论 0 原文

使用 Entity Framework 4 CTP5 Code First 和 此示例

是否可以访问鉴别器值?

我想在类似

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

From 这篇文章 我知道鉴别器无法映射到属性,但是还有其他方法可以访问它吗?

Using Entity Framework 4 CTP5 Code First and this example

Is it possible to access the discriminator value?

I would like to use it in a projection like

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

From this post I understand the discriminator cannot be mapped to a property but is there any other way of accessing it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

予囚 2024-10-16 05:39:55

我可能在这方面迟到了,但我只是向基类添加了一个 getter 属性,该属性返回当前类型的名称:

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

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

I may be late to the game on this one, but I just added a getter property to the base class that returned the name of the current type:

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

Since by default EF is going to use this same value for the Discriminator field, they will match up.

奢华的一滴泪 2024-10-16 05:39:55

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

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

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

In EF Core 2.1 (I haven't checked previous versions) it's enough to add Discriminator to the base abstract class as private set property. It will be mapped with adequate value.

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

EF by itself will automatically insert appropriate discriminator value to the database and will automatically set it to an object on read.

旧夏天 2024-10-16 05:39:55

Morteza Manavi 在他的帖子的评论中简单的答案是否定的

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

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

After further information from Morteza Manavi in the comments of his post the simple answer is no

you should be aware that the discriminator column is used internally by Code First and you cannnot read/write its values from an inheritance mapping standpoint.

To access the discriminator I would have to execute a SqlQuery against the database or change my mapping strategy.

帅气称霸 2024-10-16 05:39:55

撇开原因不谈,我最近遇到了同样的问题,但相信这仍然与 相关EF 框架 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");
})

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

class BillingDetail
{
    public BillingDetailId { get; set; }

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

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

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

Reason aside, I recently ran into the same problem but believe this is still relevant for v4 of the EF Framework.

First, create a view which selects the discriminator value into two columns.

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

Secondly, map the view to your entity during context creation:

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

Thirdly, define your discriminator mapping for your derived class using one of the columns in your view:

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

Finally, define a getter and a private setter for the other discriminator column in your view with the DatabaseGenerated annotation set as Computed to prevent EF from updating/inserting for this field:

class BillingDetail
{
    public BillingDetailId { get; set; }

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

You can change the private setter to be protected and set this value explicitly during the construction of your derived entities so that the discriminator has a value prior to being persisted:

class MyDerivedBillingDetail : BillingDetail
{
    public MyDerivedBillingDetail()
    {
        this.DiscriminatorValue = "MyValue";
    }
}
这样的小城市 2024-10-16 05:39:55

要扩展 @Michael Black 对 Entity Framework Core 2.1 的回答(之前?在 2.1.4 中测试过),

您可以使用您想要的任何属性名称、数据库字段名称和数据类型。

创建一个属性:

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

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

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

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

To expand on @Michael Black's answer for Entity Framework Core 2.1 (earlier? tested in 2.1.4)

You can use any property name, database field name and data type you want.

Create a property:

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

Then in your context class with the fluent API via modelBuilder:

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

This is really useful if you need to build composable queries that e.g., group on the discriminator, etc.

感情废物 2024-10-16 05:39:55

为什么不使用下面的查询呢?

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

Why don't you use the following query instead?

 var q = con.BillingDetails.OfType<BankAccount>().ToList();
你是年少的欢喜 2024-10-16 05:39:55

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

在 DBContext 中:

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

在基类中执行以下操作:

public string Type { get; private set; }

You can add a property with the name you gave to the discriminator in EF Core. Example:

In DBContext:

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

In base class do:

public string Type { get; private set; }
晚雾 2024-10-16 05:39:55

对我有用的是按照以下步骤通过 .HasCompulatedColumnSql() 检索鉴别器列:

  1. 添加一个属性来访问值,例如
    公共字符串EntityType{获取;放; }
  2. 配置此属性以映射到 sql 用户定义函数
    entity.Property(e => e.EntityType).HasCompulatedColumnSql("dbo.GetEntityType([Id])")
  3. 定义用户定义的函数来检索值:
    创建函数 dbo.GetEntityType (@AccountId UNIQUEIDENTIFIER)
    返回 NVARCHAR(MAX) AS
    开始
        -- 与其他表做一些事情
        声明 @returnvalue NVARCHAR(MAX);
    
        SELECT @returnvalue = 实体类型
        来自 dbo.Entiites
        其中 Id= @Id
    
        返回(@returnvalue);
    
    结尾
    
  4. 以通常的方式进行迁移和数据库更新。

What worked for me was retrieving the Discriminator column via .HasComputedColumnSql() following the steps below:

  1. Add a property to access the value e.g
    public string EntityType{ get; set; }
  2. Configure this property to map to an sql user defined function
    entity.Property(e => e.EntityType).HasComputedColumnSql("dbo.GetEntityType([Id])")
  3. Define a user defined function to retrieve the value:
    CREATE FUNCTION dbo.GetEntityType (@AccountId UNIQUEIDENTIFIER)
    RETURNS NVARCHAR(MAX) AS
    BEGIN
        -- do stuff with other tables
        DECLARE @returnvalue NVARCHAR(MAX);
    
        SELECT @returnvalue =  EntityType
        FROM dbo.Entitites
        WHERE Id= @Id
    
        RETURN(@returnvalue);
    
    END
    
  4. Do migrations and database update in the usual manner.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文