T4 Template for DBML Metadata

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 的標籤:

相關連結:

Code Generation and T4 Text Templates

T4 Toolbox

How to create a simple T4 template