How to deal with dictionary items in entity for .ToJson functionality
How to deal with dictionary items in Json?
I am banging my head against a wall trying to get a dictionary within a poco to behave nicely when storing the data as Json. I am using EFCore 7.08. Why does this seem so difficult to get done? What am I missing to understand here?. MatchSuccess Has/Owns? a property that is a collection. All I want to get stored is something that looks like reasonable json example of what I want in db:
[{ "Foo": "222", "Bar": "269506", "Meta": { "SpaceId": "123728" } }] //The Meta prop is the issue.
vs what I get in db:
[{"Meta":"{\u0022SpaceId\u0022:\u0022123728\u0022}","Foo":"222","Bar":"269506"}]
As you cannot see... I can easily parse this back out.
setup
I have a very simple POCO like this:
public class MatchSuccess
{
public MatchSuccess()
{
Meta = new Dictionary<string, string>();
}
public string Foo{ get; set; }
public string Bar{ get; set; }
public Dictionary<string, string> Meta { get; set; } // <<<<This is a mess
}
It gets used here:
public class DtoObject:
{
public int Id { get; set; }
public List<MatchSuccess> MatchSuccesses { get; set; } = new List<MatchSuccess>(); //<<<It is a list
public List<MatchFailure> MatchFailures { get; set; } = new List<MatchFailure>();
}
my builder looks like this:
modelBuilder.Entity<DtoObject>(dto=>
{
dto.OwnsMany(e=> e.MatchSuccesses, matchSuccessBuilder =>
{
matchSuccessBuilder.ToJson();
//matchSuccessBuilder.OwnsOne(matchSuccess => matchSuccess.Meta, metaBuilder => { metaBuilder.ToJson();});
// creates : @p1='[{"Foo":"236129","Bar":"888","Meta":{}}]' (Nullable = false)
matchSuccessBuilder.HasOne(matchSuccess => matchSuccess.Meta);
^^^ Throws exception
// matchSuccessBuilder.OwnsOne<Dictionary<string,string>>(c => c.Meta, b => { b.ToJson(); });
// creates: @p1='[{"Foo":"236129","Bar":"888","Meta":{}}]'
// matchSuccessBuilder.Property(p => p.Meta)
// .HasConversion(
// v => JsonSerializer.Serialize(v, options),
// v => JsonSerializer.Deserialize<Dictionary<string, string>>(v, options));
// creates: @p1='[{"Meta":"{\u0022SpaceId\u0022:\u0022236129\u0022}","Foo":"236129","Bar":"888"}]'
});
dto.OwnsMany(e => e.MatchFailures, b => { b.ToJson(); });
my serializer options are:
var options = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = false,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
This thing is slowly killing me.
Include provider and version information
EF Core version: 7.08 Database provider: (e.g. Microsoft.EntityFrameworkCore.SqlServer) Target framework: .NET 6.0 Operating system: IDE: Rider
Note for triage: likely covered by #31257, but not covered by #29427.
@ajcvickers i read the other post regarding primitives and see there was some commits to ef8. Is using the property / conversion the only supported way to do what I need in ef7? Does ef8 support this now to have just a nice array of string,string?
@MacMcDell EF8 will bring 1st-class support for primitive lists/arrays, but not for dictionaries. In both EF7 and 8, to serialize a dictionary you'll have to use a value converter.
Thanks for getting back to me. So the current method I'm using where I serialize manually in and out is pretty much the recommended way? Ie... This.property.hasconversion(in,out)...
On Sun, 16 Jul 2023, 08:05 Shay Rojansky, @.***> wrote:
@MacMcDell https://github.com/MacMcDell EF8 will bring 1st-class support for primitive lists/arrays, but not for dictionaries. In both EF7 and 8, to serialize a dictionary you'll have to use a value converter.
— Reply to this email directly, view it on GitHub https://github.com/dotnet/efcore/issues/31257#issuecomment-1637115366, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALRK5NQKQPDQE6MLIODXVLXQP7L3ANCNFSM6AAAAAA2JAISXU . You are receiving this because you were mentioned.Message ID: @.***>
Yes.
Duplicate of #29825
@ajcvickers it's not a weakly-typed mapping. Seems like I ran into the same issue with strongly typed ImmutableDictionary :(