https://discord.umbraco.com logo
#package-development
Title
# package-development
m

Matt Wise

10/21/2022, 2:37 PM
Migration table creation
Getting the following when trying to create two tables and populate one of them in migrations
KeyNotFoundException: The given key 'System.Collections.Generic.List1[Umbraco.Community.CSPManager.Models.CspDefinitionSource]' was not present in the dictionary.
Copy code
public sealed class InitialCspManagerMigration : MigrationBase
{
    public const string MigrationKey = "csp-manager-init";

    public InitialCspManagerMigration(IMigrationContext context) : base(context)
    {
    }

    protected override void Migrate()
    {
        if (!TableExists(nameof(CspDefinitionSource)))
        {
            Create.Table<CspDefinitionSource>().Do();
        }
    }
}

public sealed class PopulateDefaultBackOfficeCspMigration : MigrationBase
{
    public const string MigrationKey = "csp-manager-default-backoffice";

    public PopulateDefaultBackOfficeCspMigration(IMigrationContext context) : base(context)
    {
    }

    protected override void Migrate()
    {
        if (!TableExists(nameof(CspDefinition)))
        {
            Create.Table<CspDefinition>().Do();
            // Insert.IntoTable(nameof(CspDefinition)).Row(new CspDefinition
            // {
            //     IsBackOffice = true, Enabled = false, Sources = CspConstants.DefaultBackOfficeCsp
            // }).Do();
        }
    }
}
They run in order of the examples 🙂
d

David Brendel

10/21/2022, 2:43 PM
Any specific line on which it breaks in the stacktrace?
m

Matt Wise

10/21/2022, 2:44 PM
Create.Table().Do();
I should probably of said that 😄
Tables:
Copy code
[TableName((nameof(CspDefinition)))]
[PrimaryKey(nameof(Id), AutoIncrement = false)]
public class CspDefinition
{
    public Guid Id { get; set; }
    
    public bool Enabled { get; set; }
    
    public bool ReportOnly { get; set; }
    
    public bool IsBackOffice { get; set; }

    [References(typeof(CspDefinitionSource))]
    public List<CspDefinitionSource> Sources { get; set; } = new();
}


[TableName((nameof(CspDefinitionSource)))]
[PrimaryKey(new []{ nameof(DefinitionId), nameof(Source)})]
public class CspDefinitionSource
{
    [References(typeof(CspDefinition))]
    public Guid DefinitionId { get; set; }
    
    public string Source { get; init; }

    [SerializedColumn]
    [SpecialDbType(SpecialDbTypes.NVARCHARMAX)]
    public List<string> Directives { get; set; } = new();
}
d

David Brendel

10/21/2022, 2:47 PM
Yeah thought that it is that you use references... I had problems with them most of the time I tried to use them.
The table for the CspDefinitionSource is created if you only run that migration?
m

Matt Wise

10/21/2022, 2:52 PM
Yep.. I wonder if its how I am doing the plan then
Copy code
migrationPlan.From(string.Empty)
            .To<InitialCspManagerMigration>(InitialCspManagerMigration.MigrationKey)
            .To<PopulateDefaultBackOfficeCspMigration>(PopulateDefaultBackOfficeCspMigration.MigrationKey);
when adding that back in it all looks to work as well
d

David Brendel

10/21/2022, 2:56 PM
Are you calling the plan on your own? As it lokks as you use an instance of migrationPLan in your code sample?
m

Matt Wise

10/21/2022, 2:56 PM
Copy code
public sealed class RunCspManagerMigration : INotificationHandler<UmbracoApplicationStartingNotification>
{
    private readonly IMigrationPlanExecutor _migrationPlanExecutor;
    private readonly ICoreScopeProvider _coreScopeProvider;
    private readonly IKeyValueService _keyValueService;
    private readonly IRuntimeState _runtimeState;

    public RunCspManagerMigration(
        ICoreScopeProvider coreScopeProvider,
        IMigrationPlanExecutor migrationPlanExecutor,
        IKeyValueService keyValueService,
        IRuntimeState runtimeState)
    {
        _migrationPlanExecutor = migrationPlanExecutor;
        _coreScopeProvider = coreScopeProvider;
        _keyValueService = keyValueService;
        _runtimeState = runtimeState;
    }

    public void Handle(UmbracoApplicationStartingNotification notification)
    {
        if (_runtimeState.Level < RuntimeLevel.Run)
        {
            return;
        }

        var migrationPlan = new MigrationPlan("CspManagerMigration");

        // This is the steps we need to take
        // Each step in the migration adds a unique value
        migrationPlan.From(string.Empty)
            .To<InitialCspManagerMigration>(InitialCspManagerMigration.MigrationKey)
            .To<PopulateDefaultBackOfficeCspMigration>(PopulateDefaultBackOfficeCspMigration.MigrationKey);
        
        // Go and upgrade our site (Will check if it needs to do the work or not)
        // Based on the current/latest step
        var upgrader = new Upgrader(migrationPlan);
        upgrader.Execute(
            _migrationPlanExecutor,
            _coreScopeProvider,
            _keyValueService);
    }
}
Its using a notifcation
@David Brendel shall we jump in a breakout room in zoom?
d

David Brendel

10/21/2022, 3:01 PM
Sure lets do that 🙂
m

Matt Wise

10/21/2022, 3:05 PM
We can move ourselves in now 🙂