문제

a company I am working for is using an ERP and it's legacy database is Oracle. Until now I've used packages (oracle stored procedures) to access data but during the years the number has grown consistently and now I can't manage them anymore.
I was trying to do some experiments with Nhibernate and started mapping few tables.
All the tables have composite primary keys. A brief description:

Table Order (table name: OCSAORH)

OCHORDN (PK) => OrderNumber
OCHAMND (PK)
OCHCOSC (PK) => Company
OCHCLII
...

Table OrderLine (table name: OCSALIN)

OCLORDN (PK) => OrderNumber
OCLAMND (PK)
OCLCOSC (PK) => Company
OCLLINN (PK) => Line Number
OCLSSEQ (PK)
OCLITMN
...

This is my mapping

Order:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MvcOracleNhibernate"
                   namespace="MvcOracleNhibernate.Domain">
  <class name="Order" table="OCSAORH">
    <composite-id>
      <key-property name="Number" column="OCHORDN"></key-property>
      <key-property name="Ver" column="OCHAMND"></key-property>
      <key-property name="Company" column="OCHCOSC"></key-property>
    </composite-id>
    <property name="CustomerCode" column="OCHCLII" type="String" length="10"></property>
    <property name="Reference" column="OCHOCNO" type="String" length="25"></property>
    <property name="Date" column="OCHOCDT" type="Double"></property>
    <bag name="OrderLines" cascade="all-delete-orphan" generic="true" inverse="true" lazy="false">
      <key>
        <column name="OCLORDN" not-null="true"/>
        <column name="OCLAMND" not-null="true"/>
        <column name="OCLCOSC" not-null="true"/>
      </key>
      <one-to-many class="OrderLine" not-found="ignore"/>
    </bag>
  </class>
</hibernate-mapping>

OrderLine:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="MvcOracleNhibernate"
                   namespace="MvcOracleNhibernate.Domain">
  <class name="OrderLine" table="OCSALIN">
    <composite-id>
      <key-property name="Number" column="OCLORDN"></key-property>
      <key-property name="Ver" column="OCLAMND" ></key-property>
      <key-property name="Company" column="OCLCOSC"></key-property>
      <key-property name="Line" column="OCLLINN"></key-property>
      <key-property name="Seq" column="OCLSSEQ"></key-property>
    </composite-id>
    <property name="Item" column="OCLITMN" type="String" length="19"></property>
    <property name="Quantity" column="OCLQTYP" type="Double"></property>
  </class>
</hibernate-mapping>

With these mappings everything works fine; I can load an order and the lazy loading loads my lines. While reading some documentation I've noticed that I haven't defined the many-to-one relation so I've added this:

<many-to-one name="Order" class="Order" lazy="proxy">
  <column name="OCHORDN" not-null="true"/>
  <column name="OCHAMND" not-null="true"/>
  <column name="OCHCOSC" not-null="true"/>
</many-to-one>   

to the OrderLine mapping file.
Now if I run my test app the order is loaded properly but the order lines are not loaded.
I get a {NHibernate.ADOException} = {"could not initialize a collection: ... } I've tried to investigate and noticed that the generated query to retrieve the rows is wrong. This is the SQL:

SELECT 
    orderlines0_.OCLORDN as OCLORDN1_, 
    orderlines0_.OCLAMND as OCLAMND1_, 
    orderlines0_.OCLCOSC as OCLCOSC1_, 
    orderlines0_.OCLLINN as OCLLINN1_, 
    orderlines0_.OCLSSEQ as OCLSSEQ1_, 
    orderlines0_.OCLORDN as OCLORDN13_0_, 
    orderlines0_.OCLAMND as OCLAMND13_0_, 
    orderlines0_.OCLCOSC as OCLCOSC13_0_, 
    orderlines0_.OCLLINN as OCLLINN13_0_, 
    orderlines0_.OCLSSEQ as OCLSSEQ13_0_, 
    orderlines0_.OCLITMN as OCLITMN13_0_, 
    orderlines0_.OCLQTYP as OCLQTYP13_0_, 
    orderlines0_.OCHORDN as OCHORDN13_0_, 
    orderlines0_.OCHAMND as OCHAMND13_0_, 
    orderlines0_.OCHCOSC as OCHCOSC13_0_ 
FROM OCSALIN orderlines0_ 
WHERE 
    orderlines0_.OCLORDN=? 
    and orderlines0_.OCLAMND=? 
    and orderlines0_.OCLCOSC=?

As you can notice the last 3 fields of the select (those with the prefix OCH instead of OCL) aren't members of the OCSALIN table; they are the key of the OCSAORH.
After 1 days spent reading documentation and examples I can't figure out what I am doing wrong.
Is there anybody there who can try to help?

도움이 되었습니까?

해결책

This is the expected behavior. You're defining the foreign keys in your many-to-one mapping. So the columns need to exist in the object you're defining.

I think you want this

<many-to-one name="Order" class="Order" lazy="proxy">
  <column name="OCLORDN" not-null="true"/>
  <column name="OCLAMND" not-null="true"/>
  <column name="OCLCOSC" not-null="true"/>
</many-to-one>   
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top