Linq to sql 生成枚举的T4模板
我正在考虑创建一个T4模板来生成数据库的枚举。 本质上,我想要与亚音速相同的功能,例如Linq to SQL或实体框架4的Product.Columns.ProductId 任何帮助都将不胜感激。Linq to sql 生成枚举的T4模板,linq-to-sql,t4,Linq To Sql,T4,我正在考虑创建一个T4模板来生成数据库的枚举。 本质上,我想要与亚音速相同的功能,例如Linq to SQL或实体框架4的Product.Columns.ProductId 任何帮助都将不胜感激。 谢谢 我根据自己的需要编写了一个将您选择的查找表转换为枚举的: 将此代码放入EnumGenerator.t文件中: <#@ template debug="true" hostSpecific="true" #> <#@ output extension=".generated.cs
谢谢 我根据自己的需要编写了一个将您选择的查找表转换为枚举的: 将此代码放入EnumGenerator.t文件中:
<#@ template debug="true" hostSpecific="true" #>
<#@ output extension=".generated.cs" #>
<#@ Assembly Name="System.Data" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
string tableName = Path.GetFileNameWithoutExtension(Host.TemplateFile);
string path = Path.GetDirectoryName(Host.TemplateFile);
string columnId = tableName + "ID";
string columnName = "Name";
string connectionString = "data source=.;initial catalog=DBName;integrated security=SSPI";
#>
using System;
using System.CodeDom.Compiler;
namespace Services.<#= GetSubNamespace() #>
{
/// <summary>
/// <#= tableName #> auto generated enumeration
/// </summary>
[GeneratedCode("TextTemplatingFileGenerator", "10")]
public enum <#= tableName #>
{
<#
SqlConnection conn = new SqlConnection(connectionString);
string command = string.Format("select {0}, {1} from {2} order by {0}", columnId, columnName, tableName);
SqlCommand comm = new SqlCommand(command, conn);
conn.Open();
SqlDataReader reader = comm.ExecuteReader();
bool loop = reader.Read();
while(loop)
{
#> /// <summary>
/// <#= reader[columnName] #> configuration setting.
/// </summary>
<#= Pascalize(reader[columnName]) #> = <#= reader[columnId] #><# loop = reader.Read(); #><#= loop ? ",\r\n" : string.Empty #>
<#
}
#> }
}
<#+
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());
}
private string GetSubNamespace()
{
Regex rx = new Regex(@"(?:.+Services\s)");
string path = Path.GetDirectoryName(Host.TemplateFile);
return rx.Replace(path, string.Empty).Replace("\\", ".");
}
#>
使用制度;
使用System.CodeDom.Compiler;
命名空间服务。
{
///
///自动生成枚举
///
[生成代码(“TextTemplatingFileGenerator”,“10”)]
公共枚举
{
///
///配置设置。
///
=
}
}
m、 组[“第一”].ToString().ToUpper()+m.Groups[“提醒”].ToString().ToLower());
}
私有字符串GetSubNamespace()
{
正则表达式rx=新正则表达式(@“(?:.+服务\s)”);
字符串路径=path.GetDirectoryName(Host.TemplateFile);
返回rx.Replace(path,string.Empty).Replace(“\\”,”);
}
#>
然后,每当您希望生成枚举时,只需创建一个与数据库表同名的tt文件,如UserType.tt,并将此代码放入:
<#@ include file="..\..\T4 Templates\EnumGenerator.ttinclude" #>
现在,在my.Pascalize的替代实现中提供了更高级的模板:
private static string Pascalize(object value)
{
if (value == null)
return null;
string result = value.ToString();
if (string.IsNullOrWhiteSpace(result))
return null;
result = new String(result.Select(ch => ((ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z') ? ch : ((ch >= 'A' && ch <= 'Z') ? ((char)((int)ch + (int)'a' - (int)'A')) : '-'))).ToArray());
string[] words = result.Split(new [] {'-'}, StringSplitOptions.RemoveEmptyEntries);
words = words.Select(w => ((w[0] >= 'a' && w[0] <= 'z') ? (w.Substring(0, 1).ToUpper() + w.Substring(1)) : w)).ToArray();
result = words.Aggregate((st1, st2) => st1 + st2);
if (result[0] >= '0' && result[0] <= '9')
result = '_' + result;
return result;
}
那太好了。“我本来想自己做这件事,但你帮我省去了麻烦。”大卫·莱弗利:谢谢。我在几个项目中使用过这个,所以我想我也应该与其他人分享。Pascalize似乎不会删除不在{'a'..'z'、'a'..'z'、'0'..'9'}范围内的不需要的字符,例如'\'或'-'。有没有可能修复这一行?@Danny:你能给我一个实际的例子,这样我就可以测试我的RegExp了,它看起来很好。但我可能错了。@Danny:或者最好使用这个
(?:^[a-zA-Z]*)(?[a-zA-Z])(?[a-zA-Z0-9]*)(?:[^a-zA-Z0-9]*$)?
,它适用于您提供的所有案例。尽管我不想支持单字母序列,但在结尾有一个非单词字符的bug。所以我也更新了上面答案中的正则表达式。
int value = Convert.ToInt32(reader[enumTable.ValueId]);
string name = Pascalize(reader[enumTable.ValueName].ToString());
if (string.IsNullOrWhiteSpace(name))
name = "Value" + value;
while (result.Values.Where(v => v.Name == name).SingleOrDefault() != null)
name += '_';