Skip to content

Help to detect that a propery is stored in a JSON string #34568

@JonPSmith

Description

@JonPSmith

Users of my EfCore.SchemaCompare library want it to work on databases that uses entries that use JSON column mappings.

My EfCore.SchemaCompare library allows a developer to compare the DbContext.Model against an existing database and it tells you if there are differences between the two sources. The What does EfSchemaCompare check? section in to README tells what the library checks.

To do this I had to dig into all sorts EFCore's metadata and what they do (see EfSchemaCompare/Internal/Stage1Compare to get a feel what I did to create this library.)

I'm currently looking for metadata that tells me what properties are held in a JSON string, but I can't anything so far. I should say that I'm not as good developer as I used to be because I have dementia now (see this section in one of my articles).

What I have found so far

A JSON column is an Owned Type, which makes sense. However its not obvious how you know that it uses JSON columns. I'll keep looking.

Here is my test code

I don't think you need this, but these are the classes and DbContext I'm using at the moment.

classes

public class HeadEntry
{
    public int Id { get; set; }
    public int HeadInt { get; set; }
    public OuterJsonMap JsonParts { get; set; }

    /// <summary>
    /// Useful for debugging
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return $"{nameof(HeadInt)}: {HeadInt}, {nameof(JsonParts)}: {JsonParts}";
    }
}

public class OuterJsonMap
{
    public int OuterInt { get; set; }
    public string OuterString { get; set; }
    public DateTime OuterDate { get; set; }
    public InnerJsonMap InnerJsonMap { get; set; } = null!;

    /// <summary>
    /// Useful for debugging
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return $"{OuterInt}, {OuterString}, {OuterDate}, {InnerJsonMap}";
    }
}

public class InnerJsonMap
{
    public int InnerInt { get; set; }
    public string InnerString { get; set; }
    public DateTime InnerDate { get; set; }

    /// <summary>
    /// Useful for debugging
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return $"{InnerInt}, {InnerString}, {InnerDate}";
    }
}

public class Normal
{
    public int Id { get; set; }
    public string NormalString { get; set; }

    public int NormalExtraId { get; set; }

    public NormalExtra NormalExtra { get; set; }
}

public class NormalExtra
{
    public int NormalExtraId { get; set; }
    public string ExtraString { get; set; }
}

Test DbContext

public class JsonCustomerContext : DbContext
{

    public JsonCustomerContext(DbContextOptions<JsonCustomerContext> options)
        : base(options) {}

    public DbSet<Customer> Customers { get; set; }
    public DbSet<Normal> Normals { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>().OwnsOne(
            headEntry => headEntry.JsonParts, ownedNavigationBuilder =>
            {
                ownedNavigationBuilder.ToJson();
                ownedNavigationBuilder.OwnsOne(contactDetails => contactDetails.Address);
            });
    }
}

Include provider and version information

EF Core version: 8.0.4
Database provider: all
Target framework: .NET 8.0
Operating system: Windows 10
IDE: Visual Studio 2022 17.11

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions