【问题标题】:NHibernate - Orphans not deleting - Foreign Key set to nullNHibernate - 孤儿不删除 - 外键设置为空
【发布时间】:2010-12-30 13:07:13
【问题描述】:

我正在通过 REST Web 服务从 Javascript 发送 JSON 集合,以使用 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 设置为 null),但子记录仍保留在数据库中。

我遗漏了什么明显的东西?

【问题讨论】:

    标签: nhibernate fluent-nhibernate persistence json.net


    【解决方案1】:

    好的,这里的问题在于,在正常容量下使用 Json.NET Deserializer 本质上会创建一个新对象 - 然后这个对象由 NHibernate 持久化。最终结果是保留了数据库中的记录,就像新子对象集合中存在的所有子对象一样 - 但是被删除的子对象是孤立的 - 因为 where 没有使用 .Remove 或直接从持久的 NHibernate 对象中删除.清除。

    解决方案分为两部分。首先,我们必须使用 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 hack。

    Json.Net > 序列化 > JsonSerializerInternalReader.cs

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-23
      • 1970-01-01
      • 2011-01-02
      • 2012-10-22
      相关资源
      最近更新 更多