Избегайте атрибутов lazyloader - PullRequest
       41

Избегайте атрибутов lazyloader

0 голосов
/ 05 сентября 2018

Я искал, как избежать возврата списка без атрибута lazyLoader , я хочу продолжать использовать lazyLoader, но я не хочу возвращать атрибут, когда я возвращаю весь список моей сущности от моего контроллера

Я работаю с ядром .NET.

[
  {
    "lazyLoader": {},
    "id": "id1"
    "name": "name"
  },
  {
    "lazyLoader": {},
    "id": "id2",
    "name": "name2"
  }
]

Ответы [ 4 ]

0 голосов
/ 14 июня 2019

Проверенный ответ на этот вопрос просто работает для корневого объекта, если у нас много вложенных lazyloaded объектов, это решение не будет работать. Хотя ответ @ Marcello-Barbiani является правильным, но это не хороший способ добавить эту функцию ко всем имеющимся у нас объектам.

Лучший способ - создать новый ContractResolver, полученный из DefaultContractResolver, и проверить, является ли свойство Lazyloader, а затем пропустить его, как показано ниже:

 public class NonLazyloaderContractResolver : DefaultContractResolver
 {
        public new static readonly NonLazyloaderContractResolver Instance = new NonLazyloaderContractResolver();

        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);

            if (property.PropertyName == "LazyLoader")
            {
                property.ShouldSerialize = i => false;                    
            }

            return property;
        }
}

после добавления этого класса выше, передайте его через JsonSerializerSettings при сериализации объекта:

var json = JsonConvert.SerializeObject(newProduct, new JsonSerializerSettings() {
                ContractResolver = new NonLazyloaderContractResolver(),
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                DefaultValueHandling = DefaultValueHandling.Ignore });

и, наконец, если вы используете asp.net core или asp.net core webapi, добавьте этот контракт в качестве контрактного разрешения по умолчанию в файле startup.cs:

services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
        .AddJsonOptions(options =>
        {
            options.SerializerSettings.ContractResolver = new NonLazyloaderContractResolver();
            options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });
0 голосов
/ 03 мая 2019

В Entity Framework, если у вас есть объект, в котором одно или несколько его свойств используют отложенную загрузку, проверьте его имя типа времени выполнения с помощью GetType (). Name. Например, для объекта класса Car вы заметите, что тип среды выполнения на самом деле называется CarProxy , который является временным типом в памяти, созданным Entity Framework с использованием отражение . Базовый тип этого «поддельного» прокси-класса - Car , и имеет все оригинальные свойства Car , но включает в себя дополнительный, называемый LazyLoader для свойств, которые могут в нем нуждаться .

Если вы продолжите проверку этого «поддельного» типа CarProxy , вы также увидите, что Assembly.IsDynamic = true , что указывает на то, что класс был создан динамически с использованием отражения (см. документация ):

var TheCar = DBContext.Cars.Find(1);
Console.WriteLine(TheCar.GetType().Assembly.IsDynamic.ToString()); //will echo "true"

К счастью, Newtonsoft.Json имеет переопределение для метода JsonConvert.SerializeObject () , которое позволяет нам предоставлять базовый тип, так что результирующий JSON не содержит свойств которые не существуют в этом типе. Итак, чтобы исключить свойство LazyLoader , просто укажите BaseType объекта в качестве параметра типа:

var TheCar = DBContext.Cars.Find(1);
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(TheCar, TheCar.GetType().BaseType);

Чтобы убедиться, что вы не получаете циклические эталонные циклы при сериализации (очень высокая вероятность при использовании отложенной загрузки), вызовите сериализатор со следующей настройкой:

var TheCar = DBContext.Cars.Find(1);
var Settings = new Newtonsoft.Json.JsonSerializerSettings
{
    ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(TheCar, TheCar.GetType().BaseType, Settings);

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

0 голосов
/ 30 мая 2019

Я знаю, что это старый, но добавить

public boolean ShouldSerializeLazyLoader() { return false; }

ко всем классам вниз по дереву тех, которые вы хотите сериализовать, и вы получите свободный JSON без Lazyloader.

Ссылка: https://www.newtonsoft.com/json/help/html/ConditionalProperties.htm

0 голосов
/ 05 сентября 2018

Вы можете сделать выборку из своей коллекции, только получив остальные данные. Таким образом, ваши объекты вообще не будут иметь свойства Navigation.

db.YourCollection.Where(your condition)Select(x => new { id = x.id , name = x.name } );
...