Я создаю пользовательский ScriptProvider, реализующий интерфейс IScriptProvider в dbup, и я могу получить список скриптов с помощью метода GetScripts()
и вернуть объект SqlScript
. Я хотел бы сначала скомпилировать объект, а затем, прежде чем возвращать его, изменить имя каждого скрипта, добавив текущий выпуск к имени файла, который вставляется в таблицу журнала.
Насколько я понимаю, это должно быть выполнимым, поскольку содержимое сценария уже добавлено к объекту SqlScript
при его заполнении, похоже, что изменение имени в этот момент ни на что не повлияет.
Проблема, с которой я столкнулся заключается в том, что свойство Name
объекта SqlScript доступно только для чтения, поэтому я не могу изменить его напрямую, как хотелось бы.
Как я могу обойти это, или есть другой способ, которым я мог бы скомпилируйте сценарии для выполнения и ведения журнала, а затем перед записью имен сценариев в таблицу журнала добавьте значение к имени сценария.
Например, Script001
становится Release 1.0.0 - Script001
.
Мне также нужно было бы удалить это значение при чтении ранее выполненных скриптов, чтобы убедиться, что они соответствуют фактическим именам файлов и не получают выполняется снова.
ОБНОВЛЕНИЕ
namespace DbUpManifest
{
public class DeploymentManifestScriptProvider : IScriptProvider
{
readonly string directoryPath;
readonly string basePath;
readonly Func<string, bool> filter;
readonly Encoding encoding;
readonly FileSystemScriptOptions options;
public string Release;
public List<string> FileList;
public DeploymentManifestScriptProvider(string basePath, string directoryPath, FileSystemScriptOptions options)
{
if (options == null)
throw new ArgumentNullException("options");
this.options = options;
this.directoryPath = directoryPath;
this.basePath = basePath;
}
private List<string> SerializeJsonFile()
{
Manifest manifest;
var files = new List<string>();
using (StreamReader file = File.OpenText(directoryPath))
{
JsonSerializer serializer = new JsonSerializer();
manifest = (Manifest)serializer.Deserialize(file, typeof(Manifest));
}
Release = manifest.Release.ToString();
foreach (var item in manifest.Scripts)
{
string thisItem;
if(Debugger.IsAttached)
{
thisItem = string.Concat(basePath, @"Deployment Scripts\vNext\", item);
}
else
{
thisItem = string.Concat(basePath, @"Deployment Scripts\", Release, @"\", item);
}
FileAttributes attr = File.GetAttributes(thisItem);
foreach (var scriptExtension in options.Extensions)
{
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
{
files.AddRange(Directory.GetFiles(thisItem, scriptExtension, ShouldSearchSubDirectories()));
}
else
{
files.Add(thisItem.ToString());
}
}
}
foreach (var item in manifest.StoredProcedures)
{
string thisItem = string.Concat(basePath, "Stored Procedures", "\\", item);
FileAttributes attr = File.GetAttributes(thisItem);
foreach (var scriptExtension in options.Extensions)
{
files.Add(thisItem.ToString());
}
}
return files;
}
public IEnumerable<SqlScript> GetScripts(IConnectionManager connectionManager)
{
List<string> scripts = SerializeJsonFile();
var outputFiles = scripts.Select(x => SqlScript.FromFile(x))
.OrderBy(x => x.Name)
.ToList();
return outputFiles;
}
SearchOption ShouldSearchSubDirectories()
{
return options.IncludeSubDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
}
}
}
Я попытался изменить это, чтобы добавить выпуск к имени файла, но затем он ошибки, говорящие, что он не может найти файл, потому что физический файл фактически не назван с добавленной строкой.
var outputFiles = scripts.Select(x => SqlScript.FromFile(String.Concat(Release," - ", x)))
.OrderBy(x => x.Name)
.ToList();
В конечном итоге я хочу иметь файл манифеста, который запускает сценарии развертывания как сценарии типа «запускать один раз», а затем я хочу поддерживать единую версию таких вещей, как сохраненные процессы и представления, и иметь манифест файл определяет, какие из этих сценариев запускаются при каждом развертывании, поэтому мы не отбрасываем и воссоздаем каждую сохраненную версию pro c, что мы сейчас и делаем.
Проблема в том, что у меня есть выбор либо использовать NullJournal и ничего не записывать в БД, либо сохраненные процессы не будут выполняться более одного раза, потому что они всегда будут называться одинаковыми.
Попытка придумать другие способы выполнения это тоже, но пока у меня ничего нет.
В идеальном мире я бы хотел, чтобы физический файл dbo.StoredProcedure.sql
регистрировался как Release 1.0.0 - dbo.StoredProcedure.sql
. Таким образом, если этот spro c изменится в будущем, он будет выполнен и сохранен как Release 2.0.0 - dbo.StoredProcedure.sql
или какой-либо другой выпуск, в котором он находится. Но физический файл всегда представляет собой только один файл с тем же именем во времени / выпусках.