所以我不会撒谎,我的解决方案有点深入,但过去几天我一直在使用它,我发现它完全符合我的需要。
让我们从顶部开始,我创建的基类:
public abstract class LookupTableBase
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
这是我的一个查找表实体模型的示例:
/// <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 {}
这是与此查找表一起使用的枚举:
public enum AddressTypes
{
[StringValue("")]
Unknown = 0,
[StringValue("Home")]
Home = 1,
[StringValue("Mailing")]
Mailing = 2,
[StringValue("Business")]
Business = 3
}
StringValue 属性是我创建的一个自定义属性(基于我在网上找到的示例),它允许我调用:
AddressTypes.Home.GetStringValue();
这将返回字符串值:Home。
我将查找实体模型添加到我的 DbSet 中,以便创建表,但我从未在我的任何其他实体模型中直接引用查找实体模型。它的唯一目的是在数据库中创建查找表,以便我可以针对它们创建外键约束。
public DbSet<AddressType> AddressTypes { get; set; }
在我的上下文的 OnModelCreating 方法中,我确实必须添加这个,因为数据注释似乎没有一直保持:
modelBuilder.Entity<AddressType>()
.Property(x => x.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
在我的迁移配置文件中,我将其添加到种子方法中:
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();
最后,在迁移文件本身中,我将所有查找表创建方法移到列表顶部,现在我可以将外键约束添加到引用该枚举的任何表中。就我而言,我更进一步。由于迁移类是部分类,因此我创建了另一个部分类来匹配它。创建了两个方法:
public void LookupDataUp()
public void LookupDataDown()
在 LookupDataUp 方法中,我添加了所有自定义外键和索引,在 LookupDataDown 中,我删除了所有自定义外键和索引。
当我运行 Update-Database 时,我的所有表过去都有一些表示某些东西的整数值(在本例中为 AddressType)但没有实际值,现在有一个值可以通过将其链接到其查找来查看表。
我承认,这似乎需要大量工作才能将少量数据放入数据库,但现在每次我删除/更改/添加新项目到我的枚举时,它都会自动推送到数据库。另外,正如我在上述问题中所述,这通过在“整数”字段上设置外键约束来创建数据库完整性。