0

My code (.NET 8.0 preview 6) to allow ToJson() in SQLite:

using Microsoft.EntityFrameworkCore;

var ctx = new TestContext();
ctx.Database.EnsureCreated();
ctx.Items.ToArray();

class TestContext : DbContext
{
    public DbSet<TestItem> Items { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Data Source=test.db");
        base.OnConfiguring(optionsBuilder);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TestItem>().OwnsMany(ti => ti.Children, builder => builder.ToJson());
    }
}

class TestItem
{
    public required int Id { get; set; }
    public required string Name { get; set; }
    public required List<TestChild> Children { get; set; }
}

class TestChild
{
    public required int Id { get; set; }
    public required string Name { get; set; }
}
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-preview.6.23329.4" />
  </ItemGroup>

</Project>

I get the following error when loading the (empty) items table:

Exception thrown: 'System.ArgumentException' in System.Linq.Expressions.dll An unhandled exception of type 'System.ArgumentException' occurred in System.Linq.Expressions.dll Expression of type 'System.Object' cannot be used for assignment to type 'System.Int32'

It seem related to the children list. I can do a similar model with one child (instead of children) that works. The database is empty at this point so it is not about loaded data content.

user4157124
  • 2,809
  • 13
  • 27
  • 42
maloo
  • 685
  • 1
  • 6
  • 16

1 Answers1

0

The problem is in the Id property of TestChild. There are some conventions regarding properties named Id or suffixed with Id (for example they are discovered as PK). If you change the column type to string and try saving and reading data from the column you will get a message describing the problem:

System.InvalidOperationException: Entity type 'TestChild' is part of a collection mapped to JSON and has its ordinal key defined explicitly. Only implicitly defined ordinal keys are supported.

Rename the column to something like Identifiactor:

class TestChild
{
    public required int Identifiactor { get; set; }
    public required string Name { get; set; }
}

Also check out Columns with name "Id" in JSon object causes System.ArgumentException in materialization issue at github:

owned types that are part of the collection have hard-coded ordinal key named "Id" of type int.

Note that as workaround you can use JsonPropertyName attribute (which seems to be ignored by the EF Core):

class TestChild
{
    [JsonPropertyName("Id")]
    public required int SomeInt { get; set; }
    public required string Name { get; set; }
}
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • Thanks, it got me past DB creation, but once I try to update an item I get: `System.InvalidOperationException: 'The value of shadow key property 'TestChild.Id' is unknown when attempting to save changes. This is because shadow property values cannot be preserved when the entity is not being tracked. Consider adding the property to the entity's .NET type. See https://aka.ms/efcore-docs-owned-collections for more information.'` – maloo Aug 12 '23 at 13:28