JSON.NET и nHibernate Ленивая Загрузка Наборов

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException, что имеет смысл.

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
32
задан Xm7X 3 December 2014 в 21:12
поделиться

4 ответа

Вы получаете круговую ошибку зависимости? Как Вы игнорируете объекты от сериализации?

, Так как ленивая загрузка генерирует объекты прокси, будут потеряны любые атрибуты, которые имеют Ваши участники класса. Я столкнулся с той же проблемой с JSON-сериализатором Newtonsoft, так как объект прокси больше не имел [JsonIgnore] атрибутов.

3
ответ дан 27 November 2019 в 19:59
поделиться

Вы, вероятно, захотите к нетерпеливой загрузке большую часть объекта так, чтобы это могло быть сериализировано:

        ICriteria ic = _session.CreateCriteria(typeof(Person));

        ic.Add(Restrictions.Eq("Id", id));

        if (fetchEager)
        {
            ic.SetFetchMode("Person", FetchMode.Eager);
        }

А хороший способ сделать это должно добавить bool к конструктору (bool isFetchEager) Вашего метода поставщика данных.

3
ответ дан 27 November 2019 в 19:59
поделиться

Я использую NHibernate с Json.NET и заметил, что получаю необъяснимые свойства «__interceptors» в моих сериализованных объектах. Поиск в Google обнаружил это отличное решение Ли Хенсона, которое я адаптировал для работы с Json.NET 3.5 Release 5.

public class NHibernateContractResolver : DefaultContractResolver
{
  private static readonly MemberInfo[] NHibernateProxyInterfaceMembers = typeof(INHibernateProxy).GetMembers();

  protected override List<MemberInfo> GetSerializableMembers(Type objectType)
  {
    var members = base.GetSerializableMembers(objectType);

    members.RemoveAll(memberInfo =>
                      (IsMemberPartOfNHibernateProxyInterface(memberInfo)) ||
                      (IsMemberDynamicProxyMixin(memberInfo)) ||
                      (IsMemberMarkedWithIgnoreAttribute(memberInfo, objectType)) ||
                      (IsMemberInheritedFromProxySuperclass(memberInfo, objectType)));

    var actualMemberInfos = new List<MemberInfo>();

    foreach (var memberInfo in members)
    {
      var infos = memberInfo.DeclaringType.BaseType.GetMember(memberInfo.Name);
      actualMemberInfos.Add(infos.Length == 0 ? memberInfo : infos[0]);
    }

    return actualMemberInfos;
  }

  private static bool IsMemberDynamicProxyMixin(MemberInfo memberInfo)
  {
    return memberInfo.Name == "__interceptors";
  }

  private static bool IsMemberInheritedFromProxySuperclass(MemberInfo memberInfo, Type objectType)
  {
    return memberInfo.DeclaringType.Assembly == typeof(INHibernateProxy).Assembly;
  }

  private static bool IsMemberMarkedWithIgnoreAttribute(MemberInfo memberInfo, Type objectType)
  {
    var infos = typeof(INHibernateProxy).IsAssignableFrom(objectType)
                  ? objectType.BaseType.GetMember(memberInfo.Name)
                  : objectType.GetMember(memberInfo.Name);

    return infos[0].GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length > 0;
  }

  private static bool IsMemberPartOfNHibernateProxyInterface(MemberInfo memberInfo)
  {
    return Array.Exists(NHibernateProxyInterfaceMembers, mi => memberInfo.Name == mi.Name);
  }
}

Чтобы использовать его, просто поместите экземпляр в свойство ContractResolver вашего JsonSerializer. Проблема циклической зависимости, отмеченная jishi, может быть решена путем установки для свойства ReferenceLoopHandling значения ReferenceLoopHandling.Ignore. Вот метод расширения, который можно использовать для сериализации объектов с помощью Json.Net

  public static void SerializeToJsonFile<T>(this T itemToSerialize, string filePath)
  {
    using (StreamWriter streamWriter = new StreamWriter(filePath))
    {
      using (JsonWriter jsonWriter = new JsonTextWriter(streamWriter))
      {
        jsonWriter.Formatting = Formatting.Indented;
        JsonSerializer serializer = new JsonSerializer
          {
            NullValueHandling = NullValueHandling.Ignore,
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            ContractResolver = new NHibernateContractResolver(),
          };
        serializer.Serialize(jsonWriter, itemToSerialize);
      }
    }
  }
18
ответ дан 27 November 2019 в 19:59
поделиться

У нас была именно эта проблема, которая была решена благодаря ответу Мастера здесь.

Проблема возникает из-за того, что JSON.NET не понимает, как сериализовать прокси-классы NHibernate. Решение: сериализуйте экземпляры прокси, как их базовый класс.

Упрощенная версия кода Handcraftsman выглядит следующим образом:

public class NHibernateContractResolver : DefaultContractResolver {
    protected override List<MemberInfo> GetSerializableMembers(Type objectType) {
        if (typeof(INHibernateProxy).IsAssignableFrom(objectType)) {
            return base.GetSerializableMembers(objectType.BaseType);
        } else {
            return base.GetSerializableMembers(objectType);
        }
    }
}

IMHO, этот код имеет то преимущество, что по-прежнему полагается на поведение JSON.NET по умолчанию в отношении настраиваемых атрибутов и т. Д. (И код намного короче!).

Он используется так

        var serializer = new JsonSerializer{
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            ContractResolver = new NHibernateContractResolver()
        };
        StringWriter stringWriter = new StringWriter();
        JsonWriter jsonWriter = new Newtonsoft.Json.JsonTextWriter(stringWriter);                
        serializer.Serialize(jsonWriter, objectToSerialize);
        string serializedObject = stringWriter.ToString();

Примечание: Этот код был написан и использовался с NHibernate 2.1. Как отмечали некоторые комментаторы, это не работает из коробки с более поздними версиями NHibernate, вам придется внести некоторые изменения. Я постараюсь обновить код, если мне когда-нибудь придется сделать это с более поздними версиями NHibernate.

25
ответ дан 27 November 2019 в 19:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: