NHibernate将0保存到多对一列而不是null

NHibernate将0保存到多对一列而不是null,nhibernate,Nhibernate,我有一个表,其中有一个与活动表相关的活动ID列。如果此活动未用于此捐赠,我需要在“活动ID”列中插入0,而不是Null 捐款表中的映射如下所示: <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true"> <class name="Donation,Entities" lazy="true" table="Donations" dynamic-update="true" >

我有一个表,其中有一个与活动表相关的活动ID列。如果此活动未用于此捐赠,我需要在“活动ID”列中插入0,而不是Null

捐款表中的映射如下所示:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
    <class name="Donation,Entities" lazy="true" table="Donations" dynamic-update="true" >
        <id name="DonationID" column="PledgeID" type="Int64">
            <generator class="native" />
        </id>
        <many-to-one name="FundraisingCampaign" class="Campaign, Entities" column="CampaignID" lazy="proxy" not-found="ignore" cascade="none" />
问题是,我在尝试保存时收到一条错误消息“对象引用了一个未保存的临时实例-在刷新之前保存该临时实例”

我不明白为什么它关心我的活动对象上除了活动ID以外的任何东西,因为我有cascade=“none”它不应该尝试将任何东西保存到活动表中


当前系统强迫我在那里设置0而不是Null,因此保存Null不是一个选项。

尝试从DB加载DB标识为0的活动对象。然后它将是一个完全持久化的对象。然后,您应该能够设置它并坚持捐赠

如果这样做有效,则需要更改活动对象的ID属性映射。Nh无法确定您在此处创建的临时活动对象:

new Campaign() {CampaignID = 0};
实际上是一个分离的对象。您应该做的是在映射中添加一个“未保存的值”,例如,-1。现在Nh可以分辨出DB标识为0的有效分离活动与标识为-1的临时新活动之间的区别。然后记住将新创建的活动的Id设置为-1

  • NHibernate通过检查主键知道是否已经存储了实体。如果为0,则不存储它。您可以在映射中更改此行为
  • 如果尝试保存实体,则所有引用实体必须级联或已存储。这对于NHibernate获取外键很重要。它不能用外键指向内存,它必须在数据库中,所以必须存储。如果情况并非如此,则会收到异常消息
  • 有了这些信息,你应该明白为什么你会有这个问题

    是否使用自动计数器生成活动ID?那么它无论如何都不起作用。(您无法在应用程序中设置id。)除非您使用活动id=0存储活动(请参见下文)

    您可以将活动ID设置为可为null的int,然后默认情况下未保存的值为null

    请注意,您的数据库中有一个活动ID为0的活动。这是一个“空对象”。您需要存储它,例如在设置数据库之后


    如果要避免空对象,就会遇到麻烦。NHibernate在概念上不允许您访问外键,它为您管理外键。你可能可以做一些技巧(例如在拦截器中),但我认为这不值得麻烦。您还必须确保没有外键约束,这也是不好的。

    我将未保存的值设置为-1,并将所有代码更新为现在将活动ID设置为-1,以便创建一个新的。现在,我的活动ID中有0,而不是Null。谢谢,Noel。使用空值比较容易。
    new Campaign() {CampaignID = 0};