読者です 読者をやめる 読者になる 読者になる

ビルド時に .sql ファイルを検証する MSBuild インラインタスク

SQL Server .NET

Visual Studio勉強会 : ATND の LT で紹介したネタです。
MSBuild 4 からは、インラインタスクが書ける(MSBuild 4.0 からインラインタスクが書けます - お だ のスペース)ので、 さくっと書いてみた。

...
  <ItemGroup>
    <Content Include="libs\Microsoft.SqlServer.TransactSql.ScriptDom.dll" />
    <Content Include="sql\受注テーブル\Delete.sql" />
    <Content Include="sql\受注テーブル\Insert.sql" />
    <Content Include="sql\受注テーブル\Select.sql" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  -->
  <UsingTask
    TaskName="SQLVerify"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
    <ParameterGroup />
    <Task>
      <Reference Include="libs\Microsoft.SqlServer.TransactSql.ScriptDom.dll" />
      <Using Namespace="Microsoft.SqlServer.TransactSql.ScriptDom" />
      <Using Namespace="System" />
      <Using Namespace="System.Collections.Generic" />
      <Using Namespace="System.Linq" />
      <Using Namespace="System.IO" />
      <Code Type="Fragment" Language="cs">
        var valid = true;
        foreach (var f in Directory.GetFiles(".", "*.sql", SearchOption.AllDirectories)) {
          var parser = new TSql110Parser(false);
          IList&lt;ParseError&gt; errors;
          var parsed = parser.Parse(new StringReader(File.ReadAllText(f)), out errors);
          if (errors.Count != 0) {
            Log.LogError(string.Join(Environment.NewLine,
              errors.Select(e =&gt; string.Format("ファイル:{0} 行:{1} {2}文字目 {3}", f, e.Line, e.Column, e.Message))));
            valid = false;
          }
        }
        return valid;
      </Code>
    </Task>
  </UsingTask>
  <Target Name="BeforeBuild">
    <SQLVerify />
  </Target>
  <Target Name="AfterBuild">
  </Target>
...