Jer*_*ose 29 entity-framework ef-code-first entity-framework-5
我想定义一个用于EF5的枚举,以及一个相应的查找表.我知道EF5现在支持枚举,但开箱即用,它似乎只在对象级别支持此功能,并且默认情况下不会为这些查找值添加表格.
例如,我有一个用户实体:
public class User
{
int Id { get; set; }
string Name { get; set; }
UserType UserType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
和UserType枚举:
public enum UserType
{
Member = 1,
Moderator = 2,
Administrator = 3
}
Run Code Online (Sandbox Code Playgroud)
我希望数据库生成创建一个表,如:
create table UserType
(
Id int,
Name nvarchar(max)
)
Run Code Online (Sandbox Code Playgroud)
这可能吗?
Tim*_*ell 21
这是我之前制作的nuget包,它生成查找表并应用外键,并使查找表行保持与枚举同步:
https://www.nuget.org/packages/ef-enum-to-lookup
将其添加到项目中并调用Apply方法.
github上的文档:https://github.com/timabell/ef-enum-to-lookup
Lad*_*nka 17
这不是直接可能的.EF支持与.NET相同级别的枚举,因此枚举值仅命名为integer =>类中的枚举属性始终是数据库中的整数列.如果你想拥有表,你需要在你自己的数据库初始化程序中与外键一起手动创建它,User并用枚举值填充它.
我提出了一些关于用户语音的建议,以允许更复杂的映射.如果您发现它有用,您可以投票赞成该提案.
我写了一个小助手类,它为UserEntities类中指定的枚举创建了一个数据库表.它还在引用枚举的表上创建外键.
所以这里是:
public class EntityHelper
{
public static void Seed(DbContext context)
{
var contextProperties = context.GetType().GetProperties();
List<PropertyInfo> enumSets = contextProperties.Where(p =>IsSubclassOfRawGeneric(typeof(EnumSet<>),p.PropertyType)).ToList();
foreach (var enumType in enumSets)
{
var referencingTpyes = GetReferencingTypes(enumType, contextProperties);
CreateEnumTable(enumType, referencingTpyes, context);
}
}
private static void CreateEnumTable(PropertyInfo enumProperty, List<PropertyInfo> referencingTypes, DbContext context)
{
var enumType = enumProperty.PropertyType.GetGenericArguments()[0];
//create table
var command = string.Format(
"CREATE TABLE {0} ([Id] [int] NOT NULL,[Value] [varchar](50) NOT NULL,CONSTRAINT pk_{0}_Id PRIMARY KEY (Id));", enumType.Name);
context.Database.ExecuteSqlCommand(command);
//insert value
foreach (var enumvalue in Enum.GetValues(enumType))
{
command = string.Format("INSERT INTO {0} VALUES({1},'{2}');", enumType.Name, (int)enumvalue,
enumvalue);
context.Database.ExecuteSqlCommand(command);
}
//foreign keys
foreach (var referencingType in referencingTypes)
{
var tableType = referencingType.PropertyType.GetGenericArguments()[0];
foreach (var propertyInfo in tableType.GetProperties())
{
if (propertyInfo.PropertyType == enumType)
{
var command2 = string.Format("ALTER TABLE {0} WITH CHECK ADD CONSTRAINT [FK_{0}_{1}] FOREIGN KEY({2}) REFERENCES {1}([Id])",
tableType.Name, enumProperty.Name, propertyInfo.Name
);
context.Database.ExecuteSqlCommand(command2);
}
}
}
}
private static List<PropertyInfo> GetReferencingTypes(PropertyInfo enumProperty, IEnumerable<PropertyInfo> contextProperties)
{
var result = new List<PropertyInfo>();
var enumType = enumProperty.PropertyType.GetGenericArguments()[0];
foreach (var contextProperty in contextProperties)
{
if (IsSubclassOfRawGeneric(typeof(DbSet<>), contextProperty.PropertyType))
{
var tableType = contextProperty.PropertyType.GetGenericArguments()[0];
foreach (var propertyInfo in tableType.GetProperties())
{
if (propertyInfo.PropertyType == enumType)
result.Add(contextProperty);
}
}
}
return result;
}
private static bool IsSubclassOfRawGeneric(Type generic, Type toCheck)
{
while (toCheck != null && toCheck != typeof(object))
{
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur)
{
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}
public class EnumSet<T>
{
}
}
Run Code Online (Sandbox Code Playgroud)
使用代码:
public partial class UserEntities : DbContext{
public DbSet<User> User { get; set; }
public EntityHelper.EnumSet<UserType> UserType { get; set; }
public static void CreateDatabase(){
using (var db = new UserEntities()){
db.Database.CreateIfNotExists();
db.Database.Initialize(true);
EntityHelper.Seed(db);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15056 次 |
| 最近记录: |