2011-10-27 61 views
5

我正在尋找一個教程,指導或軟件,可以生成簡單的POCO的一些SQL Server表在ASP.NET MVC中使用。事情是這樣的:簡單的T4代爲簡單的POCO

1)保持在應有POCO的SQL Server數據庫中的表名的列表產生

2)訂閱列表中某些程序

3)程序生成簡單的POCO(更像是DTO)在一個.cs文件中,或附加到Poco.cs.無論哪種方式,這並不重要。

例如:

public class MyDto 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public bool? IsMale {get; set;} 
} 

4)運行程序時,我想重新生成POCO的

程序可能是WinForm的,命令行,或別的東西。沒關係。

回答

8

我一直想回答這個問題,但一直佔線。

我已經創建了一個關於如何讀取數據庫模式並從中生成類和屬性的簡單示例。

基本上你應該可以將它粘貼到TT文件中(參見Oleg Sychs blog關於如何入門),更新連接字符串並保存以執行模板。

我並不認爲這是一個完整的樣本,但它可以作爲一個起點你:

<#@ template language = "C#"       #> 
    <#@ assembly name  = "Microsoft.CSharp"    #> 
    <#@ assembly name  = "System.Core"     #> 
    <#@ assembly name  = "System.Data"     #> 
    <#@ import  namespace = "System.Collections.Generic" #> 
    <#@ import  namespace = "System.Dynamic"    #> 
    <#@ import  namespace = "System.Linq"     #> 
    <#@ import  namespace = "System.Data.SqlClient"  #> 

    <# 
    var namespaceName = "Poco2"; 
    // Update the connection string to something appropriate 
    var connectionString = @"Data Source=localhost\SQLExpress;Initial Catalog=MyTest;Integrated Security=True"; 
    #> 

    <# 
    using (var db = new SqlConnection (connectionString)) 
    using (var cmd = db.CreateCommand()) 
    { 
     db.Open(); 
     var tables    = ReadRows (cmd, "SELECT * FROM sys.tables").ToArray(); 

     var columns    = ReadRows (cmd, "SELECT * FROM sys.columns").ToLookup (k => k.object_id); 

     var indexes    = ReadRows (cmd, "SELECT * FROM sys.indexes").ToLookup (k => k.object_id); 
     var indexColumns  = ReadRows (cmd, "SELECT * FROM sys.index_columns").ToLookup (k => k.object_id); 

     var foreignKeys   = ReadRows (cmd, "SELECT * FROM sys.foreign_keys").ToArray(); 
     var foreignKeyColumns = ReadRows (cmd, "SELECT * FROM sys.foreign_key_columns").ToArray(); 
    #> 
    namespace <#=namespaceName#> 
    { 
    using System; 
    using System.Data.Linq.Mapping; 

    <# 
     foreach (var table in tables) 
     {   
    #> 
    [Table] 
    partial class <#=table.name#> 
    { 
    <# 
      IEnumerable<dynamic> tc = columns[table.object_id]; 
      var tableColumns = tc.OrderBy (r => r.column_id).ToArray();   

      IEnumerable<dynamic> ti = indexes[table.object_id]; 
      var tableIndexes = ti.ToArray();   

      var primaryKeyIndex = tableIndexes.FirstOrDefault (i => i.is_primary_key); 
      var primaryKeyColumns = new Dictionary<dynamic, dynamic>(); 
      if (primaryKeyIndex != null) 
      { 
       IEnumerable<dynamic> pc = indexColumns[table.object_id]; 
       primaryKeyColumns = pc 
       .Where (c => c.index_id == primaryKeyIndex.index_id) 
       .ToDictionary (c => c.column_id, c => c.key_ordinal) 
       ; 
      } 

      foreach (var tableColumn in tableColumns) 
      { 
       var type = MapToType (tableColumn.user_type_id, tableColumn.max_length, tableColumn.is_nullable); 

    #> 
     [Column (IsPrimaryKey = <#=primaryKeyColumns.ContainsKey (tableColumn.column_id) ? "true" : "false"#>)] 
     public <#=type#> <#=tableColumn.name#> {get;set;} 

    <# 
      } 
    #> 

    } 
    <# 
     } 
    #> 
    } 
    <# 
    } 
    #> 

    <#+ 

    struct DataType 
    {  
     public readonly int  SizeOf; 
     public readonly string SingularType; 
     public readonly string PluralType; 

     public DataType (
      int sizeOf, 
      string singularType, 
      string pluralType = null 
      ) 
     { 
      SizeOf   = sizeOf; 
      SingularType = singularType; 
      PluralType  = pluralType ?? (singularType + "[]"); 
     } 

    } 
    static Dictionary<int, DataType> dataTypes = new Dictionary<int, DataType> 
     { 
      {61 , new DataType (8, "DateTime"   )}, 
      {127 , new DataType (8, "long"    )}, 
      {165 , new DataType (1, "byte"    )}, 
      {231 , new DataType (2, "char" , "string")}, 
     }; 

    static string MapToType (int typeId, int maxLength, bool isNullable) 
    { 
     DataType dataType; 

     if (dataTypes.TryGetValue (typeId, out dataType)) 
     { 
      var length = maxLength > 0 ? (maxLength/dataType.SizeOf) : int.MaxValue; 
      if (length > 1) 
      { 
       return dataType.PluralType; 
      } 
      else 
      { 
       return dataType.SingularType + (isNullable ? "?" : ""); 
      } 
     } 
     else 
     { 
      return "UnknownType_"+ typeId; 
     } 
    } 

    static IEnumerable<dynamic> ReadRows (SqlCommand command, string sql) 
    { 
     command.CommandText = sql ?? ""; 

     using (var reader = command.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       var dyn = new ExpandoObject(); 
       IDictionary<string, object> dic = dyn; 

       for (var iter = 0; iter < reader.FieldCount; ++iter) 
       { 
        dic[reader.GetName(iter) ?? ""] = reader.GetValue(iter); 
       } 

       yield return dyn; 
      } 

     } 
    } 


    #> 
+1

我添加了我需要的缺失數據類型後爲我工作。謝謝。 – kampsj

2

大約一年前,我建立了一個類似的自定義生成工具,我沒有找到一個統一的,全面的資源來完成這個目標。

Oleg Sych在his blog上提供了大量有關使用T4的博客文章,並且維護一個庫來幫助T4代,T4 Toolbox。我在開發過程中嚴重依賴兩者。

對於T4模板中的數據庫模式發現,我使用了SQL Server Management Objects

我在Visual Studio中運行我的T4模板。

0

您可以在亞音速3(在Visual Studio中運行)中使用classes.tt模板(在linqtemplates中,加上SQLServer.ttinclude)。 http://subsonicproject.com/ 生成的屬性具有支持變量和一些額外的行以支持INotifyPropertyChanging和INotifyPropertyChanged,但您可以編輯模板以取出這些行。

下面是示例輸出和模板:

public partial class Order 
{ 
    public int OrderID { get; set; } 
    public string CustomerID { get; set; } 
    public int? EmployeeID { get; set; } 
    public DateTime? OrderDate { get; set; } 
    public DateTime? RequiredDate { get; set; } 
    public DateTime? ShippedDate { get; set; } 
    public int? ShipVia { get; set; } 
    public decimal? Freight { get; set; } 
    public string ShipName { get; set; } 
    public string ShipAddress { get; set; } 
    public string ShipCity { get; set; } 
    public string ShipRegion { get; set; } 
    public string ShipPostalCode { get; set; } 
    public string ShipCountry { get; set; } 
} 


<#@ template language="C#" debug="False" hostspecific="True" #> 
<#@ output extension=".cs" #> 
<#@ include file="SQLServer.ttinclude" #> 
<# 
    var tables = LoadTables(); 
#> 
using System; 
using System.ComponentModel; 
using System.Linq; 

namespace <#=Namespace#> 
{ 


<# foreach(Table tbl in tables){#>  

    /// <summary> 
    /// A class which represents the <#=tbl.Name#> table in the <#=DatabaseName#> Database. 
    /// This class is queryable through <#=DatabaseName#>DB.<#=tbl.ClassName#> 
    /// </summary> 

    public partial class <#=tbl.ClassName#> 
    { 
     #region Properties 

<#  foreach(var col in tbl.Columns){ 
      if (tbl.ClassName == col.CleanName) 
      { 
       col.CleanName += "X"; 
      } 
#> 
     public <#=col.SysType#><#=CheckNullable(col)#> <#=col.CleanName#> { get; set; } 
<#  }#> 

     #endregion 

    } 

<#}#> 
} 
0

St4bby在github上。開源。 T4。很容易閱讀和操作,如你所願。