在EF中使用枚举类

时间:2016-05-29 18:20:55

标签: c# enums entity-framework-core

我在我的域模型中使用基于Jimmy Bogard的this文章的枚举类。但是,EF将类视为实体,并希望定义一个键。

有没有办法让EF存储枚举类中的值,就像使用标准C#枚举一样?

这就是我目前实现枚举类的方法:

public class ReservationStatus : Enumeration
{
    public static readonly ReservationStatus Outstanding = new ReservationStatus(0, "Oustanding");
    public static readonly ReservationStatus Paid = new ReservationStatus(1, "Paid");
    public static readonly ReservationStatus Canceled = new ReservationStatus(2, "Canceled");
    public static readonly ReservationStatus Rejected = new ReservationStatus(3, "Rejected");

    private ReservationStatus() { }
    private ReservationStatus(int value, string displayName) : base(value, displayName) { }
}

public class Reservation : Entity<int>
{
    public ReservationStatus Status { get; set; }
}

我正在使用EF 7 RC1。

3 个答案:

答案 0 :(得分:1)

在EF6中,您可以将ReservationClass配置为ComplexType,忽略DisplayName属性并映射Value属性。

不幸的是,根据these design meeting notes

  

在EF7的初始RTM中,我们计划启用复杂和/或类型。

换句话说,你不能在当前的EF Core中这样做。

答案 1 :(得分:1)

对于使用 EF Core 遇到此引用广泛的线程的人,我通常使用类型转换将按其值(即标识符)存储的自定义类型枚举存储在数据库中。可以在方法OnModelCreating(或实现IEntityTypeConfiguration<T>的类)中使用此扩展方法:

internal static class EnumerationConfiguration
{
    public static void OwnEnumeration<TEntity, TEnum>(this EntityTypeBuilder<TEntity> builder,
        Expression<Func<TEntity, TEnum>> property)
        where TEntity : class
        where TEnum : Enumeration
    {
        builder
            .Property(property)
            .HasConversion(x => x.Id, x => Enumeration.FromId<TEnum>(x));
    }
}

然后,可以如下配置枚举属性:

internal class SpecimenConfiguration : IEntityTypeConfiguration<Specimen>
{
    public void Configure(EntityTypeBuilder<Specimen> builder)
    {
        builder.OwnEnumeration(x => x.Type);
    }
}

此方法的好处在于,它仅存储标识符(而不存储附加到Enumeration的给定派生类的其他属性),并支持Enumeration的子类。

缺点是大量使用通过Enumeration.FromId<TEnum>(x)进行反思。可以通过在此方法中引入缓存来摊销此费用,Jimmy Bogard的链接文章未提供此内容。

答案 2 :(得分:0)

对于使用EF Core 3.1的用户,有更好的方法。目标是要有一个列出枚举的数据库表。

(1)定义枚举表的外观:

public virtual DbSet<ReservationStatus> ReservationStatuses { get; set; }
 
public void Configure(EntityTypeBuilder<ReservationStatus> builder)
{
    builder.HasKey(x => x.Id);
    builder.Property(x => x.Id).HasDefaultValue(1).ValueGeneratedNever().IsRequired();
    builder.Property(x => x.Name).IsRequired();
}

(2)定义值在预留实体中的关系

 public void Configure(EntityTypeBuilder<Reservation> builder)
 {
     builder.Property(x => x.ReservationStatusId).IsRequired();
     builder.HasOne(x => x.ReservationStatus)
         .WithMany()
         .HasForeignKey(x => x.ReservationStatusId);
 }

(3)播种枚举表

if (!await RevervationSatuses.AnyAsync())
{
    RevervationSatuses.AddRange(Enumeration.GetAll<RevervationSatus>());
    await SaveChangesAsync();
}