NHibernate - 孤儿未删除 - 外键设置为null

时间:2010-12-30 13:07:14

标签: nhibernate fluent-nhibernate persistence json.net

我正在通过REST Web服务从Javascript发送JSON集合,使用Json.NET进行反序列化,最后使用NHibernate在数据库中进行更新(我正在使用Fluent)。

我的Json是:

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

我的困难在于,当我从Javascript中的'Key'集合中删除一个子节点时,后续更新只会使子节点的外键为空 - 它实际上并不删除它。我已经设置了我认为父母和孩子的正确映射:

对象一对多映射:

// 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设置为​​null)。

我遗失的任何明显的东西?

1 个答案:

答案 0 :(得分:2)

好的,这里的问题在于,以正常容量使用Json.NET反序列化器本质上会创建一个新对象 - 然后NHibernate会持久化该对象。最终结果是保留了数据库中的记录,新子对象集合中存在的所有子对象也是如此 - 但是被删除的子对象是孤立的 - 因为不使用.Remove直接从持久化的NHibernate对象中删除.Clear。

解决方案分为两部分。首先,我们必须使用Json.NET的CustomCreationConverter来传递要处理的现有对象的实例(合并)。

    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&gt;序列化&gt; JsonSerializerInternalReader.cs

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

在重新编译并重新添加DLL之后 - 它可以工作 - 在javascript中删除的子项最终也会从数据库中删除。