我在我的域模型中使用基于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。
答案 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();
}