我正在通过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)。
我遗失的任何明显的东西?
答案 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中删除的子项最终也会从数据库中删除。