<分区>
我正在寻找可以为一些 SQL Server 表生成简单 POCO 以在 ASP.NET MVC 中使用的教程、指南或软件。像这样:
1) 保留 SQL Server 数据库中应该生成 POCO 的表名列表
2) 将列表提供给某个程序
3) 该程序在单个 .cs 文件中生成一个简单的 POCO(更像 DTO),或附加到 Poco.cs。无论哪种方式,都没有关系。
例如:
public class MyDto
{
public int Id { get; set; }
public string Name { get; set; }
public bool? IsMale {get; set;}
}
4) 每当我想重新生成 POCO 时运行程序
该程序可以是 WinForm、命令行或其他程序。没关系。
我一直想回答这个问题,但一直很忙。
我创建了一个关于如何读取数据库模式并从中生成类和属性的简单示例。
基本上,您应该能够将其剪切并粘贴到 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;
}
}
}
#>