ããã«ã¡ã¯ãHabrïŒ
ãã®èšäºã§ã¯ãT4-ããã¹ããã³ãã¬ãŒãå€æããŒã«ãããã䜿çšããVisual Studioã§ã®èªåã³ãŒãçæã®ãããã¯ãç¶ç¶ããŸãã ãã®ããã°ã§å°ãåã«å
¬éããã
ããŒã1ã¯ãT4æ§æãšãã®äœ¿çšã®åºæ¬ååã説æããŠããŸãã åæã«ãå°æ¬ãããŠãã
Oleg Sychã®ããã°ã詳ãã調ã¹ãŠã圌ã®æ¥çžŸã®äžéšãhabraã®èŠèŽè
ã«ããã«é©åãããããšã«ããŸããã ç¹ã«ãä»æ¥ã¯æ¬¡ã®ãããã¯ã«ã€ããŠèª¬æããŸãã
- åå©çšå¯èœãªãã©ã¡ãŒã¿ãŒåå¯èœãªãã³ãã¬ãŒããäœæãã
- ãã³ãã¬ãŒããžã§ãã¬ãŒã¿ãŒã®äœæ
- ãžã§ãã¬ãŒã¿ãŒã®ãããã°ããã¹ããæ¡åŒµïŒãªã³ã¯ïŒ
ç§ã¯ç¹å¥ãªäŸãçºæããŸããã§ããã Olegã«ãã£ãŠèšè¿°ãããã¹ãã¢ãããã·ãŒãžã£ã®äœæã䌎ãã¯ãšãªã®éçºã®å±¥æŽã¯ããžã§ãã¬ãŒã¿ãå¿
èŠãšããå¯èœæ§ã®ããåé¡ã説æããã®ã«çæ³çã§ãã ããã«ãããã¯ç¹åŸŽçã§ããã倧ãããªåé¡ã§ã¯ãããŸããã ãŸãããã®èšäºã¯ãèšèãå°ãªãããŠã³ãŒããå¢ããããšããååãé å®ããŠããŸãã
以äžã§ã¯ãVisual Studio 2005/2008/2010ãããã³
T4 Toolboxãã€ã³ã¹ããŒã«ãããŠããããšãåæãšããŠããŸãã
ãã©ã¡ãŒã¿åå¯èœãªãã³ãã¬ãŒã
åæ段é
ããŒã¿ããŒã¹ããããŸãã ãã®ããŒã¿ããŒã¹ã«ã¯ããŒãã«ããããŸãã ãããŠãè¡šã§ã¯ãKoshchei the Immortalã®æé«ã®äŒçµ±ã«ãåé€ãããè¡ããããŸãã ãããŠããã®ããã«åé€ããã ãã§ãªããæ°ããäœæããã¹ãã¢ãããã·ãŒãžã£ã䜿çšããŠåé€ããŸãã ç°¡åã«ããããã«ããã©ã¡ãŒã¿ãããã·ãŒãžã£ã«æž¡ããŠãã ããããã¹ãŠããŒãã«ã®åäžã®ãã£ãŒã«ãã«æž¡ããŠãåé€ããè¡ãèå¥ããŸãã ãã®ãããªããã·ãŒãžã£ãæåã§äœæããèŠæ±ãå
¥åããããšã¯ãæè¬ã®ãªãä»äºãªã®ã§ãT4ã䜿çšããŠã次ã®ãããªã³ãŒããäœæããŸãã
<#@ template language= â C#v3.5 â #>
<#@ output extension= â SQL â #>
<#@ assembly name= â Microsoft.SqlServer.ConnectionInfo â #>
<#@ assembly name= â Microsoft.SqlServer.Smo â #>
<#@ import namespace= â Microsoft.SqlServer.Management.Smo â #><#
Server server = new Server();
Database database = new Database(server, âNorthwindâ);
Table table = new Table(database, âProductsâ);
table.Refresh();
#>
create procedure <#= table.Name #> _Delete
<#
PushIndent(â\tâ);
foreach (Column column in table.Columns)
if (column.InPrimaryKey)
WriteLine(â@â + column.Name + â â + column.DataType.Name);
PopIndent();
#>
as
delete from <#= table.Name #>
where
<#
PushIndent(â\t \ tâ);
foreach (Column column in table.Columns)
if (column.InPrimaryKey)
WriteLine(column.Name + â = @â + column.Name);
PopIndent();
#>
ããã§ã¯ã
SQL Server管çãªããžã§ã¯ã ïŒSMOïŒã䜿çšããŠãããŒã«ã«SQLãµãŒããŒã®ããŒã¿ããŒã¹ããããŒãã«ãã£ãŒã«ãã«é¢ããæ
å ±ãååŸããŸãã ãã¡ã€ã«ãåºåã«ä¿åããåŸãæ€çŽ¢ã¯ãšãªãååŸããŸãã ããšãã°ã次ã®ããã«ãªããŸãã
create procedure Products_Delete
@ProductID int
as
delete from Products
where ProductID = @ProductID
ãã©ã¡ãŒã¿å
ãã®ã³ãŒããèŠã人ã®é ã«æåã«åºãŠãã質åã¯ããªãããŒã¿ããŒã¹åãšããŒãã«ãã³ãŒãã«ããŒãã³ãŒããããŠããã®ã§ããïŒ æ°ãããªã¯ãšã¹ããäœæããããã«ãããã°ã©ããŒã¯ãã³ãã¬ãŒããã¯ããŒã«ããããã€ãã®å Žæã§æåã§å€æŽããå¿
èŠããããŸããïŒ
æ¬åœã«å¿
èŠãããŸããã å¥ã®çææ¹æ³ã䜿çšããã°ååã§ãã T4ããŒã«ããã¯ã¹ã®ãã¡ã€ã«ã®ä»£ããã«ãã³ãã¬ãŒããªãã·ã§ã³ã䜿çšããŠãæ°ãããã¡ã€ã«ããããžã§ã¯ãã«è¿œå ããŸããããšãã°ãDeleteProcedureTemplate.ttãªã©ã®ååãä»ããŸãã ã芧ã®ãšãããç°å¢ã¯ãã©ã¡ãŒã¿ãŒåããããã³ãã¬ãŒãã®ãã©ã³ã¯ãã€ãŸããã¡ã€ã«ãèªåçã«äœæããäžè¬åããã圢åŒã§äœ¿çšããããã«ä»ã®ãã³ãã¬ãŒãã«å«ããŸãã
<#+
// <copyright file=âDeleteProcedureTemplate.ttâ company=âYour Companyâ>
// Copyright © Your Company. All Rights Reserved.
// </copyright>
public class DeleteProcedureTemplate : Template
{
protected override void RenderCore()
{
}
}
#>
Microsoft.VisualStudio.TextTemplatingåå空éã§Templateã¯ã©ã¹ãèŠã€ããããšããªãã§ãã ããã ããã¯T4Toolboxã§å®çŸ©ãããæœè±¡ã¯ã©ã¹ã§ãããT4Toolbox.ttãã¡ã€ã«ããã©ã¡ãŒã¿ãŒåããããã³ãã¬ãŒãèªäœã«çŽæ¥æ¥ç¶ããããšã¯æå³ããããŸããã ãããã£ãŠãDeleteProcedureTemplate.ttãä¿åãããã³ã«ãStudioã¯ãããåŠçããåºåãã¡ã€ã«ãçæããã¯ã©ãã·ã¥ããŠãã®ãšã©ãŒãéç¥ããããšããŸãã ãã®äžå¿«ãªåäœã¯ãç·šéå¯èœãªãã¡ã€ã«ã®[ããããã£]ãŠã£ã³ããŠãèŠãŠãã«ã¹ã¿ã ããŒã«ããããã£ã空ã®è¡ã«èšå®ããããšã§ç°¡åã«åé€ã§ããŸãã çŸåšãæé»çãªçæã®è©Šè¡ã¯è¡ãããŸããã
Templateã¯ã©ã¹ã®RenderCoreïŒïŒã¡ãœããã¯ããã©ã¡ãŒã¿ãŒåããããã³ãã¬ãŒãã®äž»èŠãªæäœãã€ã³ãã§ãã ãžã§ãã¬ãŒã¿å
ã®ãã³ãã¬ãŒããæçµçã«è²¬ä»»ãè² ãã®ã¯ãããã¹ãã®äžéšãçæãããããšã§ãã ãããã£ãŠããã以äžèŠåŽããããšãªããæ¢è£œã®ã³ãŒããããã«è»¢éããã ãã§ãã
<#@ assembly name= â Microsoft.SqlServer.ConnectionInfo â #>
<#@ assembly name= â Microsoft.SqlServer.Smo â #>
<#@ import namespace= â Microsoft.SqlServer.Management.Smo â #>
<#+
public class DeleteProcedureTemplate : Template
{
public string DatabaseName;
public string TableName;
protected override void RenderCore()
{
Server server = new Server();
Database database = new Database(server, DatabaseName);
Table table = new Table(database, TableName);
table.Refresh();
#>
create procedure <#= table.Name #> _Delete
<#+
PushIndent(â\tâ);
foreach (Column column in table.Columns)
{
if (column.InPrimaryKey)
WriteLine(â@â + column.Name + â â + column.DataType.Name);
}
PopIndent();
#>
as
delete from <#= table.Name #>
where
<#+
PushIndent(â\t \ tâ);
foreach (Column column in table.Columns)
{
if (column.InPrimaryKey)
WriteLine(column.Name + â = @â + column.Name);
}
PopIndent();
}
}
#>
ãã³ãã¬ãŒãã«å ããããäž»ãªå€æŽã¯ãéããŠãããã£ãŒã«ãDatabaseNameãšTableNameã®è¿œå ã§ãããããã¯å®éããã©ã¡ãŒã¿ãŒåã®æ©èœãå®è¡ããŸãã ããã§ãããŒã¿ãã¡ã€ã«ãšããžãã¯ãã¡ã€ã«ãåé¢ãããŸããã æ®ã£ãŠããã®ã¯ãincludeãã£ã¬ã¯ãã£ãã䜿çšããŠãç°ãªãããŒã¿ããŒã¹ãšããŒãã«ã§åããã³ãã¬ãŒãã亀äºã«éå§ããããšã§ãã次ã«äŸã瀺ããŸãã
<#@ template language =â C#v3.5 â hostspecific =â True â #>
<#@ output extension =â sql â #>
<#@ include file =â T4Toolbox.tt â #>
<#@ include file =â DeleteProcedureTemplate.tt â #>
<#
DeleteProcedureTemplate template = new DeleteProcedureTemplate();
template.DatabaseName = âNorthwindâ ;
template.TableName = âProductsâ ;
template.Render();
#>
å¿
èŠã«å¿ããŠãåãæ¹æ³ã䜿çšããŠããã©ã¡ãŒã¿ãŒã«å¿ããŠãDELETEã ãã§ãªãSELECTãINSERTãããã³UPDATEã«åºã¥ãã¹ãã¢ãããã·ãŒãžã£ãäœæãããŠãããŒãµã«ãã³ãã¬ãŒããäœæã§ããŸãã 誰ããèªåã§ãã³ãã¬ãŒãã³ãŒããäœæã§ããããã«ãªããŸããã
èãžã®ããããªåŸéã äžèŠãããšããã説æãããŠãããã¹ãŠã®è³æã¯åæ©çãªãã®ã«èŠããŸãã ã¯ããå®éã圌ã¯T4å
šäœãšåãããã«ååšããŠããŸãã 質åã¯ç°ãªããŸãããããã®æ©èœã¯æšæºããã±ãŒãžã«å«ãŸããŠããŸãããã®åçŽãªèšäºã®ã³ã³ãã€ã«ã§ã¯ãèªè
ïŒããã³çµéšã®ç°ãªãHabrã®èªè
ïŒãèªåã®èªè»¢è»ãç©ã¿éãªãå±éºããä¿è·ããããšæããŸãã 以äžã«èª¬æãããã³ãã¬ãŒããžã§ãã¬ãŒã¿ã¯ããã®ãããªå¥ã®èœãšãç©Žã§ãã
ãã³ãã¬ãŒããžã§ãã¬ãŒã¿ãŒ
ãã©ã¡ãŒã¿åããããã³ãã¬ãŒãã«ã¯ããŸã 説æãããŠããªãæ¬ é¥ã1ã€ãããŸãã ã¯ããåå¥ã®ãã¡ã€ã«ã«ç¹å®ã®ããŒã¿ããŒã¹åãšããŒãã«åãæã€ãã³ãã¬ãŒããèµ·åããããžãã¯ãåããŸããããããã€ãã®å¯èœãªããŒã¿ããŒã¹ãšããŒãã«ã§äœæ¥ããå Žåããã®ãããªãœãªã¥ãŒã·ã§ã³ã¯ãœãŒããœãŒãã®ä»£ããã«ãªããŸãã ããã°ã©ãã¯ãç¹å®ã®ããŒãã«ããšã«åå¥ã®ãã³ãã¬ãŒããã¡ã€ã«ãäœæããããšãäœåãªããããŠããŸãã ãããã®ãã¡ã€ã«ã®ãµã€ãºã¯ç®ç«ã£ãŠå°ãããªããŸãããã³ããŒãšè²Œãä»ãã®åé¡ããã£ã³ã»ã«ãã人ã¯ããŸããã çæ³çã«ã¯ããã®ç¹å®ã®ããŒã¿ããŒã¹ã®åããŒãã«ã«å¯ŸããŠåå¥ã®ã¯ãšãªãäžåºŠã«äœæããããšæããŸãã å¯èœã§ããïŒ ã¯ã
ãããžã§ã¯ãã«ãT4Toolbox-Generatorã®äžéšãšããŠéçºããã3çªç®ã®äŸ¿å©ãªã¿ã€ãã®ãã³ãã¬ãŒããè¿œå ããŸãã ãžã§ãã¬ãŒã¿ãŒã¯ããã©ã¡ãŒã¿ãŒåããããã³ãã¬ãŒãã䜿çšããŠãããŸããŸãªãã©ã¡ãŒã¿ãŒå€ïŒããŒã¿ããŒã¹åãšããŒãã«ïŒãããã«ä»£å
¥ããåŠççµæãããŸããŸãªãã¡ã€ã«ã«éä¿¡ããŸãã åŸè
ã®ç®çã®ããã«ãTemplateã¯ã©ã¹ã¯çŽ æŽãããRenderToFileã¡ãœãããæäŸããŸãã
ãããã£ãŠããžã§ãã¬ãŒã¿ãŒãã¡ã€ã«ã®ååã¯CrudProcedureGenerator.ttã§ããããã®ããã©ã«ãã®ã¹ããã¯ã¯æ¬¡ã®ããã«ãªããŸãã
<#+
// <copyright file=âCrudProcedureGenerator.ttâ company=âYour Companyâ>
// Copyright © Your Company. All Rights Reserved.
// </copyright>
public class CrudProcedureGenerator : Generator
{
protected override void RunCore()
{
}
}
#>
ãžã§ãã¬ãŒã¿ãŒèªäœã¯T4ããã¹ãã®åŠçãè¡ããããã§ã«äœæãããŠããä»ã®åºæ¬ãã³ãã¬ãŒãã®ã¿ãé çªã«èµ·åããŸãã ãããã£ãŠãRenderããã³RenderCoreã®ä»£ããã«å¯Ÿå¿ããã¡ã€ã³ã¡ãœããã¯ãããããRunããã³RunCoreãšåŒã°ããŸãã ããããèªåçšã«èª¿æŽããŸãããïŒ
<#@ assembly name =â Microsoft.SqlServer.ConnectionInfo â #>
<#@ assembly name =â Microsoft.SqlServer.Smo â #>
<#@ import namespace =â Microsoft.SqlServer.Management.Smo â #>
<#@ include file =â DeleteProcedureTemplate.tt â #>
<#+
public class CrudProcedureGenerator : Generator
{
public string DatabaseName;
public DeleteProcedureTemplate DeleteTemplate = new DeleteProcedureTemplate();
protected override void RunCore()
{
Server server = new Server();
Database database = new Database(server, this .DatabaseName);
database.Refresh();
foreach (Table table in database.Tables)
{
this .DeleteTemplate.DatabaseName = this .DatabaseName;
this .DeleteTemplate.TableName = table.Name;
this .DeleteTemplate.RenderToFile(table.Name + â_Delete.sqlâ );
}
}
}
#>
ããã§ã¯ãç¹å®ã®1ã€ã®ããŒã¿ããŒã¹å
ã®ãã¹ãŠã®ããŒãã«ã䞊ã¹æ¿ããããDeleteProcedureTemplateã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ããšã«ãèŠæ±ãšå
±ã«åå¥ã®äžæã®åºåãã¡ã€ã«ãäœæãããŸãã å®å
šã«å¹žçŠã«ããã«ã¯ãããŒã¿ããŒã¹ãèšå®ããŠå®å
šãªåŠçãµã€ã¯ã«ãéå§ããã ãã§ã¯ååã§ã¯ãããŸããã
<#@ template language =â C#v3.5 â hostspecific =â True â debug =â True â #>
<#@ output extension =â txt â #>
<#@ include file =â T4Toolbox.tt â #>
<#@ include file =â CrudProcedureGenerator.tt â #>
<#
CrudProcedureGenerator generator = new CrudProcedureGenerator();
generator.DatabaseName = âNorthwindâ ;
generator.Run();
#>
ç»é¢äžã®çµæïŒ
è¿œèšã ãžã§ãã¬ãŒã¿ãŒã䜿çšããæ©èœ
éåžžã®ããžãã¯ã«åŸã£ãŠããžã§ãã¬ãŒã¿ãŒã«é¢ããèšäºã¯ãé«åºŠãªããŒãºã«åãããŠãããããããã°ããã¹ããããã³ç°¡åã«å€æŽããæ¹æ³ã«ã€ããŠã®ã¡ã¢ãšãšãã«å®äºããå¿
èŠããããŸãã æ®å¿µãªããããã®1ã€ã®habrastatyaã¯ãã®ãããªéã®äœåãªããã°ã©ã ã³ãŒãã«èããããŸãããã3çªç®ã®ããŒãã«å
¥ããæ°ã¯ãããŸãããçŽ æã貧匱ã§ããŒã ããé¢å©ããããšã«ãªããŸãã ãããã£ãŠããªã¬ã°ã¯ããªã¬ã°ãµã€ãã®ããã°ããã®ãœãŒã¹ã³ãŒããšåæ§ã«ãèªè
ãåé¡ãªããžã§ãã¬ãŒã¿ãŒãç掻ã®äžã§äœ¿çšã§ããããã«ãªãããšã«åºã¥ããŠã¢ããã€ã¹ã«éå®ããŸãã
- ãžã§ãã¬ãŒã¿ãŒããã¹ãããããã«ãT4 Toolboxã«ã¯ãUnit Testããšããååã®ç¬èªã®åªãããã©ã³ã¯ããããŸãã
- çæã®äžå¿ïŒãã³ãã¬ãŒãã«ãã£ãŠçæãããã³ãŒãïŒãå€æŽããå¿
èŠãããå Žåããã®ã¯ã©ã¹ïŒãã®å Žåã¯DeleteProcedureTemplateïŒã§ãã¡ã€ã«ãçŽæ¥ç·šéããå¿
èŠã¯ãããŸããã å¥ã®ãã¡ã€ã«ããžã§ãã¬ãŒã¿ãŒã«ã€ã³ããŒãããã°ããã³ãã¬ãŒãã®çžç¶äººãå¿
èŠãªèª¿æŽãšãšãã«èšè¿°ã§ããŸãã
- Generatorã¯ã©ã¹ã«ã¯ãã³ãŒãçæïŒRunCoreïŒãçŽæ¥åŠçããåã«ãæåã«Runã¡ãœããã«ãã£ãŠåŒã³åºãããValidateé¢æ°ããããŸãã ãžã§ãã¬ãŒã¿ã®å
¥åãã©ã¡ãŒã¿ã確èªããããã«äœ¿çšã§ããŸãã
- ãšã©ãŒãå ±åããã«ã¯ãTextTransformationã¯ã©ã¹ã§èª¬æãããã®ãšåæ§ã®Errorããã³Warningã¡ãœããã䜿çšã§ããŸãã
é¢é£ãªã³ã¯ïŒ
ã³ãŒããžã§ãã¬ãŒã¿ãŒã§ã®ãšã©ãŒåŠçåäœãã¹ãã³ãŒããžã§ãã¬ãŒã¿ãŒã³ãŒããžã§ãã¬ãŒã¿ãŒãæ¡åŒµå¯èœã«ãã