开发者

NHibernate - Orphans not deleting - Foreign Key set to null

I'm sending a JSON collection from Javascript through a REST web service to be Deserialized using Json.NET and then finally updated in the DB using NHibernate (I'm using Fluent).

My Json is:

{
  "ID": 1,
  "Name": "ObjectName",
  "Keys": [
    {
      "ID": 6,
  开发者_JAVA百科    "Name": "ID"
    }
  ]
}

My difficulty is that when I remove a child from the 'Key' collection in Javascript, the subsequent update only nulls the foreign key of the child - it doesn't actually delete it. I have setup what I think is the correct mappings on both the parent and child:

Object one-to-many mapping:

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

Key many-to-one mapping:

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

NHibernate code that performs the update:

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

Although this example is bidirectional, I have also attempted uni-directional mappings, but so far this has had no effect; the child record persists in the database, although the association itself is broken (FK set to null).

Anything obvious that I'm missing?


Ok, the problem here lies in the fact that using the Json.NET Deserializer in a normal capacity essentially creates a new object - this object is then persisted by NHibernate. The end result is the record in the database is kept, as are all the child objects that exist in the new child object collection - however children that were removed are orphaned - since the where not removed directly from the persisted NHibernate object using .Remove or .Clear.

The solution is in two parts. Firstly, we have to use the CustomCreationConverter of Json.NET to pass in an instance of the existing object to be worked on (merge).

    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;
        }

    }

This alone will not work however, as the exiting objects child collections will be added to by the children in the json collection. The remedy this, and to ensure that NHibernate knows what to do when receiving the resulting object, we need to do a bit of a Json.NET hack.

Json.Net > Serialization > JsonSerializerInternalReader.cs

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

After re-compiling, and re-adding the DLL - it works - children that are removed in javascript are finally removed from the DB as well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜