Code First Enumerations放入查找表

Jas*_*n H 5 c# enums entity-framework

我曾在很多商店工作,他们运行数据库优先模型,因此总是需要查找表.您的查找表必须与您的枚举匹配,以便保持数据库的完整性.我100%同意这个想法,但已经发现,当涉及到Code First Model时,这不是开箱即用的.我确实在某处读过EF团队可能会添加在EF7中动态地将Enums添加到您的数据库(通过迁移)的功能,但他们警告说这不是承诺.

那么你(如果有的话)如何实现这一目标呢?我将在下面的答案中提供我的解决方案,并期待您的反馈.

我使用的是EF 6.1.3和.NET 4.5.1

Jas*_*n H 5

所以我不会撒谎,我的解决方案有点深入,但我过去几天一直在使用它,我发现它的工作方式正如我所需要的那样.

让我们从顶部开始,我创建的基类:

public abstract class LookupTableBase
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这是我的一个查找表实体模型的示例:

/// <summary>
///     Lookup Table for Enumeration AddressTypes
///     File Reference: DataAccessLayer/Enumerations/Locators.cs
///     DO NOT USE
///     SHOULD NOT BE AVAILABLE IN ENTITY MODELS
/// </summary>
[Table("AddressTypes", Schema = "Lookup")]
public class AddressType : LookupTableBase {}
Run Code Online (Sandbox Code Playgroud)

以下是与此查找表一起使用的枚举:

public enum AddressTypes
{
    [StringValue("")]
    Unknown = 0,

    [StringValue("Home")]
    Home = 1,

    [StringValue("Mailing")]
    Mailing = 2,

    [StringValue("Business")]
    Business = 3
}
Run Code Online (Sandbox Code Playgroud)

StringValue属性是我创建的自定义属性(基于我在网上找到的示例),允许我调用:

AddressTypes.Home.GetStringValue();
Run Code Online (Sandbox Code Playgroud)

这将返回字符串值:Home.

我将查找实体模型添加到我的DbSets中,因此将创建表,但我从未在任何其他实体模型中直接引用查找实体模型.它的唯一目的是在DB中创建查找表,以便我可以针对它们创建外键约束.

public DbSet<AddressType> AddressTypes { get; set; }
Run Code Online (Sandbox Code Playgroud)

在我的Context的OnModelCreating方法中,我确实必须添加它,因为Data Annotation似乎没有完全保留:

modelBuilder.Entity<AddressType>()
            .Property(x => x.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
Run Code Online (Sandbox Code Playgroud)

在我的Migration的配置文件中,我将其添加到种子方法中:

var addressTypeCount = Enum.GetValues(typeof (AddressTypes)).Length;
var addressTypes = new List<AddressType>();
for (var i = 1; i < addressTypeCount; i++) {
    addressTypes.Add(new AddressType {
                                         Id = i,
                                         Name = ((AddressTypes)i).GetStringValue()
                                     });
}
context.AddressTypes.AddOrUpdate(c => c.Id, addressTypes.ToArray());
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

最后,在Migration文件本身中,我将所有查找表创建方法移到列表顶部,现在我可以将外键约束添加到引用该枚举的任何表中.就我而言,我更进了一步.由于Migration Class是部分的,我创建了另一个部分类来匹配它.创建了两种方法:

public void LookupDataUp()
public void LookupDataDown()
Run Code Online (Sandbox Code Playgroud)

在LookupDataUp方法中,我添加了所有自定义外键和索引,并在LookupDataDown中删除了所有自定义外键和索引.

当我运行Update-Database时,我以前的所有表都有一些表示某些东西的整数值(在这种情况下是一个AddressType)但没有实际值,现在有一个值可以通过将它链接到它的查找表来看到.

我承认,这似乎只是为了将少量数据存入数据库,但现在每次我删除/更改/添加新项目到我的枚举时,它都会自动推送到数据库.正如我在上面的问题中所述,这通过在"整数"字段上具有外键约束来创建数据库完整性.