1

I have two tables:

DIC_STATUS:

STATUS_ID

   1
   2

DIC_STATUS_STRINGS:

STATUS_ID   LANG_ID   STATUS_NAME

    1         1         Name1
    1         2         Name1_1
    2         1         Name2
    2         2         Name2_2

And classes:

public class StatusS : AbstractDictionaryObject
    {
        public virtual string StatusName { get; set; }
        public virtual Languages Lang { get; set; }
        public virtual Status Status { get; set; }
    }

  public class Status:AbstractDisplayDictionary
    {
        [Browsable(false)]
        public IList<StatusS> DicStatusStrings { get; set; }
        public Status()
        {
            DicStatusStrings = new List<StatusS>();
        }
    }

 public abstract class AbstractDisplayDictionary
    {
        [Browsable(false)]
        public virtual int Id { get; set; }
        [DisplayName("Наименование на русском")]
        public virtual string NameRu { get; set; }
        [DisplayName("Наименование на казахском")]
        public virtual string NameKz { get; set; }
    }

Mapping files:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="EArchive.Data" namespace="EArchive.Data.Class">  
  <class name="Status" table="DIC_STATUS" lazy="false">
    <id name="Id" column="STATUS_ID">
      <generator class="increment">
      </generator>
    </id>
    <bag name="DicStatusStrings" inverse="true" cascade="all-delete-orphan">
      <key column="STATUS_ID" />
      <one-to-many class="StatusS" />
    </bag>
    <property name="NameRu"
              formula="(SELECT str.STATUS_NAME FROM DIC_STATUS_STRINGS str
              WHERE str.Status_Id = Status_Id and str.Lang_Id=1)"/>

    <property name="NameKz"
              formula="(SELECT str.STATUS_NAME FROM DIC_STATUS_STRINGS str
              WHERE str.Status_Id = Status_Id and str.Lang_Id=2)"/>    
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="EArchive.Data" namespace="EArchive.Data.Class">
<class name="StatusS" table="DIC_STATUS_STRINGS" lazy="false">
  <composite-id>    
    <key-many-to-one name="Status" class="Status">
      <column name="STATUS_ID"/>
    </key-many-to-one>
    <key-property name="LangId" column="LANG_ID"/>
  </composite-id>
  <property name="StatusName" column="STATUS_NAME"/>
  <many-to-one name="Lang" class="Languages" column="LANG_ID" />  
</class>
</hibernate-mapping>

Method to add record:

 public void AddRecord(object record)
        {
            StatusDAO statusDao = GetStatusDAO();
            var status = (Status) record;
            IList<StatusS> statusS = status.DicStatusStrings;
            status.DicStatusStrings = null;
            status = statusDao.Save(status);

            foreach (var s in statusS)
            {
                s.Status = status;
            }
            status.DicStatusStrings = statusS;
            statusDao.Update(status);
        }

I have error only for adding record, editing works well. Thanks.

EDIT: The Equals and GetHashCode methods is overriden.

user348173
  • 8,818
  • 18
  • 66
  • 102
  • It could be a DB trigger causing this. See here: http://stackoverflow.com/questions/821981/nhibernate-updating-a-table-with-a-trigger-on-it-causes-an-error-unexpected – user2173353 Mar 20 '14 at 12:45

1 Answers1

1

I had the same problem with composite keys. It's related to the Equals() and GetHashCode().

You have to override those, otherwise NHibernate can't know the difference between them.

Have a look here and here for more information.

EDIT: It's actually related to the match between saved and unsaved objects. Missing overrides of Equals and GetHashCode is one of multiple thing which can cause this.

Community
  • 1
  • 1
Jonas Stensved
  • 14,378
  • 5
  • 51
  • 80
  • :I did it, just not written in question. – user348173 Aug 10 '11 at 12:09
  • I noticed inverse="true" on Status.DicStatusStrings. It makes the other side responsible for the relation which might prevent it from getting set if you call update on Status. – Jonas Stensved Aug 10 '11 at 13:27
  • Look at [this thread](https://forum.hibernate.org/viewtopic.php?p=2369496) (the 4th post from the top by "ibaf31"). It suggests using and explains why. – Jonas Stensved Aug 11 '11 at 06:48
  • thanks for link, but I saw it. If I changed to native then throwing following exception: "Cannot insert the value NULL into column 'STATUS_ID', table 'EArchive.dbo.DIC_STATUS'; column does not allow nulls. INSERT fails. The statement has been terminated." in the line: status = statusDao.Save(status);. I have trying add unsaved-value but not works. – user348173 Aug 11 '11 at 09:20
  • Hmm. Do you have the inverse="true" attribute? Add it if not. This error looks like the other end of the relation is being saved before Status has and ID generated. – Jonas Stensved Aug 11 '11 at 09:48
  • Yes, I have it. – user348173 Aug 11 '11 at 10:12