Update Scripts

NuGet Package Details

Package Name
Llamachant.ExpressApp.UpdateScripts.Xpo

Overview

The Update Script Module provides a structured and maintainable way to manage one-time database update logic during deployment. Instead of placing all update code in Updater.cs, this module lets you define discrete, versioned update scripts that are executed only once per database, ensuring that critical changes are applied safely and automatically without manual intervention.

TIP:

You should have a deployment strategy in place that takes a backup of the database before you deploy new versions

Installation

Step 1: Install the Module

Install-Package 'Llamachant.ExpressApp.UpdateScripts.Xpo'

Step 2: Register the Module

public override void Setup(XafApplication application) {
    base.Setup(application);
    this.RequiredModuleTypes.Add(typeof(LlamachantFrameworkUpdateScriptsModuleXpo));
}

OR

services.AddXaf(Configuration, builder => {
    builder.UseApplication<ExpressAppBlazorApplication>();
    builder.Modules
        .AddLlamachantFrameworkUpdateScriptsModuleXpo();
});

Setup

You define update scripts by implementing the IUpdateScript interface. Each script includes metadata (ID, description, creation date) and a Run method that performs the update using the provided IObjectSpace. The module executes scripts in order based on their CreatedDate, and only those that haven't run yet are applied.

You then register these scripts by implementing IUpdateScriptProvider in your ModuleBase class, allowing the module to automatically detect and run updates during application startup.

Notes:

  • Scripts can be designated as Pre-Update or Post-Update, giving you control over when they are applied in the update process.
  • You can disable update execution during debugging by setting UpdateScriptManager.Instance.UpdateWhenDebugging = false.

Step 1: Create a new class that implements IUpdateScript

// You can create as many of these types of classes as you need
public class OneTimeUpdate : IUpdateScript
{
    public string UpdateID { get; } = Guid.NewGuid().ToString(); //This must be unique
    public string Description { get; } = "Perform a one time update";
    public DateTime CreatedDate { get; } = DateTime.Parse("January 1, 2022");
    public IUpdateScriptType ScriptType { get; } = IUpdateScriptType.PostUpdateScript;

public string Run(IObjectSpace space, Version databaseVersion)
    {
        try
        {
            //try to perform your update here using the IObjectSpace
            return "Success";
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }
}

Step 2: Implement the IUpdateScriptProvider interface on your ModuleBase

public sealed class YourApplicationModule : ModuleBase, IUpdateScriptProvider
{
    public IList<IUpdateScript> GetPreUpdateScripts()
    {
        // This will automatically collect all IUpdateScripts in the current assembly
        return UpdateScriptManager.GetInstance(this.ModuleManager.Modules)
            .FindUpdateScriptsInAssembly(Assembly.GetExecutingAssembly(), IUpdateScriptType.PreUpdateScript);
    }
    public IList<IUpdateScript> GetPostUpdateScripts()
    {
        // This approach lets you determine which IUpdateScripts to release
        //return new List<iupdatescript>() { new OneTimeUpdate() };

// This will automatically collect all IUpdateScripts in the current assembly
        return UpdateScriptManager.GetInstance(this.ModuleManager.Modules)
            .FindUpdateScriptsInAssembly(Assembly.GetExecutingAssembly(), IUpdateScriptType.PostUpdateScript);
    }
}

Step 3: Initialize the UpdateScriptManager and add the updater

public override void Setup(XafApplication application)
{
    base.Setup(application);

LlamachantFramework.UpdateScripts.Utils.UpdateScriptManager.GetInstance(application.Modules)?.Initialize(application); //The update script manager will find all IUpdateScriptProviders
}

public override IEnumerable<ModuleUpdater> GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB)
{
        ModuleUpdater updater = new DatabaseUpdate.Updater(objectSpace, versionFromDB);
        return new[]
            {
                updater,
                new LlamachantFramework.UpdateScripts.Xpo.DatabaseUpdate.Updater(objectSpace, versionFromDB, UpdateScriptManager.GetInstance(Application.Modules)))
            };
}

Final Notes

  • You define update scripts by implementing the IUpdateScript interface. Each script includes metadata (ID, description, creation date) and a Run method that performs the update using the provided IObjectSpace.
  • The module executes scripts in order based on their CreatedDate, and only those that haven't run yet are applied.
  • You can disable update execution during debugging by setting UpdateScriptManager.Instance.UpdateWhenDebugging = false.