DbUp – generowanie silnie typowanych nazw procedur za pomocą T4

O bibliotece DbUp pisałem tutaj:
DBUP – AKTUALIZACJA BAZ DANYCH

Z kolei o szablonach T4  stworzyłem cały mini-cykl, który można znaleźć tutaj.

Problem z DbUp jest taki, że wywołuje on po prostu kolejne skrypty. Następnie sami za pomocą np. Dapper, musimy podać nazwę procedury czy tabeli na której chcemy operować. DbUp + Dapper to częsta kombinacja narzędzi. Jeśli korzystamy z rozbudowanego ORM, takiego jak EntitityFramework, wtedy wszystkie tabele czy nazwy procedur i tak są silnie typowane ponieważ framework je wygeneruje. Za pomocą  EF Migrations, można uzyskać to samo co robi DbUp.

Jeśli jednak korzystamy tylko z Dapper+DbUp, wciąż możemy mieć silnie typowane nazw. Załóżmy że w projekcie DbUp mamy następującą strukturę skryptów:

-> StoredProcs
—>1. GetFirstNameById
—>2. GetData
—>3. UpdateData

->Functions:
—>1. Split
—>2. MaxData

->Types
—>1.  CustomType1
—>2.  CustomType2

Wtedy można pokusić się o następujący szablon T4:

<#@ template debug="false" hostspecific="true" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".cs" #>
namespace Data.Sql
{
<#
	 string[] foldersToGenerate = new [] { "StoreProcs", "Functions","Types" };
	 string scriptsPath = Host.ResolvePath(@"..\Database\Scripts");

	 foreach(var folderName in foldersToGenerate)
	 {
	     WriteLine(string.Format("\tinternal static class {0}\n\t{{",folderName));

		 foreach(var directory in System.IO.Directory.GetDirectories(scriptsPath, "*" + folderName, SearchOption.AllDirectories))
		 {
			foreach(var fileName in Directory.GetFiles(directory))
			{
				string name = Path.GetFileNameWithoutExtension(fileName).Split(' ').Last();
				string declaration = string.Format("\t\tinternal const string {0} = \"{0}\";", name);

				WriteLine(declaration);
			}
		 }

		 WriteLine("\t}");
	 }
#>
}

Szablon przejdzie automatycznie po wszystkich plikach i wygeneruje statyczną klasę zawierającą stałe, np.:

internal static class StoreProcs
{
    internal const string GetFirstNameById="GetFirstNameById";
    internal const string GetData="GetData";
    internal const string UpdateData="UpdateData";
}

Rozwiązanie zakłada, że nazwa pliku pokrywą się z nazwą zasobu (czyli procedury, funkcji czy typu). Analogicznie sprawa wygląda z tabelami. Myślę, że jest to lepsze rozwiązanie niż hardcodowanie za każdym razem procedury.

Leave a Reply

Your email address will not be published.