NHibernate - Сироты не удаляются - Внешний ключ установлен в нуль - PullRequest
1 голос
/ 30 декабря 2010

Я отправляю коллекцию JSON из Javascript через веб-сервис REST для десериализации с использованием Json.NET и последующего обновления в БД с помощью NHibernate (я использую Fluent).

Мой Json:

{
  "ID": 1,
  "Name": "ObjectName",
  "Keys": [
    {
      "ID": 6,
      "Name": "ID"
    }
  ]
}

Моя трудность заключается в том, что когда я удаляю дочерний элемент из коллекции «Ключ» в Javascript, последующее обновление только обнуляет внешний ключ дочернего элемента - оно фактически не удаляет его.Я настроил то, что я считаю правильным отображением на родительском и дочернем элементах:

Объект Отображение один-ко-многим:

// one-to-many
HasMany(x => x.Keys)
  .KeyColumn("ObjectID")
  .Cascade.AllDeleteOrphan();

Ключ сопоставление многие-к-одному:

// many-to-one
References(x => x.Object)
  .Cascade.None(); 

Код NHibernate, который выполняет обновление:

using (var transaction = Session.BeginTransaction())
  {
    Session.SaveOrUpdate(entity);
    transaction.Commit();
  }
Session.Flush();

Хотя этот пример является двунаправленным, я также пытался однонаправленные сопоставления,но пока это не имело никакого эффекта;дочерняя запись сохраняется в базе данных, хотя сама связь нарушена (FK установлен на ноль).

Что-нибудь очевидно, что я пропускаю?

1 Ответ

2 голосов
/ 31 декабря 2010

Хорошо, проблема здесь заключается в том, что использование десериализатора Json.NET в обычном режиме по существу создает новый объект - этот объект затем сохраняется в NHibernate. Конечным результатом является сохранение записи в базе данных, как и всех дочерних объектов, которые существуют в новой коллекции дочерних объектов - однако удаленные дочерние объекты являются осиротевшими, поскольку они не удаляются непосредственно из сохраняемого объекта NHibernate с помощью .Remove .clear.

Решение состоит из двух частей. Во-первых, мы должны использовать CustomCreationConverter в Json.NET для передачи экземпляра существующего объекта, над которым нужно работать (слияние).

    public static T Deserialize<T>(T existingObject, string json)
    {
        return JsonConvert.DeserializeObject<T>(json, new ObjectConverter<T>(existingObject));
    }

    public class ObjectConverter<T> : CustomCreationConverter<T>
    {
        public T ExistingObject { get; set; }
        public ObjectConverter(T existingObject)
        {
            ExistingObject = existingObject;
        }
        public override T Create(Type objectType)
        {
            return ExistingObject;
        }

    }

Однако это само по себе не сработает, поскольку дочерние коллекции выходящих объектов будут добавлены к дочерними элементами в коллекции json. Исправьте это, и для того, чтобы NHibernate знал, что делать при получении результирующего объекта, нам нужно сделать небольшой взлом Json.NET.

Json.Net> Сериализация> JsonSerializerInternalReader.cs

private object PopulateList(IWrappedCollection wrappedList, JsonReader reader, string reference, JsonArrayContract contract)
{
  // Edit // Clear the collection
  wrappedList.Clear();

После перекомпиляции и повторного добавления DLL - это работает - потомки, которые удалены в javascript, наконец, удаляются и из БД.

...