Entity Framework / Linq не знает, как десериализовать объект? - PullRequest
0 голосов
/ 06 мая 2020

У меня есть 3 класса:

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 и Dtos совпадают, поэтому я извлечу один виджет, поэтому:

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 используется для преобразования json . Я хочу вычислить напрямую атрибут Widget.LabelConfig, но каждый раз он будет иметь значение null.

Если я попытаюсь преобразовать его после использования EF, будут получены правильные данные:

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

Is это проблема EF / Linq или я что-то делаю не так?

1 Ответ

0 голосов
/ 07 мая 2020

Проблема в том, как работает ядро ​​EF и как структурирован ваш запрос. Ядро EF преобразует все, что находится перед оператором «увлажнения», в SQL, но не знает, что делать с вашим оператором LabelConfig. Однако, как только вы пропустите его через ToListAsync(), сущности станут объектами в памяти, и LINQ может работать так, как вы ожидаете. Итак, что вам нужно сделать, это извлечь необработанные данные и сохранить их в строке, а затем преобразовать их после того, как они будут загружены в память. Это можно сделать, выбрав новый анонимный объект, содержащий ваш виджет и строку, передав ToList() один раз для гидратации, а затем выбрав из этого объекта с выражением JSON, чтобы заполнить его.

...