この例は、プロジェクトに切り貼りできるソリューションを意図したものではなく、データベース スキーマからコードを生成するテンプレートを作成する方法の例としてのものです。
コード成果物を生成する方法を示す簡単なテンプレートを作成しました。
ここでプロジェクト全体を見つけることができます: https://github.com/mrange/CodeStack/tree/master/q18787460/ModelGenerator
テンプレート自体は、T4Include.Schema を使用して db スキーマを取得します。SMO も完全に合法的に使用できます。私はパフォーマンスのために T4Include.Schema を好み、SqlConnection のみに依存しています (T4Include.Schema はhttps://www.nuget.org/packages/T4IncludeTemplate/の一部です)。
テンプレートの基本的な戦略は、すべてのテーブルを取得し、それらを反復処理してコード アーティファクトを生成することです。
<#@ include file="$(SolutionDir)\packages\T4IncludeTemplate.1.0.3\T4\Schema.ttinclude"#>
<#
// The namespace surrounding the code
var namespaceName = "ModelGenerator";
var connectionString = @"Data Source=localhost\SQLEXPRESS;Initial Catalog=TestDB;Integrated Security=True";
var schema = GetSchema (connectionString);
Func<string, string> justify = s => LeftJustify (s, 40);
var tables = schema
.SchemaObjects
.Where (so => so.Type == SchemaObject.SchemaObjectType.Table)
.ToArray ()
;
#>
namespace <#=namespaceName#>
{
<#
foreach (var table in tables)
{
#>
/// <summary>
/// Repository interface for <#=table.Name#>
/// </summary>
partial interface I<#=table.Name#>Repository : IRepository<<#=table.Name#>>
{
}
/// <summary>
/// Repository class for <#=table.Name#>
/// </summary>
partial class <#=table.Name#>Repository : RepositoryBase<<#=table.Name#>>, I<#=table.Name#>Repository
{
}
/// <summary>
/// Poco class for <#=table.Name#>
/// </summary>
partial class <#=table.Name#>
{
<#
foreach (var column in table.Columns)
{
#>
public <#=justify (column.CsTypeName)#> <#=justify (column.Name)#>{ get; set; }
<#
}
#>
}
/// <summary>
/// Command class for <#=table.Name#>
/// </summary>
partial class <#=table.Name#>Command : CommandBase, ICommand
{
<#
foreach (var column in table.Columns)
{
#>
public <#=justify (column.CsTypeName)#> <#=justify (column.Name)#> { get; set; }
<#
}
#>
}
/// <summary>
/// Command handler class for <#=table.Name#>
/// </summary>
partial class <#=table.Name#>CommandHandler : ICommandHandler<<#=table.Name#>Command>
{
private readonly IUsersRepository _repository;
private readonly IUnitOfWork _unitOfWork;
public <#=table.Name#>CommandHandler(IUsersRepository repository, IUnitOfWork unitOfWork)
{
_repository = repository;
_unitOfWork = unitOfWork;
}
public ICommandResult Execute(<#=table.Name#>Command command)
{
<#=table.Name#> entity;
<#
var identityColumn = table.Columns.FirstOrDefault (c => c.IsIdentity);
if (identityColumn == null)
{
#>
@@@ ERROR__NO_IDENTITY_COLUMN_FOUND_FOR: <#=table.FullName#>
<#
}
else
{
#>
if (command.<#=identityColumn.Name#> == 0)
{
entity = AutoMapper.Mapper.Map<<#=table.Name#>>(command);
_repository.Add(entity);
}
else
{
entity = _repository.Get(x=>x.UserId==command.<#=identityColumn.Name#>);
entity = AutoMapper.Mapper.Map<<#=table.Name#>>(command);
_repository.Update(entity);
}
_unitOfWork.Commit(command.<#=identityColumn.Name#>);
return new CommandResult(true,entity.<#=identityColumn.Name#>);
<#
}
#>
}
}
<#
}
#>
}
<#+
static Schema GetSchema (string connectionString)
{
using (var connection = new SqlConnection (connectionString))
{
connection.Open ();
return new Schema (connection);
}
}
#>
最後に、生成されたコードは次のようになります (テーブルが 1 つしかないテスト データベースの場合: CUS_Customer)
// ############################################################################
// # #
// # ---==> T H I S F I L E I S G E N E R A T E D <==--- #
// # #
// # This means that any edits to the .cs file will be lost when its #
// # regenerated. Changes should instead be applied to the corresponding #
// # template file (.tt) #
// ############################################################################
namespace ModelGenerator
{
/// <summary>
/// Repository interface for CUS_Customer
/// </summary>
partial interface ICUS_CustomerRepository : IRepository<CUS_Customer>
{
}
/// <summary>
/// Repository class for CUS_Customer
/// </summary>
partial class CUS_CustomerRepository : RepositoryBase<CUS_Customer>, ICUS_CustomerRepository
{
}
/// <summary>
/// Poco class for CUS_Customer
/// </summary>
partial class CUS_Customer
{
public System.Int64 CUS_ID { get; set; }
public System.String CUS_FirstName { get; set; }
public System.String CUS_LastName { get; set; }
public System.DateTime CUS_Born { get; set; }
public System.DateTime CUS_Created { get; set; }
}
/// <summary>
/// Command class for CUS_Customer
/// </summary>
partial class CUS_CustomerCommand : CommandBase, ICommand
{
public System.Int64 CUS_ID { get; set; }
public System.String CUS_FirstName { get; set; }
public System.String CUS_LastName { get; set; }
public System.DateTime CUS_Born { get; set; }
public System.DateTime CUS_Created { get; set; }
}
/// <summary>
/// Command handler class for CUS_Customer
/// </summary>
partial class CUS_CustomerCommandHandler : ICommandHandler<CUS_CustomerCommand>
{
private readonly IUsersRepository _repository;
private readonly IUnitOfWork _unitOfWork;
public CUS_CustomerCommandHandler(IUsersRepository repository, IUnitOfWork unitOfWork)
{
_repository = repository;
_unitOfWork = unitOfWork;
}
public ICommandResult Execute(CUS_CustomerCommand command)
{
CUS_Customer entity;
if (command.CUS_ID == 0)
{
entity = AutoMapper.Mapper.Map<CUS_Customer>(command);
_repository.Add(entity);
}
else
{
entity = _repository.Get(x=>x.UserId==command.CUS_ID);
entity = AutoMapper.Mapper.Map<CUS_Customer>(command);
_repository.Update(entity);
}
_unitOfWork.Commit(command.CUS_ID);
return new CommandResult(true,entity.CUS_ID);
}
}
}
github からプロジェクトを取得し、接続文字列を自分に関連するものに更新すると、コードが生成されます。問題が発生した場合は、この投稿に返信してください。