2011-10-27 15 views
5

ASP.NET MVC'de kullanılmak üzere bazı SQL Server tabloları için basit POCO'lar üretebilen bir öğretici, yönlendirme veya yazılım arıyorum. Böyle bir şey:Basit POCO için Basit T4 jenerasyonu

1) POCO olmalıdır SQL Server veritabanındaki tablo adlarının bir listesini tutun bazı programa

3) programı oluşturur listeyi Yem) oluşturulan Tek bir .cs dosyasında basit POCO (daha fazla DTO gibi) veya Poco.cs'a ekler. Her iki durumda da önemli değil. Örneğin

:

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

4) Ben WinForm, komut satırı, ya da başka bir şey olabilir Poco en

programını yeniden oluşturmak istediğinizde programı çalıştırın. Fark etmez.

cevap

8

:

Burada örnek çıkışı ve şablondur.

Veritabanı şemasının nasıl okunacağına ve bunlardan sınıf ve özelliklerin nasıl oluşturulacağına dair basit bir örnek oluşturdum.

Temel olarak, (Başlamak için nasıl Oleg Sychs blog bakınız) TT dosyasına bu cutnpaste bağlantı dizesini güncelleştirmek ve şablonu yürütmek için kaydetmek gerekir.

Bu tam bir örnek olduğunu iddia etmiyorum ama bu sizin için bir başlangıç ​​noktası olarak hizmet verebilir: github de

<#@ 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

Gerekli olan eksik veri türlerini ekledikten sonra bana çalıştım. Teşekkürler. – kampsj

2

1 yıl önce benzer bir özel üretim aracı oluşturdum ve bu hedefe ulaşmak için birleştirilmiş, kapsamlı bir kaynak bulamadım.

Oleg Sych, his blog numaralı telefondan T4 kullanımı hakkında bir dizi blog yazısı sağlar ve T4 nesli, T4 Toolbox ile ilgili yardım için bir kitaplık sağlar. Gelişim sırasında yoğun olarak güvendim.

T4 şablonlarında veritabanı şeması bulma işlemi için SQL Server Management Objects kullanılır.

T4 şablonlarını Visual Studio'dan çalıştırıyorum.

0

Subsonic 3'teki classes.tt şablonunu (linqtemplates, artı SQLServer.ttinclude) kullanabilirsiniz (görsel stüdyoda çalışır). http://subsonicproject.com/ Oluşturulan özellikler, backing değişkenlerine ve INotifyPropertyChanging ve INotifyPropertyChanged öğelerini desteklemek için bazı ek satırlara sahiptir, ancak bu satırları çıkarmak için şablonu düzenleyebilirsiniz. Bunu cevaplamak istedim ama yoğun olmuştur

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. Açık kaynak. T4. Dilediğiniz kadar okumak ve manipüle etmek kolay.