Yulian Dimitrov
Yulian Dimitrov

Reputation: 43

EF Core PostgreSQL jsonb column with POCO binding on nested model object

I have PostgreSQL server and a C# app that uses EF Core as an ORM. This is the scenario I have - main model:

public class TenantSettingsDbModel
{
    [Key]
    public Guid TenantId { get; set; }
    public TenantSettingsModel Settings { get; set; }
}

And,

public class TenantSettingsModel
{
    public RecycleBinRetentionModel RecycleBinRetention { get; set; }
}

and then:

public class RecycleBinRetentionModel
{
    public bool Enabled { get; set; }
    public int Period { get; set; }
}

then I have the following as a DbContext:

public virtual DbSet<TenantSettingsDbModel> TenantSettings { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<TenantSettingsDbModel>().OwnsOne(
        ts => ts.Settings, sNavigationBuilder =>
        {
            sNavigationBuilder.ToJson();
            sNavigationBuilder.OwnsOne(p => p.RecycleBinRetention, rbNavigationBuilder => rbNavigationBuilder.ToJson());
        });
}

Then I want to save a model to the database:

var settings = new TenantSettingsDbModel()
{
    TenantId = tenantId,
    Settings = new TenantSettingsModel
    {
        RecycleBinRetention = new RecycleBinRetentionModel
        {
            Enabled = true,
            Period = 28
        }
    },
};
await this.dbContext.TenantSettings.AddAsync(settings, cancellationToken);
await this.dbContext.SaveChangesAsync(cancellationToken);

But when the SaveChangesAsync() is executed i get this error:

This exception was originally thrown at this call stack:
    System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument) in ThrowHelper.cs
    System.Collections.Generic.Dictionary<TKey, TValue>.FindValue(TKey) in Dictionary.cs
    System.Collections.Generic.Dictionary<TKey, TValue>.TryGetValue(TKey, out TValue) in Dictionary.cs
    Microsoft.EntityFrameworkCore.Update.ModificationCommand.GenerateColumnModifications.__HandleJson|41_4(System.Collections.Generic.List<Microsoft.EntityFrameworkCore.Update.IColumnModification>, ref Microsoft.EntityFrameworkCore.Update.ModificationCommand.<>c__DisplayClass41_0)
    Microsoft.EntityFrameworkCore.Update.ModificationCommand.GenerateColumnModifications()
    Microsoft.EntityFrameworkCore.Update.ModificationCommand.get_ColumnModifications.AnonymousMethod__33_0(Microsoft.EntityFrameworkCore.Update.ModificationCommand)
    Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized<TParam, TValue>(ref TValue, TParam, System.Func<TParam, TValue>)
    Microsoft.EntityFrameworkCore.Update.ModificationCommand.ColumnModifications.get()
    Npgsql.EntityFrameworkCore.PostgreSQL.Update.Internal.NpgsqlUpdateSqlGenerator.AppendInsertOperation(System.Text.StringBuilder, Microsoft.EntityFrameworkCore.Update.IReadOnlyModificationCommand, int, bool, out bool)
    Npgsql.EntityFrameworkCore.PostgreSQL.Update.Internal.NpgsqlUpdateSqlGenerator.AppendInsertOperation(System.Text.StringBuilder, Microsoft.EntityFrameworkCore.Update.IReadOnlyModificationCommand, int, out bool)

The same exception I get when I want to save existing entity:

if (settings != null)
{

    settings.Settings = settingsModel;
    await this.dbContext.SaveChangesAsync(cancellationToken);

    logger.LogInformation($"Settings for tenant {tenantId} saved!...");
}

this throws the same error as above. Is there something that I'm doing wrong to get this exception?

Upvotes: 1

Views: 32

Answers (0)

Related Questions