Свойство отложенной загрузки, которое является JsonConvert.DeserializeObject другого свойства - PullRequest
2 голосов
/ 03 апреля 2019

Я настраиваю приложение, которое использует EF Core в паре с PostgreSQL, используя драйвер npgsql. Я использую тип поля [jsonb] в PostgreSQL, но в моей модели данных он отображается только на строковое свойство.

public class MyModel
{
     [Column(TypeName = "jsonb")]
     public string JsonData { get; set; }
}

Я хотел бы получить доступ к полю JsonData в качестве свойства словаря. Приведенный ниже код работает, но мне кажется расточительным, поскольку JsonDataDictionary перестраивается при каждом обращении к нему (кэширование).

public class MyModel
{
     [Column(TypeName = "jsonb")]
     public string JsonData { get; set; }

     public Dictionary<string,string> JsonDataDictionary
     {
        get
        {
            return JsonConvert.DeserializeObject<Dictionary<string, string>>(JsonData);
        }
     }
}

Я мог бы сохранить десериализованный объект в первый раз, а затем возвращать его каждый раз. Но ... возможно, что свойство JsonData изменится, поэтому словарь необходимо перестроить.

public class MyModel
{
     [Column(TypeName = "jsonb")]
     public string JsonData { get; set; }

     private Dictionary<string,string> JsonDataDictionary; 
     public Dictionary<string,string> JsonDataDictionary
     {
        get
        {
            if (_JsonDataDictionary == null)
            {
                 _JsonDataDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(JsonData);
            }

            return _JsonDataDictionary;
        }
     }
}

Я думал об использовании какого-либо флага для отслеживания «грязности» свойства JsonData, но кое-что из этого не выглядит наилучшей практикой.

public class MyModel
{
    private string _JsonData;
    private bool _JsonDataChanged = true;

    [Column(TypeName = "jsonb")]
    public string JsonData
    {
        get
        {
            return _JsonData;
        }
        set
        {
            _JsonData = value;
            _JsonDataChanged = true;
        }
    }

    private Dictionary<string,string> _JsonDataDictionary;

    [NotMapped]
    public Dictionary<string,string> JsonDataDictionary
    {
        get
        {
            if (_JsonDataDictionary == null || _JsonDataChanged)
            {
                _JsonDataDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(_JsonData);
                _JsonDataChanged = false;
            }

            return _JsonDataDictionary;
        }
    }
}

Кто-нибудь знает лучший способ сделать это?

ЦЕЛИ: не запускать десериализацию каждый раз, когда вызывается словарь. Тратить как можно меньше циклов. Понимая, что EF Core иногда кэширует кучу этих объектов, я хочу, чтобы объекты словаря загружались только во время их первого доступа (или при изменении строки JsonData).

Я прочитал инициализацию Lazy, но поскольку JsonDataDictionary опирается на строку JsonData, я не думаю, что статическая природа Lazy будет работать. Смотри: https://docs.microsoft.com/en-us/dotnet/framework/performance/lazy-initialization

...