tags:

views:

105

answers:

2

Hi all,

I'm new to nhibernate so this should be easy. I have a mapping file as below although I deleted some fields that aren't relevant to this question. The streamfields class contains a bag of fieldmappings. I want the join to be on field_no column but the sql that is sent is on the id field (str_fld_id") as seen below.

I see what the below sql is doing but it's not what I wanted. It's trying to query the field_mappings table based on the values found in the id column str_fld_id in the StreamFields class when I thought it was clear I wanted the field_no to be used on both ends. I say I thought it was clear because the mapping for the field_mapping class has the below attribute and they both have the same named field Below is in my FieldMappings mapping file.

<many-to-one name="FieldNo" cascade="none" column="`Field_No`" not-null="true">

Sql sent

NHibernate: SELECT fkfieldmap0_.[field_no] as field5_1_, fkfieldmap0_.[Mapping_Id] as Mapping1_1_, fkfieldmap0_.[Mapping_Id] as Mapping1_3_0_, fkfieldmap0_.[Std_fld_Id] as Std2_3_0_, fkfieldmap0_.[Field_Position] as Field3_3_0_, fkfieldmap0_.[Field_No] as Field4_3_0_ FROM [Field_Mappings] fkfieldmap0_ WHERE fkfieldmap0_.[field_no]=@p0; @p0 = '20'

StreamFields mapping

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="DataTransfer.StreamFields,DataTransfer" table="`stream_fields`"   lazy="true">
<id name="StrFldId" column="`str_fld_id`" type="int">
<generator class="native" />
</id>
<property type="int" not-null="true" name="FieldNo" column="`field_no`" />
<many-to-one name="StreamId" cascade="none" column="`stream_Id`" />
<bag name="FkFieldMappingsStreamFields" inverse="true" lazy="false" cascade="all">
<key column="`field_no`" />
<one-to-many class="DataTransfer.FieldMappings,DataTransfer"/>
</bag>
</class>

A: 

[Edited - with old comments]

Okay, i think i finally got you right and i might admit the problems i had understanding what you want took me a while and result of the lack of information you provided. In the future please provide the mapping of both tables clarify on the point wheather it is a mapping or a query issue. Thx.

IMO you have misunderstood the idea of a parent/child-relation. The bag you mentioned like to have within the StreamFields class shouldn't be a bag but a direct association. Like this:

<class name="DataTransfer.StreamFields,DataTransfer" table="stream_fields" >
  <id name="StrFldId" column="str_fld_id" type="int">
    <generator class="native" />
  </id>
  <property type="int" not-null="true" name="FieldNo" column="field_no" />
  <many-to-one name="FieldMapping" class="FiueldMapping" column="Field_No" />
</class>

This of course will only work if you have a property of type FiledMapping in your class.

You want to map FieldMapping to the column Field_No within StreamFields class. There can only be one value within this column, so a bag makes no sense at all. If you want to have a bag of course you can keep it the way it already worked but be aware that the 'key-column' within the bag refers to the child table - in an other way it makes no sense cause a ForeignKey has to map to a PrimaryKey on its parent table. This ensures it is unique and set. I really don't want to rant but would strongly encourage you to review the hibernate reference about collection mapping to get a deeper clue however.

Hopely this will solve your problem.

zoidbeck
Thanks for the answer but I don't think that's what I'm looking for. My question is probably written poorly. The problem is that nhibernate is using the wrong column (wrong in terms that I want to use a different one) when automatically collecting the child item belonging to the streamfields class. The sql that was automatically generated is using the 'id' column instead of the column I thought would be used by this:<key column="`field_no`" />Does this make more sense now?
I am still not sure i got you right, but at least i now understand that this is about mapping and not querying. Can you please provide complete mapping of both classes? I don't see where it uses the id column you mentioned. Doesn't it say "WHERE fkfieldmap0_.[field_no]=@p0; @p0 = '20'"?
zoidbeck
true, the name of the field isn't mentioned in the query but it used the values found in the field called 'StrFldId' to try and look up the field mappings when it should be using the values from the field_no field. There is no value 20 in the field_no field but that value is found in the strfldid field. I'll 'answer' my own question to post the mappings.
A: 

Below are the mappings for the classes.

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="DataTransfer.StreamFields,DataTransfer" table="`stream_fields`" lazy="true">
<id name="StrFldId" column="`str_fld_id`" type="int">
  <generator class="native" />
</id>
<property type="string" length="50" name="FieldName" column="`field_name`" />
<property type="int" name="InputFieldPosition" column="`input_field_position`" />
<property type="int" name="Start" column="`start`" />
<property type="int" name="Width" column="`width`" />
<property type="string" length="50" name="Datatype" column="`datatype`" />
<property type="int" not-null="true" name="FieldNo" column="`field_no`" />
<property type="int" name="FieldOrder" column="`field_order`" />
<property type="int" name="StdId" column="`Std_Id`" />
<many-to-one name="StreamId" cascade="none" column="`stream_Id`" />
<bag name="FkFieldMappingsStreamFields" inverse="true" lazy="false" cascade="all">
  <key column="`field_no`" />
  <one-to-many class="DataTransfer.FieldMappings,DataTransfer"/>
</bag>
</class>
</hibernate-mapping>


<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="DataTransfer.FieldMappings,DataTransfer" table="`Field_Mappings`" lazy="false">
<id name="MappingId" column="`Mapping_Id`" type="int">
  <generator class="native" />
</id>
<property type="int" name="StdFldId" column="`Std_fld_Id`" />
<property type="int" name="FieldPosition" column="`Field_Position`" />
<many-to-one name="FieldNo" cascade="none" column="`Field_No`" not-null="true"  property-ref="FieldNo" />
</class>
</hibernate-mapping>

To make things easy on myself, there is one record in stream_fields and the field_no value is 1 and 20 is the value in StrFldId.

SELECT fkfieldmap0_.[field_no] as field5_1_, fkfieldmap0_.[Mapping_Id] as Mapping1_1_, fkfieldmap0_.[Mapping_Id] as Mapping1_3_0_, fkfieldmap0_.[Std_fld_Id] as Std2_3_0_, fkfieldmap0_.[Field_Position] as Field3_3_0_, fkfieldmap0_.[Field_No] as Field4_3_0_ FROM [Field_Mappings] fkfieldmap0_ WHERE fkfieldmap0_.[field_no]=@p0; @p0 = '20' –

Thats what i guessed. See my edits. This cannot be done using hibernate. The bag has to refer to the PK of the parent table, which is strFldId.
zoidbeck
Thanks a lot for your help! Sorry I wasn't clear from the start. I understand parent/child-relations and I will admit my solution is contrived because I'm new to hibernate so I'm looking for easy ways to use it. I realized bag wasn't the proper way to do this but I wanted a reference to the object instead of an id. Field_No in the stream_fields class can not be a unique value although it's unique in a class called data_source_fields. Each data_source_field could be in multiple stream outputs for a giving data_source. I probably should use a composite field linking the two.
Of course you do, and you're welcome. The composite field seems to be a valid solution. Let me know if you need some more help.
zoidbeck
I do need a little more help if you have time. I tried adding the below: <many-to-one name="DataTransfer.FieldMappings" class="DataTransfer.FieldMappings" column="field_no"/>I have DataTransfer.FieldMappings as a property of type DataTransfer.FieldMappings in the stream_fields class and I get the below error. Any idea? "Could not compile the mapping document: DataTransfer.StreamFields.hbm.xml"
I'll post my code as a new answer if you have time to look.