代码优先枚举放入查找表 [英] Code First Enumerations put into Lookup Tables

查看:115
本文介绍了代码优先枚举放入查找表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在很多商店里工作过,他们运行数据库第一模型,因此总是需要查找表。您的查找表必须匹配您的枚举,以保持数据库的完整性。我100%同意这个想法,但是发现,当涉及到Code First Model时,这是不可用的。我读过某个地方,EF团队可能会增加在EF7中将Enums添加到您的DB(通过迁移)的能力,但他们警告说这不是一个承诺。





我正在使用EF 6.1.3和.NET 4.5.1

解决方案

所以我不会说谎,我的解决方案有点深入,但是我过去几天一直在使用它我发现它的工作原理与我需要的一样。



我从顶端开始,我创建的基础类:

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

[必需]
public string Name {get;组; }
}

这是一个查找表实体模型之一的示例: p>

  ///< summary> 
///枚举地址类型查找表
///文件参考:DataAccessLayer /枚举/ Locators.cs
///不要使用
///不可用IN ENTITY MODELS
///< / summary>
[Table(AddressTypes,Schema =Lookup)]
public class AddressType:LookupTableBase {}

这是查找表中的枚举:

  public enum AddressTypes 
{
[StringValue()]
未知= 0,

[StringValue(Home)]
Home = 1,

[StringValue(Mailing)]
Mailing = 2,

[StringValue(Business)]
Business = 3
}

StringValue属性是我创建的一个自定义属性(根据我在线查找的示例),允许我调用: p>

  AddressTypes.Home.GetStringValue(); 

哪个将返回字符串值:首页



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

  public DbSet< AddressType> ; AddressTypes {get;组; } 

在我的上下文的OnModelCreating方法中,我没有添加,因为数据注释没有似乎一直保持下去:

  modelBuilder.Entity< AddressType>()
.Property(x => ; x.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

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

  var addressTypeCount = Enum.GetValues(typeof(AddressTypes))。 
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中删除所有我的自定义外键和索引。 / p>

当我运行更新数据库时,我所有的表都有一些整数值,表示一些东西(在这种情况下是一个AddressType),但没有真正的价值,现在有一个值可以通过将其链接到查找表中看到。



我会承认,这似乎是很多工作只是为了获得少量的数据到数据库但现在每次我删除/更改/添加新项目到我的枚举,它会被自动推送到数据库。正如我在上述问题中所说明的,通过在整数字段上限制外键来创建数据库的完整性。


I have worked in a lot of shops where they ran a Database First Model so Lookup Tables were always required. Your lookup table had to match your Enums so that you kept database integrity. I 100% agree with this idea, but have found that when it comes to the Code First Model, this is not available out of the box. I did read somewhere that the EF Team may be adding the ability to dynamically have Enums added to your DB (via migrations) in EF7 but they warned that it's not a promise.

So how do you (if at all) accomplish this? I am going to provide my solution below in an answer and look forward to your feedback.

I am using EF 6.1.3 and .NET 4.5.1

解决方案

So I am not going to lie, my solution is a bit in-depth but I have been using it now for the past few days and I find it works exactly as I need it to.

Let's start at the top, my base class I created:

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

    [Required]
    public string Name { get; set; }
}

Here is an example of one of my lookup table Entity Models:

/// <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 {}

Here is the Enum that goes with this Lookup Table:

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

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

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

    [StringValue("Business")]
    Business = 3
}

The StringValue Attribute is a custom attribute I created (based on examples I found online) that allow me to call:

AddressTypes.Home.GetStringValue();

Which will return the string value: Home.

I add the Lookup Entity Model to my DbSets so the table will be created but I never directly reference the Lookup Entity Models in any of my other Entity Models. Its sole purpose is to create lookup tables in the DB so that I can create Foreign Key Constraints against them.

public DbSet<AddressType> AddressTypes { get; set; }

In my OnModelCreating Method for my Context, I did have to add this because the Data Annotation did not seem to hold all the way through:

modelBuilder.Entity<AddressType>()
            .Property(x => x.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

In my Migration's Configuration file, I add this into the Seed Method:

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();

Last, in the Migration file itself I move all the lookup table creation methods to the top of the list, now I can add Foreign Key Constraints to any table that references that enum. In my case, I took it one step further. Since the Migration Class is a partial, I created another partial class to match it. Created two methods:

public void LookupDataUp()
public void LookupDataDown()

In the LookupDataUp method, I add all my custom Foreign Keys and Indexes and in the LookupDataDown I Remove all my custom Foreign Keys and Indexes.

When I run Update-Database, all my tables that used to have some integer value that represented something (in this case an AddressType) but had no real value, now have a value that can be seen by linking it to its lookup table.

I will admit, this seems like a lot of work just to get some small amount of data into the database but now every time I remove/change/add new items to my enum, it's automatically pushed to the DB. Plus as I stated in the above question, this creates database integrity by having the foreign key constraint on the 'integer' field.

这篇关于代码优先枚举放入查找表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆