使用T4模板基于POCO生成多个类

我正在寻找一种方法来提高生产力,当我向我的数据库添加一个表。 通常,当我添加新表时,我必须执行以下步骤。

  1. 将表添加到数据库(简单)
  2. 创建相应的EF Code First类。 (我不使用db迁移)
  3. 创建一个匹配#2中创建的EF类的POCO模型。
  4. 创建存储库类
  5. 为CQRS模式创建命令和处理程序
  6. 为新创建的类创建AutoMapper映射

我最近创建了一个新网站,其中要求首先使用EF数据库,我看到它是如何使用tt文件生成类的。 这让我想到我可以以某种方式使用这些模板(新的模板)来生成基本CRUD操作的所有标准支持项。 麻烦的是我没有创建这些模板的经验,也不知道从哪里开始。

要生成的示例代码:

知识库

using System; using System.Collections.Generic; using System.Linq; using System.Text; public interface IUsersRepository : IRepository { } public class UsersRepository : RepositoryBase, IUsersRepository { public UsersRepository(IDatabaseFactory databaseFactory) : base(databaseFactory) { } } 

基于EDMX(或Code First)生成的实体的基本模型

 using System; using System.Collections.Generic; using System.Linq; using System.Text; public class User { public int UserId { get; set; } public string UserRole { get; set; } public string UserName { get; set; } } 

命令

 using System; using System.Collections.Generic; using System.Linq; using System.Text; public class AddUpdateUserPayoutCommand : CommandBase, ICommand { public int UserId { get; set; } public string UserRole { get; set; } public string UserName { get; set; } } 

命令处理程序

 using System; using System.Collections.Generic; using System.Linq; using System.Text; public class AddUpdateUserHandler: ICommandHandler { private readonly IUsersRepository _repository; private readonly IUnitOfWork _unitOfWork; public AddUpdateUserPayoutHandler(IUsersRepository repository, IUnitOfWork unitOfWork) { _repository = repository; _unitOfWork = unitOfWork; } public ICommandResult Execute(AddUpdateUserCommand command) { Users entity; if (command.UserId == 0) { entity = AutoMapper.Mapper.Map(command); _repository.Add(entity); } else { entity = _repository.Get(x=>x.UserId==command.UserId); entity = AutoMapper.Mapper.Map(command); _repository.Update(entity); } _unitOfWork.Commit(command.UserId); return new CommandResult(true,entity.UserId); } } 

Automapper Maps – 放置在app_start中

 Mapper.CreateMap(); 

这个例子并不是一个可以切入项目的解决方案,而是作为一个例子来说明如何编写一个从数据库模式生成代码的模板。

构建了一个快速模板,演示了如何生成代码工件。

你可以在这里找到整个项目: https : //github.com/mrange/CodeStack/tree/master/q18787460/ModelGenerator

模板本身使用T4Include.Schema来获取数据库模式。 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 justify = s => LeftJustify (s, 40); var tables = schema .SchemaObjects .Where (so => so.Type == SchemaObject.SchemaObjectType.Table) .ToArray () ; #> namespace <#=namespaceName#> { <# foreach (var table in tables) { #> ///  /// Repository interface for <#=table.Name#> ///  partial interface I<#=table.Name#>Repository : IRepository<<#=table.Name#>> { } ///  /// Repository class for <#=table.Name#> ///  partial class <#=table.Name#>Repository : RepositoryBase<<#=table.Name#>>, I<#=table.Name#>Repository { } ///  /// Poco class for <#=table.Name#> ///  partial class <#=table.Name#> { <# foreach (var column in table.Columns) { #> public <#=justify (column.CsTypeName)#> <#=justify (column.Name)#>{ get; set; } <# } #> } ///  /// Command class for <#=table.Name#> ///  partial class <#=table.Name#>Command : CommandBase, ICommand { <# foreach (var column in table.Columns) { #> public <#=justify (column.CsTypeName)#> <#=justify (column.Name)#> { get; set; } <# } #> } ///  /// Command handler class for <#=table.Name#> ///  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); } } #> 

最后,生成的代码看起来像这样(对于我的测试数据库,只有一个表:CUS_Customer)

 // ############################################################################ // # # // # ---==> THISFILEISGENERATED <==--- # // # # // # 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 { ///  /// Repository interface for CUS_Customer ///  partial interface ICUS_CustomerRepository : IRepository { } ///  /// Repository class for CUS_Customer ///  partial class CUS_CustomerRepository : RepositoryBase, ICUS_CustomerRepository { } ///  /// Poco class for CUS_Customer ///  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; } } ///  /// Command class for CUS_Customer ///  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; } } ///  /// Command handler class for CUS_Customer ///  partial class CUS_CustomerCommandHandler : ICommandHandler { 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(command); _repository.Add(entity); } else { entity = _repository.Get(x=>x.UserId==command.CUS_ID); entity = AutoMapper.Mapper.Map(command); _repository.Update(entity); } _unitOfWork.Commit(command.CUS_ID); return new CommandResult(true,entity.CUS_ID); } } } 

如果你从github拉出项目并将连接字符串更新为与你相关的东西,它应该为你生成代码。 如果您遇到任何问题,请回复此帖。

您想要的是实体接口生成器的路线图

https://entityinterfacegenerator.codeplex.com

该项目包含自定义的T4模板,可以为DbContext类和实体类生成接口和属性。 它不会,但很快就会生成通用存储库。