Skip to content

Add EF Core 7 style JSON support (owns & ToJson) #1752

@mkozlina

Description

@mkozlina

Code

using Microsoft.EntityFrameworkCore;

public enum OrderStatus
{
    Pending,
    Shipped
}

public class StreetAddress
{
    public string Street { get; set; }
    public string City { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public OrderStatus Status { get; set; }
    public StreetAddress ShippingAddress { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<Order> Orders { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseMySql(
                "Server=localhost;Database=test;User=root",
                new MySqlServerVersion(new System.Version(8, 0)),
                o => o.UseMicrosoftJson());
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>()
            .OwnsOne(
                p => p.ShippingAddress,
                nb => nb.ToJson());
    }
}

public static class Program
{
    public static void Main(string[] args)
    {
        using var context = new MyContext();

        context.Database.EnsureDeleted();
        context.Database.EnsureCreated();

        context.Add(new Order
        {
            Id = 101,
            Status = OrderStatus.Pending,
            ShippingAddress = new StreetAddress { City = "London", Street = "221 B Baker St" }
        });

        context.SaveChanges();
    }
}

Steps to reproduce

  1. Build
  2. Add migration
  3. Run

The issue

Throws a DbUpdateException on context.SaveChanges(), with an inner InvalidCastException saying that it cannot cast from 'String' to 'JsonElement'.

Exception message: Invalid cast from 'System.String' to 'System.Text.Json.JsonElement'.
Stack trace:
   at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter`2.Sanitize[T](Object value)
   at Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter`2.<>c__DisplayClass4_0`2.<SanitizeConverter>b__1(Object v)
   at Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping.CreateParameter(DbCommand command, String name, Object value, Nullable`1 nullable, ParameterDirection direction)
   at Microsoft.EntityFrameworkCore.Storage.Internal.TypeMappedRelationalParameter.AddDbParameter(DbCommand command, Object value)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalParameterBase.AddDbParameter(DbCommand command, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.CreateDbCommand(RelationalCommandParameterObject parameterObject, Guid commandId, DbCommandMethod commandMethod)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)

Further technical details

Database version: MySQL v8.0.27 and MariaDB v10.6.11
Operating system: Windows 10 build 19044.2486
Pomelo.EntityFrameworkCore.MySql version: 7.0.0
Microsoft.AspNetCore.App: 6.0.13 and 7.0.2

Other info

I tried this on multiple machines and always end up with the same exception. It only happens when aggregating to JSON (nb.ToJson()).

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions