NHibernate:与孩子一起坚持一个对象 [英] NHibernate: Persist an object with children

查看:71
本文介绍了NHibernate:与孩子一起坚持一个对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用子对象集合来持久化对象.由于有FK关系,我不能先坚持孩子.我可以先保存父级,然后再添加子级,但这会带来更多工作.基本上,我只是试图一步一步地保存一个完全填充的对象,而不是将它分成几部分.我的映射是否有问题(对不起,看起来很难看)还是我的方法?

I am trying to persist an object with a collection of child objects. I can't persist the children first as there is a FK relationship. I could save the parent first and then add the children on to it, but this would introduce more work. Basically I'm just trying to save a fully populated object in one step and not break it into parts. Is there something wrong with my mapping (sorry it looks so ugly) or is it my methods?

父母:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="NetworkOrderManagement.Core.Order, NetworkOrderManagement.Core" table="NETORDMGMT.ORDERHEADER" lazy="false" >
    <id name="OrderId" column="ORDERID" type="int">
      <generator class="seqhilo">
        <param name="sequence">ORDERID_SEQ</param>
      </generator>
    </id>
    <property name="TransmissionDate" column="TRANSMISSIONDATE" type="DateTime"/>
    <property name="StoreNumber" column="STORENUMBER" type="Int16"/>
    <property name="Department" column="DEPARTMENT" type="Int16"/>
    <property name="OrderType" column="ORDERTYPE" type="Int16"/>
    <property name="OrderSequence" column="ORDERSEQUENCE" type="Int16"/>
    <property name="ExtractTime" column="EXTRACTTIME" type="DateTime"/>
    <property name="Status" column="STATUS" type="Int16"/>
    <property name="ReceivedTime" column="RECEIVEDTIME" type="DateTime"/>
    <bag name="OrderDetail" table="NETORDMGMT.ORDERDETAIL" 
         lazy="false" cascade="all" inverse="true">
      <key column="ORDERID" on-delete="cascade"/>
      <one-to-many class="NetworkOrderManagement.Core.OrderDetail, NetworkOrderManagement.Core"  />
    </bag>
  </class>
</hibernate-mapping>

孩子:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="NetworkOrderManagement.Core.OrderDetail, NetworkOrderManagement.Core" table="NETORDMGMT.ORDERDETAIL" lazy="false">
    <id name="OrderDetailId" column="ORDERDETAILID" type="int">
      <generator class="seqhilo">
        <param name="sequence">"ORDERDTLID_SEQ"</param>
      </generator>
    </id>
<many-to-one name="Order" class="NetworkOrderManagement.Core.Order, NetworkOrderManagement.Core"
                 column="OrderId" lazy="false" not-null="true" />
    <property name="ItemNumber" column="ITEMNUMBER" type="Int32"/>
    <property name="OrderQuantity" column="ORDERQUANTITY" type="Int32"/>
    <property name="ErrorCode" column="ERRORCODE" type="Int32"/>
  </class>
</hibernate-mapping>

这是我的例外:

Test method NetworkOrderManagement.Tests.DataAccess.QuickTests.QuickTest threw exception:
Distribution.Exceptions.DataAccessException: NHibernate Exception --->
NHibernate.PropertyValueException: not-null property references a null or transient valueNetworkOrderManagement.Core.OrderDetail.Order.

当我的以下测试尝试在订单仍处于瞬态状态时向该订单添加一个orderdetail时,我得到了此提示:

I get this when my test below tries to add an orderdetail to the order while it is still transient:

    [TestMethod]
    public void QuickTest()
    {
        myOrderRepository = NetworkOrderManagement.Data.RepositoryFactory.Instance.GetOrderRepository();
        myOrderDetailRepository = NetworkOrderManagement.Data.RepositoryFactory.Instance.GetOrderDetailRepository();
        myOrder = new Order { StoreNumber = RandGen.LittleRand(), Department = RandGen.LittleRand(), TransmissionDate = DateTime.MinValue, ExtractTime = DateTime.MinValue, ReceivedTime = DateTime.MinValue };
        myOrder = myOrderRepository.Save(myOrder);

        myOrderDetail1 = new OrderDetail {OrderId = myOrder.OrderId, ItemNumber = RandGen.BigRand(), OrderQuantity = RandGen.LittleRand() };
        myOrderDetail2 = new OrderDetail {OrderId = myOrder.OrderId, ItemNumber = RandGen.BigRand(), OrderQuantity = RandGen.LittleRand() };
        myOrderDetail1 = myOrderDetailRepository.Save(myOrderDetail1);
        myOrderDetail2 = myOrderDetailRepository.Save(myOrderDetail2);
        myOrder.OrderDetail.Add(myOrderDetail1);
        myOrder.OrderDetail.Add(myOrderDetail2);

        myOrderRepository.CommitChanges();

        myOrderDetailRepository.Delete(myOrderDetail2);
        myOrderRepository.CommitChanges();
        myOrderRepository.Delete(myOrder);
        myOrderRepository.CommitChanges();
    }

推荐答案

在集合上指定级联,然后让NHibernate为您解决

Specify cascading on the collection, and let NHibernate figure it out for you

http://ayende.com/Blog/archive/2006/12/02/NHibernateCascadesAllAlldeleteorphansAndSaveupdate.aspx之间的不同之间

http://www.hibernate. org/hib_docs/nhibernate/1.2/reference/en/html/example-parentchild.html

好的,我已经知道您已经做到了. :) 您还没有做的是指定反向引用. 我的意思是:您向收藏夹添加了一个项目,但是此添加的项目对其所有者具有尚未设置的属性:

Okay, I've seen that you've done that. :) What you haven't done, is specify the back-reference. I mean: you add an item to your collection, but this added item has a property to its owner, which you haven't set:

Order o = new Order();

OrderDetail detail = new OrderDetail ();

detail.Order = o;
o.OrderLines.Add (detail);

这(简化)会更好(恕我直言):

What would be even better (imho) is this (simplified) :

public class Order
{
    private IList<OrderDetail> _details = new List<OrderDetail>();

    public ReadOnlyCollection<OrderDetail> Details
    {
       return new List(_details).AsReadOnly();
    }

    public void AddOrderLine( OrderDetail d )
    {
        d.Order = this;
        _details.Add (d);
    }

    public void RemoveOrderLine( OrderDetail d )
    {
        _details.Remove (d);
    }
}

这篇关于NHibernate:与孩子一起坚持一个对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆