0

我正在创建一个在 dbup 中实现 IScriptProvider 接口的自定义 ScriptProvider,并且我能够使用该GetScripts()方法获取脚本列表,并返回一个SqlScript对象。我想先编译对象,然后在返回之前修改每个脚本的名称,将当前版本添加到插入到日志表中的文件名之前。

我的理解是这应该是可行的,因为脚本的内容在SqlScript填充时已经添加到对象中,似乎此时修改名称不会影响任何事情。

我遇到的问题是NameSqlScript 对象的属性是只读的,所以我不能随意修改它。

我该如何解决这个问题,或者是否有另一种方法可以编译要执行和记录的脚本,然后在将脚本名称写入日志表之前,为脚本名称添加一个值。

例如,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();

我最终希望有一个清单文件,将部署脚本作为“运行一次”类型的脚本运行,然后我想维护一个单一版本的东西,例如存储的过程和视图,并让清单文件指示哪些脚本可以运行每个部署,所以我们不会删除和重新创建每个存储的过程,这就是我们目前正在做的事情。

问题是,我可以选择使用 NullJournal 而不向数据库写入任何内容,或者存储的过程不会执行多次,因为它们的名称总是相同的。

也试图想其他方法来实现这一点,但到目前为止我一无所获。

在一个完美的世界中,我希望能够将物理文件dbo.StoredProcedure.sql记录为Release 1.0.0 - dbo.StoredProcedure.sql. 这样,如果该存储过程在未来发生变化,它将被执行并存储为Release 2.0.0 - dbo.StoredProcedure.sql它所在的任何版本。但物理文件始终只有一个跨时间/版本的同名文件。

4

0 回答 0