Entity framework 实体框架5-从数据库中存储的值动态生成枚举
因此,我的数据库中有一个现有的查找表,它存储一个ID列(int),ID值的描述/名称。我们一直在使用此表中的数据进行枚举。 此后,我们开始使用EntityFramework5和CodeFirst,但我们的查找值仍在数据库中。我们想要做的是创建一个实体来表示值,最好是一个枚举来访问该表中的值和名称,并使它们在我们的应用程序中可用 通常,下面的代码对于从数据库值动态构建枚举类型是有意义的,但我们不想这样做Entity framework 实体框架5-从数据库中存储的值动态生成枚举,entity-framework,ef-code-first,enumeration,Entity Framework,Ef Code First,Enumeration,因此,我的数据库中有一个现有的查找表,它存储一个ID列(int),ID值的描述/名称。我们一直在使用此表中的数据进行枚举。 此后,我们开始使用EntityFramework5和CodeFirst,但我们的查找值仍在数据库中。我们想要做的是创建一个实体来表示值,最好是一个枚举来访问该表中的值和名称,并使它们在我们的应用程序中可用 通常,下面的代码对于从数据库值动态构建枚举类型是有意义的,但我们不想这样做 static void GenerateStateEnumerations(String
static void GenerateStateEnumerations(String enumassemblyName, String enumTypeName, String assemblyName, IDictionary<int, String> EnumDB)
{
// Get the current application domain for the current thread.
AppDomain currentDomain = AppDomain.CurrentDomain;
// Create a dynamic assembly in the current application domain,
// and allow it to be executed and saved to disk.
AssemblyName EnumassemblyName = new AssemblyName(enumassemblyName);
AssemblyBuilder ab = currentDomain.DefineDynamicAssembly(
EnumassemblyName, AssemblyBuilderAccess.RunAndSave);
// Define a dynamic module in assemblyName assembly. For a single-
// module assembly, the module has the same name as the assembly.
ModuleBuilder mb = ab.DefineDynamicModule(EnumassemblyName.Name, EnumassemblyName.Name + ".dll");
// Define a public enumeration with the name "Elevation" and an
// underlying type of Integer.
EnumBuilder eb = mb.DefineEnum(enumTypeName, TypeAttributes.Public, typeof(int));
// Define the enumeration members
foreach (KeyValuePair<int, String> element in EnumDB)
{
eb.DefineLiteral(element.Value, element.Key);
}
// Create the type and save the assembly.
Type finished = eb.CreateType();
//Save the assembly via the assembly builder
ab.Save(EnumassemblyName.Name + ".dll");
}
static void generateStateNumerations(字符串enumassemblyName、字符串enumTypeName、字符串assemblyName、IDictionary EnumDB)
{
//获取当前线程的当前应用程序域。
AppDomain currentDomain=AppDomain.currentDomain;
//在当前应用程序域中创建动态程序集,
//并允许将其执行并保存到磁盘。
AssemblyName EnumassemblyName=新的AssemblyName(EnumassemblyName);
AssemblyBuilder ab=currentDomain.DefinedDynamicAssembly(
EnumassemblyName、AssemblyBuilderAccess.RunAndSave);
//在assemblyName assembly中定义动态模块。对于单个-
//模块程序集,模块与程序集具有相同的名称。
ModuleBuilder mb=ab.DefinedDynamicModule(EnumassemblyName.Name,EnumassemblyName.Name+“.dll”);
//定义一个名为“高程”的公共枚举和
//整数的基础类型。
EnumBuilder eb=mb.DefineEnum(enumTypeName,TypeAttributes.Public,typeof(int));
//定义枚举成员
foreach(EnumDB中的KeyValuePair元素)
{
eb.DefineLiteral(element.Value,element.Key);
}
//创建类型并保存程序集。
类型finished=eb.CreateType();
//通过部件生成器保存部件
ab.Save(EnumassemblyName.Name+“.dll”);
}
在EF 5中,如何创建一个枚举实体来表示存储在此表中的数据?目前是否可能 我知道您说过不想动态执行此操作,但您是否考虑过使用文本模板?如果使用文本模板(*.tt T4文件),则每次生成时都会动态生成枚举。表中的任何新值都将自动添加到代码中的枚举中 下面是一个如何从文本模板创建枚举的示例:
<#@ template language="C#" hostSpecific="true" #>
<#@ output extension=".generated.cs" #>
<#@ Assembly Name="C:\Program Files (x86)\Common Files\microsoft shared\MSEnv\PublicAssemblies\EnvDTE.dll" #>
<#@ Assembly Name="System.Data" #>
<#@ assembly name="System.Configuration.dll" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Configuration" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
// This file dynamically creates Enumerations to be used in the [your project name] project.
// get an appSetting value
//string myAppSetting = AppSettings["myAppSetting"].Value;
// use a helper method to get value or default
// string absentAppSetting = (string)AppSettingValueOrDefault("xxx","default value for absent setting");
// get a project property
//string rootNamespace = Project.Properties.Item("RootNamespace").Value.ToString();
ConnectionStringSettings cs = ConnectionStrings["MyDBName"];
string tableName = "dbo.MyEnumTable"; // Path.GetFileNameWithoutExtension(Host.TemplateFile);
string path = Path.GetDirectoryName(Host.TemplateFile);
string columnId = "MyEnumTableId";
string columnName = "MyEnumTableValue";
string connectionString = cs.ConnectionString;
// Get containing project
IServiceProvider serviceProvider = (IServiceProvider)Host;
DTE dte = (DTE)serviceProvider.GetService(typeof(DTE));
Project project = dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject;
# > //remove space between # > issue with SO formatting
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
namespace <#= project.Properties.Item("DefaultNamespace").Value #>
{
/// <summary>
/// Auto generated enumeration from database table <#= tableName #>
/// </summary>
[GeneratedCode("TextTemplatingFileGenerator", "10")]
public enum MyEnumTableEnum
{
<#
SqlConnection conn = new SqlConnection(connectionString);
string command = string.Empty;
command = string.Format("select tbl.{0}, tbl.{1} from {2} as tbl order by tbl.{0}", columnId, columnName, tableName);
SqlCommand comm = new SqlCommand(command, conn);
conn.Open();
SqlDataReader reader = comm.ExecuteReader();
bool loop = reader.Read();
while(loop)
{
# > //remove space between # > issue with SO formatting
/// <summary>
/// <#= reader[columnName] #> configuration setting.
/// </summary>
<#= Pascalize(reader[columnName]) #> = <#= reader[columnId] #><# loop = reader.Read(); #><#= loop ? ",\r\n" : string.Empty #>
<#
}
#>
}
/// <summary>
/// This auto generated class is used to get or set the MyEnumTableEnum user friendly display names.
/// The 'values' object is of type Dictionary<int, string>
/// Usage: string keyValue = MyEnumTableDict.values[int key];
/// </summary>
public class MyEnumTableDict
{
public static Dictionary<int, string> values = new Dictionary<int, string>();
static MyEnumTableDict()
{
<#
reader.Close();
reader = comm.ExecuteReader();
loop = reader.Read();
while(loop)
{
#>
values[<#= reader[columnId] #>] = "<#= reader[columnName] #>";<#= "\r\n" #><# loop = reader.Read(); #>
<#
}
reader.Close();
reader.Dispose();
#>
}
}
}
<#+
/// <summary>
/// Used to Pascal-case objects
/// </summary>
private string Pascalize(object value)
{
Regex rx = new Regex(@"(?:[^a-zA-Z0-9]*)(?<first>[a-zA-Z0-9])(?<reminder>[a-zA-Z0-9]*)(?:[^a-zA-Z0-9]*)");
return rx.Replace(value.ToString(), m => m.Groups["first"].ToString().ToUpper() + m.Groups["reminder"].ToString().ToLower());
}
// Configuration Accessor Helpers
private static System.Configuration.Configuration _config;
private static EnvDTE.Project _project;
/// <summary>
/// Example:
/// <code>
/// string cs = ConnectionStrings["myConnectionString"].ConnectionString;
/// </code>
/// </summary>
private ConnectionStringSettingsCollection ConnectionStrings
{
get { return Configuration.ConnectionStrings.ConnectionStrings;}
}
/// <summary>
/// Example:
/// <code>
/// string setting = AppSettings["mySetting"].Value;
/// </code>
/// </summary>
private KeyValueConfigurationCollection AppSettings
{
get { return Configuration.AppSettings.Settings; }
}
/// <summary>
/// Returns value of setting, if present, otherwise defaultValue
/// </summary>
/// <param name="key">appSettings key</param>
/// <param name="defaultValue">value to return if setting is absent</param>
/// <returns></returns>
private object AppSettingValueOrDefault(string key,object defaultValue)
{
if (AppSettings[key] != null)
{
return AppSettings[key].Value;
}
return defaultValue;
}
/// <summary>
/// The app/web config file for hosting project, if any
/// </summary>
private System.Configuration.Configuration Configuration
{
get
{
if(_config==null)
{
string configurationFilename=null;
// examine each project item's filename looking for app.config or web.config
foreach (EnvDTE.ProjectItem item in Project.ProjectItems)
{
if (Regex.IsMatch(item.Name,"(app|web).config",RegexOptions.IgnoreCase))
{
// TODO: try this with linked files. is the filename pointing to the source?
configurationFilename=item.get_FileNames(0);
break;
}
}
if(!string.IsNullOrEmpty(configurationFilename))
{
// found it, map it and return it
ExeConfigurationFileMap configFile = null;
configFile = new ExeConfigurationFileMap();
configFile.ExeConfigFilename=configurationFilename;
_config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
}
}
return _config;
}
}
/// <summary>
/// The hosting project.
/// </summary>
private EnvDTE.Project Project
{
get
{
if(_project==null)
{
// Get the instance of Visual Studio that is hosting the calling file
EnvDTE.DTE env = (EnvDTE.DTE)((IServiceProvider)this.Host).GetService(typeof(EnvDTE.DTE));
// Gets an array of currently selected projects. Since you are either in this file saving it or
// right-clicking the item in solution explorer to invoke the context menu it stands to reason
// that there is 1 ActiveSolutionProject and that it is the parent of this file....
_project = (EnvDTE.Project)((Array)env.ActiveSolutionProjects).GetValue(0);
}
return _project;
}
}
#>
更新:
忘记包含输出类。现在包括完整性:)
使用系统;
使用System.CodeDom.Compiler;
使用System.Collections.Generic;
名称空间MyNameSpace
{
///
///从数据库表dbo.MyEnumTable自动生成枚举
///
[生成代码(“TextTemplatingFileGenerator”,“10”)]
公共枚举MyEnumTableDictEnum
{
///
///说明1
///
enumName1=1,
///
///说明2
///
enumName2=2,
//……等等。
}
///
///此自动生成的类用于获取或设置MyEnumTableDictEnum
///用户友好的显示名称。
///“values”对象的类型为Dictionary
///用法:string keyValue=MyEnumTableDict.values[int key];
///
公共类MyEnumTableDict
{
公共静态字典值=新字典();
静态MyEnumTableDict()
{
值[1]=“EnumName1”;
值[2]=“EnumName2”;
值[3]=“…等”;
}
}
}
您是否需要一个表示表的实体(即带有键和描述),或者您只需要在任何地方都使用的枚举类型,因此您的模型中甚至不需要该表的实体?枚举是否会发生变化?您是否使用数据库优先的方法?
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
namespace MyNameSpace
{
/// <summary>
/// Auto generated enumeration from database table dbo.MyEnumTable
/// </summary>
[GeneratedCode("TextTemplatingFileGenerator", "10")]
public enum MyEnumTableDictEnum
{
/// <summary>
/// description 1
/// </summary>
enumName1 = 1,
/// <summary>
/// description 2
/// </summary>
enumName2 = 2,
//..etc.
}
/// <summary>
/// This auto generated class is used to get or set the MyEnumTableDictEnum
/// user friendly display names.
/// The 'values' object is of type Dictionary<int, string>
/// Usage: string keyValue = MyEnumTableDict.values[int key];
/// </summary>
public class MyEnumTableDict
{
public static Dictionary<int, string> values = new Dictionary<int, string>();
static MyEnumTableDict()
{
values[1] = "EnumName1";
values[2] = "EnumName2";
values[3] = "...etc.";
}
}
}