Use JsonDocument with SQL Server in EF Core 7. The LINQ expression cannot be translated

332 Views Asked by At

I am using EF Core 7. I have a requirement to save dynamic json at run time. I am using the System.Text.Json.JsonDocument class in the class, as shown below.

public class SomeEntity : IDisposable
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Name { get; set; }

    public JsonDocument JsonDocument { get; set; }

    public void Dispose()
    {
        JsonDocument.Dispose();
    }
}

The application can use SQL Server or PostgreSQL. When using PostgreSQL, the JsonDocument type is converted to jsonb in the database. I am able to save and query the json data without any problems.

await _dataContext.SomeEntities
                    .Where(x => x.JsonDocument.RootElement.GetProperty("Name").GetString().Contains(name)
                    )
                    .OrderBy(x => x.JsonDocument.RootElement.GetProperty("DOB"))
                    .ToListAsync();

However, when using Sql Server, I have to provide a Converter OnModelCreating in order for the JsonDocument to work.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
     modelBuilder.Entity<SomeEntity>().Property(e => e.JsonDocument).HasConversion(new JsonDocumentConverter());
}

public class JsonDocumentConverter : ValueConverter<JsonDocument, string>
{
    public JsonDocumentConverter() : base(
        d => d.RootElement.ToString(),
        s => JsonDocument.Parse(s, default))
    { }
}

Using the converter, the JsonDocument will be translated to NVarchar(MAX) in the database. Saving data is working fine, but I am not able to query the data in the JsonDocument. I am getting an exception

System.InvalidOperationException: 'The LINQ expression 'DbSet<SomeEntity>()
.Where(s => s.JsonDocument.RootElement.GetProperty("Name").GetString().Contains(__name_0))' 
could not be translated. Either rewrite the query in a form that can be translated, or
switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 
'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?
linkid=2101038 for more information.'
0

There are 0 best solutions below