AlleXyS
AlleXyS

Reputation: 2598

Entity Framework / Linq doesn't know to deserialize object?

I have 3 classes:

public class Widget 
{
     public int Id {get; set;}
     public string Name {get; set;}
     public List<WidgetConfig> Configs {get; set;}
     public LabelConfig LabelConfig {get; set;}
}

public class WidgetConfig 
{
     public int Id {get; set;}
     public string Name {get; set;}
     public string JsonValue {get; set;}
}

public class LabelConfig 
{
     public int Type {get; set;}
     public string Color {get; set;}
     public object Value {get; set;}
}

Entities and Dtos match, so I'll extract one widget so:

var model = await dataContext.Widgets
      .Includes(x => x.Configs)
      .Select(x => new Dtos.Widget() {
         Id = x.Id,
         Name = x.Name,
         Configs = x.Configs.Select(y => new Dtos.WidgetConfig() {
            Id = y.Id,
            Name = y.Name,
            JsonValue = y.JsonValue
         }).ToList(),
         LabelConfig = x.Name == "Test"
             ? JsonConvert.DeserializeObject<LabelConfig>(x.Configs[0].JsonValue)
             : null
        }).ToListAsync();

Newtonsoft.Json is used for converting json. I want to calculate directly Widget.LabelConfig attribute, but this will be null every time.

If I try to convert it after using EF, this will get correct data:

  var jsonValue = model.Configs[0].JsonValue;
  var convertedObject = JsonConvert.DeserializeObject<LabelConfig>(jsonValue);
  model.LabelConfig = convertedObject;

Is it an EF / Linq issue or I do something wrong?

Upvotes: 0

Views: 976

Answers (1)

Nik FP
Nik FP

Reputation: 3063

The issue is in the way EF core works and the way you have your query structured. EF core will convert anything before a "hydrating" statement to SQL, but it doesn't know what to do with your LabelConfig statement. However, once you run it through ToListAsync(), the entities become in-memory objects and LINQ can work as you would expect. So what you need to do is pull the raw data and store it in a string, then convert it after it's been pulled into memory. That can be done by selecting into a new anonymous object that holds your Widget and the string, passing ToList() once to hydrate, then selecting out of THAT object with the JSON expression to fill it in.

Upvotes: 1

Related Questions