Можно ли получить доступ к значению дискриминатора в сопоставлении TPH с помощью Entity Framework 4 CTP5 - PullRequest
13 голосов
/ 24 декабря 2010

Использование Entity Framework 4 CTP5 Code First и в этом примере

Возможно ли получить доступ к значению дискриминатора?

Я хотел бы использовать его в проекции типа

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

Из этого поста Я понимаю, что дискриминатор не может быть сопоставлен со свойством, но есть ли другой способ доступа к нему?

Ответы [ 6 ]

20 голосов
/ 11 июня 2013

Я могу опоздать к игре на этом, но я просто добавил свойство getter в базовый класс, который возвращает имя текущего типа:

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

Так как по умолчанию EF собираетсяиспользуйте это же значение для поля Дискриминатор, они совпадут.

8 голосов
/ 04 января 2011

После дополнительной информации от Мортеза Манави в комментариях к своему посту простой ответ -

вы должны знать, что столбец дискриминатора используется внутри Code First, и вы не можете читать / записывать его значения с точки зрения отображения наследования.

Чтобы получить доступ к дискриминатору, мне нужно выполнить SqlQuery для базы данных или изменить мою стратегию отображения.

4 голосов
/ 26 июля 2018

В EF Core 2.1 (я не проверял предыдущие версии) достаточно добавить Discriminator в базовый абстрактный класс как частное свойство набора.Он будет отображен с адекватным значением.

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

EF сам по себе автоматически вставит соответствующее значение дискриминатора в базу данных и автоматически установит его для объекта на чтение.

4 голосов
/ 10 декабря 2015

Причина в стороне, я недавно столкнулся с той же проблемой, но считаю, что она все еще актуальна для v4 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");
})

Наконец, определите получатель и частный установщик для другого столбца дискриминатора в вашем представлении с аннотацией DatabaseGenerated, установленной как Computed, чтобы предотвратить обновление / вставку EF для этого поля:

class BillingDetail
{
    public BillingDetailId { get; set; }

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

Вы можете изменить частный установщик для защиты и установить это значение явно во время создания ваших производных сущностей, чтобы дискриминатор имел значение до его сохранения:

class MyDerivedBillingDetail : BillingDetail
{
    public MyDerivedBillingDetail()
    {
        this.DiscriminatorValue = "MyValue";
    }
}
1 голос
/ 24 декабря 2010

Почему бы вам не использовать следующий запрос?

 var q = con.BillingDetails.OfType<BankAccount>().ToList();
0 голосов
/ 19 октября 2018

Чтобы расширить ответ @Michael Black для Entity Framework Core 2.1 (ранее? Протестирован в 2.1.4)

Вы можете использовать любое имя свойства, имя поля базы данных и тип данных, который вы хотите.

Создайте свойство:

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

Затем в вашем контекстном классе с плавным API через modelBuilder:

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

Это действительно полезно, если вам нужно создавать составные запросы, например:группа на дискриминаторе и т. д.

...