首頁

2013年9月1日 星期日

**在[.NET]透過--T4--產生對應>>DB table 的entity=我們可以利用code**藉由T4產生多個資料物件喔~!^

!**在[.NET]透過--T4--產生對應>>DB table 的entity=
我們可以利用code**藉由T4產生多個資料物件喔~^

**透過自訂 Attribute 來封裝 entity 與 DB 資料欄位的對應,
以企圖讓 data access layer 回來的資料,都是以 entity 物件的形式,
而非 DataTable 或 DataSet 這類弱型別的結構 .**
*難道每次設計 mapping table 的 entity 都只能手動去刻嗎?感覺好蠢、好浪費時間喔!! *
 以 LINQ to SQL 或 LINQ to EF,都只需要拉一拉 data model,
就可以自動產生對應的entity 集合 ~*
*所以有很多人會自己寫對應的程式碼產生器,甚至許多套件也都有提供類似的功能 **
*是透過內建的 T4 轉換,用最簡單的方式來自動產生我們所需要的 entity class 檔案 !!
**註:有些人可能會說,為什麼不乾脆使用 LINQ to SQL 或 LINQ to EF,但實際上很多現實狀況,是不允許使用的。不管是 .net framework migration 的問題,或是 performance 問題,或是需要在DA層自訂一些客製化的動作時,就不一定可以直接使用 ~**

**T4 的全名是「Text Template Transformation Toolkit」,簡單的說,
就是一個可以轉換的文字範本,在範本裡面可以透過程式碼與邏輯,
來決定要嵌入哪些文字。幾乎現在的 Visual Studio 上 的 code generator --
--底子都是透過 T4 來產生對應的程式碼 ***

範例

需求說明:
  1. 針對某一個DB中,某一張 table
  2. 產生對應的 class 內容
  3. Class 名稱預設與 table 名稱相同
  4. Property 名稱預設與 table column 名稱相同
  5. Property type 預設為 column type 所對應的 data type
  6. 每一個 property 上,要有對應的自訂 attribute,供 RowMapper 使用
  7. 可自行加入 todo 註解,或是相關 using namespace
在任何一個專案底下,新增一個項目,類型為「文字範本」**
**


*接著會出現下面的視窗,其實就是 T4 要幫忙轉換輸出結果的動作,
當按下確定,就會按照 tt 上的範本邏輯產生對應的程式碼。
第一次所產生的程式碼其實是空的,所以按確定跟取消都沒差*



**CODE**藉由T4產生多個資料物件喔~!^**

**需求是有現成的XML資料定義檔如下      **
*
<?xml version="1.0" encoding="utf-8" ?>
<datatable>
  <table id="Running" version="1.0">
    <col name="RunDateTime" datatype="System.DateTime" pkey="Y"/>
    <col name="RunnerId"    datatype="System.String" pkey="Y"/>
    <col name="Record"        datatype="System.String"/>
  </table>
  <table id="Runner" version="1.0">
    <col name="RunnerId"    datatype="System.String" pkey="Y"/>
    <col name="Name"        datatype="System.String" />
    <col name="Birthday"    datatype="System.DateTime" />
  </table>
</datatable>                                             *
 
**希望為其中每個Table各產生一個C#類別轡下:                  **
*
using System.ComponentModel.DataAnnotations;
 
public class Runner
{
    [Key]
    public System.String RunnerId { get; set; }
    public System.String Name { get; set; }
    public System.DateTime Birthday { get; set; }
}                                                           *
 
**在過去,我會自己寫Code,解析XML文件再用StringBuilder組裝C#類別的內容。 
但既然已經學會T4範本程式產生器- 這等好物,自然沒有再走回頭路的道理。
由XML產生C#類別的邏輯很簡單,唯一的小挑戰是一般T4範例多是一個.tt檔產生一個.cs檔,
而這個需求得依照XML定義一次產生多個.cs檔案。
爬文找到範例,單一.tt要輸出多個檔案的原理,是在執行過程---
---由GenerationEnvironment.ToString()取得當時累積的輸出結果,
以File.WriteAllText()寫入檔案後,執行GenerationEnvironment.Clear()清掉---
---已寫到檔案的內容,再執行下個類別的程式碼產生邏輯。
T4程式碼如下:                                          **
    ****
*
<#@ template  debug="true" hostSpecific="true" #>
<#@ output extension=".log" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ Assembly Name="System.Windows.Forms.dll" #>
<#@ Assembly Name="System.Xml.dll" #>
<#@ Assembly Name="System.Xml.Linq.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #> 
<#
    string currPath = Path.GetDirectoryName(Host.TemplateFile);
    XDocument xd = XDocument.Load(Path.Combine(currPath, "marathon.xml"));
    foreach (var t in xd.Root.Elements()) {
        string tableName = t.Attribute("id").Value;
#>
using System.ComponentModel.DataAnnotations;
 
public class <#= tableName #>
{
<#
        foreach (var c in t.Elements()) {
            string name = c.Attribute("name").Value;
            string type = c.Attribute("datatype").Value;
            bool isPK = c.Attribute("pkey") != null;
            if (isPK) {
#>
    [Key]
<#
            }
#>
    public <#= type #> <#= name #> { get; set; }
<#
        }
#>
}
<#
        string relativeOutputFilePath = "Code\\" + tableName + ".cs";
        string outputFilePath = Path.Combine(currPath, relativeOutputFilePath);
        TemplateHelper.WriteTemplateOutputToFile(outputFilePath, GenerationEnvironment);
    }
#>
<#+
//REF: http://bit.ly/X9wTu0
public class TemplateHelper
{
    public static void WriteTemplateOutputToFile(
        string outputFilePath,
        System.Text.StringBuilder genEnvironment)
    {
        System.IO.File.WriteAllText(outputFilePath, genEnvironment.ToString());
        genEnvironment.Clear();
 
    }
}
#> 
 
**補充**
:
  1. 預設T4並未參照System.Xml.dll及System.Xml.Linq.dll,
  2. 記得要在最前方透過<#@ Assembly #>及<#@ import #>加入參照。
  3. 透過Host.TemplateFile可取得T4檔案所在實體路徑,可用來決定輸出檔案路徑。
  4. T4檔末端透過<#+ #>宣告了共用函數TemplateHelper.WriteTemplateOutputToFile(),
  5. 透過其將產生結果寫入檔案 .
                ****
                &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
                &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
                &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

                沒有留言:

                張貼留言


                if you like make fds, wellcome you here~~anytime***

                my free place for everyones who want the good software,

                come & download them~ wellcome!!