T4 Template for DBML Metadata
之前曾經自己用xslt去套了DB的Xml之後產出Metadata,這次因為要給外包商使用,所以想說來套套看T4,就花了一早上在看…其實用起來跟xslt原理差不多(原本還以為有什麼特別的,結果Demo大回我一句:「產生器你還期待他能怎樣?飛嗎」),只不過語法不同,然後功能比較多(畢竟很多可以用程式寫嘛?)。
今天的目標是要利用dbml來產出MVC專案要用的Metadata,不過我之前沒有寫過T4,所以很想偷懶找別人寫過的來改…當然就是先到codeplex上面找一下…然後就發現寶了:LINQ to SQL templates for T4
雖然他是用來產db class的,不過有範本接下來就簡單多了,以下是我調整完的範本,預設是每個類別產一個檔案出來:
<#@ include file="L2ST4.ttinclude"#>
<#@ output extension=".cs"#>
<# // Template by Eric Phan http://ericphan.info inspired by Damien Guard http://damieng.com
var options = new {
DbmlFileName = Host.TemplateFile.Replace(".tt",".dbml"), // Which DBML file to operate on (same filename as template)
SerializeDataContractSP1 = false, // Emit SP1 DataContract serializer attributes
FilePerEntity = true, // Put each class into a separate file
StoredProcedureConcurrency = false, // Table updates via an SP require @@rowcount to be returned to enable concurrency
};
var code = new CSharpCodeLanguage();
var data = new Data(options.DbmlFileName);
var manager = Manager.Create(Host, GenerationEnvironment);
data.ContextNamespace = (new string[] { manager.GetCustomToolNamespace(data.DbmlFileName), data.SpecifiedContextNamespace, manager.DefaultProjectNamespace }).FirstOrDefault(s => !String.IsNullOrEmpty(s));
data.EntityNamespace = (new string[] { manager.GetCustomToolNamespace(data.DbmlFileName), data.SpecifiedEntityNamespace, manager.DefaultProjectNamespace }).FirstOrDefault(s => !String.IsNullOrEmpty(s));
manager.StartHeader();
#>
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Generated at <#=DateTime.Now#>
// Runtime Version:<#=Environment.Version#>
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.ComponentModel;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.ComponentModel.DataAnnotations;
namespace <#=data.EntityNamespace#>
{
<#
manager.EndBlock();
foreach(Table table in data.Tables) {
foreach(TableClass class1 in table.Classes) {
manager.StartNewFile(Path.ChangeExtension(class1.Name,".generated.cs"));
#>
[MetadataType(typeof(<#=class1.Name#>MetaData))]
public partial class <#=class1.Name#>
{
private class <#=class1.Name#>MetaData
{
<#
if (class1.Columns.Count > 0)
foreach(Column column in class1.Columns)
{
if(column.DbType.Contains("Char") && !column.DbType.Contains("MAX"))
{
int start = column.DbType.IndexOf("(") + 1;
int end = column.DbType.IndexOf(")");
string len = column.DbType.Substring(start, end - start);
#>
[StringLength(<#=len#>, ErrorMessage = "請勿輸入超過 <#=len#> 個字")]
<#}
if (!column.CanBeNull) { #>
[Required(ErrorMessage = "")]
<#}#>
[DisplayName("<#=column.Member#>")]
public <#=code.Format(column.Type)#> <#=column.Member#> { get; set; }
<#}#>
}
partial void OnValidate(System.Data.Linq.ChangeAction action)
{
}
}
}
<#}}#>
#pragma warning restore 1591<#
manager.EndBlock();
manager.Process(options.FilePerEntity);#>
使用方法:
1.先從CodePlex下載l2st4專案,裡面有一個L2ST4.ttinclude,我們只需要這個檔案。
2.建立一個新的metadata.tt,程式碼如上。
3.二個檔案放在同一層的資料夾,修改metadata.tt中的DbmlFileName = Host.TemplateFile.Replace("MetaData.tt","你的檔案名稱.dbml")
不過可惜的是因為dbml裡面沒有欄位的Description,所以不能直接產生DisplayName,edml的倒是比較多可以利用的資料~
檔案下載:metadata.zip
Dotblogs 的標籤:T4
相關連結: