These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Only one side of many-to-many mapping being recognized Join
PostPosted: Sat Jan 27, 2007 9:35 pm 
Newbie

Joined: Sat Jan 27, 2007 8:59 pm
Posts: 3
Location: Troy, Michigan
I am stumped, any suggestions are greatly appreciated. I have given mapping, db & objects later below. I am able to set all properties and write to both Tasks and Developers tables. I am also able to write to the TaskDevelopers tables successfully by doing:

Code:
               mydev.Tasks.Add(mytask);
                        mytask.Developerz.Add(mydev);
                        session.SaveOrUpdate(mytask);
                        session.SaveOrUpdate(mydev);


TaskDevelopers has only one entry for above association due to inverse=true which is good. When I retreive a Developer object using session.get I can see the associated tasks in the Tasks property correctly. But when I retrieve a Task object fromt he db using

Code:
mytask = (Task)session.Get(typeof(BalaHiberDemo1.Task), inTasknum);


I get the correct object with other properties (id, description etc) properly filled in, but Developerz property is empty with count = 0.
Any ideas??

Its the same join table, similar bag definitions but it can recognize one way and not the other developer.tasks IList is okay but task.developerz IList is not, what gives?
Thank you!!

NHibernate version:1.2.0.2002
Database is Firebird embedded 2.0

My mapping doc:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property">
   <class name="BalaHiberDemo1.Task, BalaHiberDemo1" table="Tasks" lazy="false">
      <id name="Id" column="TaskId">
         <generator class="assigned" />
      </id>
      <property name="Description" column="TaskDesc" />
      <property name="StartDate" column="StartDate" />
      <property name="EndDate" column="EndDate" />
      <property name="DueDate" column="DueDate" />
      <bag name="Developerz" table="TaskDevelopers" cascade="none" access="nosetter.camelcase" lazy="false" inverse="false">
         <key column="TASKID" />
         <many-to-many column="DEVID" class="BalaHiberDemo1.Developer, BalaHiberDemo1" />
      </bag>
   </class>
   <class name="BalaHiberDemo1.Developer, BalaHiberDemo1" table="Developers" discriminator-value="?" lazy="false" >
      <id name="Id" column="DevId" access="nosetter.camelcase" unsaved-value="0">
         <generator class="assigned" />
      </id>
      <discriminator column="DevType" />
      <property name="Name" column="DevName" />
      <property name="Department" column="DeptName" />
      <property name="Manager" column="Manager" />
      <component name="Address" class="BalaHiberDemo1.Address, BalaHiberDemo1" access="nosetter.camelcase">
         <property name="Line" column="AddressLine" not-null="false" />
         <property name="City" column="AddressCity" not-null="false" />
         <property name="State" column="AddressState" not-null="false" />
         <property name="Zip" column="AddressZip" not-null="false" />
      </component>
      <bag name="Tasks" table="TaskDevelopers" cascade="none" access="nosetter.camelcase" lazy="false" inverse="true">
         <key column="DevId" />
         <many-to-many column="TaskId" class="BalaHiberDemo1.Task, BalaHiberDemo1" />
      </bag>
      <subclass name="BalaHiberDemo1.Architect, BalaHiberDemo1" discriminator-value="A" lazy="false">
         <property name="Mastery" column="PolyName" />
      </subclass>
      <subclass name="BalaHiberDemo1.Programmer, BalaHiberDemo1" discriminator-value="P" lazy="false">
         <property name="Level" column="PolyName" />
      </subclass>
   </class>
</hibernate-mapping>




Database:
Code:
CREATE TABLE DEVELOPERS(
  DEVID Integer NOT NULL,
  DEVNAME Varchar(50) NOT NULL,
  DEVTYPE Char(1) NOT NULL,
  POLYNAME Varchar(50) NOT NULL,
  DEPTNAME Varchar(50) NOT NULL,
  MANAGER Varchar(50) NOT NULL,
  ADDRESSLINE Varchar(50) NOT NULL,
  ADDRESSCITY Varchar(50) NOT NULL,
  ADDRESSSTATE Varchar(2) NOT NULL,
  ADDRESSZIP Varchar(5) NOT NULL,
  CONSTRAINT DEV_PK PRIMARY KEY (DEVID)
);
CREATE TABLE TASKS(
  TASKID Char(99) NOT NULL,
  TASKDESC Varchar(50) NOT NULL,
  STARTDATE Date,
  ENDDATE Date,
  DUEDATE Date,
  CONSTRAINT TASKS_PK PRIMARY KEY (TASKID)
);
CREATE TABLE TASKDEVELOPERS(
  TASKID Char(99) NOT NULL,
  DEVID Integer NOT NULL,
  CONSTRAINT CATEGORYCONTACTS_PK PRIMARY KEY (TASKID,DEVID)
);

Not very normalized!!

My objects:
[b]
Code:
using System;
using System.Collections;
using System.Text;

namespace BalaHiberDemo1
{
    //**************************************************
    // Classes that encapsulate SQL tables go here
    //**************************************************

    //Start Address
    //*************
    public class Address
    {
        private string line;
        private string city;
        private string state;
        private string zip;

        public string Line
        {
            get { return this.line; }
            set { this.line = value; }
        }

        public string City
        {
            get { return this.city; }
            set { this.city = value; }
        }

        public string State
        {
            get { return this.state; }
            set { this.state = value; }
        }

        public string Zip
        {
            get { return this.zip; }
            set { this.zip = value; }
        }

        public override string ToString()
        {
            return string.Format("{0}{1}{2}{3}{4} {5}", this.line, (this.line != null && this.line.Length > 0 ? "; " : ""),
                this.city, (this.city != null && this.city.Length > 0 ? ", " : ""), this.state, this.zip);
        }
    }
    //End Address

    //Start Programmer
    //***************
    public class Programmer : Developer
    {
        private string level;

        public string Level
        {
            get { return this.level; }
            set { this.level = value; }
        }

        public override string ToString()
        {
            return string.Format("{0}; {1}", this.Name, this.level);
        }
    }
    //End Programmer

    //Start Architect
    //***************
    public class Architect : Developer
    {
        private string mastery;

        public string Mastery
        {
            get { return this.mastery; }
            set { this.mastery = value; }
        }

        public override string ToString()
        {
            return string.Format("{0}; {1}", this.Name, this.mastery);
        }
    }
    //End Architect

    //Start Task
    //**************
    public class Task
    {
        private string id; // User-Entered Char Key Field
        private string description;
        private DateTime startdate;
        private DateTime enddate;
        private DateTime duedate;
        private IList developerz = new ArrayList(); // Many-To-Many Relationship

        public string Id
        {
            get { return this.id; }
            set { this.id = value; }
        }

        public string Description
        {
            get { return this.description; }
            set { this.description = value; }
        }

        public DateTime StartDate
        {
            get { return this.startdate; }
            set { this.startdate = value; }
        }
       
        public DateTime EndDate
        {
            get { return this.enddate; }
            set { this.enddate = value; }
        }
       
        public DateTime DueDate
        {
            get { return this.duedate; }
            set { this.duedate = value; }
        }

        public IList Developerz
        {
            get { return this.developerz; }
        }

        public override string ToString()
        {
            return this.description;
        }
    }
    //End Task

    // Start Developer
    //***************
    public class Developer
    {
        private int id; // Database-Generated Key Field
        private string name;
        private string department;
        private string manager;
        private Address address = new Address(); // Embedded Object Type
        private IList tasks = new ArrayList(); // Many-To-Many Relationship


        public int Id
        {
            get { return this.id; }
        }

        public string Name
        {
            get { return this.name; }
            set { this.name = value; }
        }

        public string Department
        {
            get { return this.department; }
            set { this.department = value; }
        }

        public string Manager
        {
            get { return this.manager; }
            set { this.manager = value; }
        }

        public Address Address
        {
            get { return this.address; }
        }

        public IList Tasks
        {
            get { return this.tasks; }
        }

        public override string ToString()
        {
            return this.name;
        }
    }
    // End Developer

// end namespace
}

_________________
Tis' the gift to be simple, tis the gift to be free, tis the gift to come down where we ought to be - Old Shaker Ballad
Go Pistons!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 28, 2007 1:07 am 
Contributor
Contributor

Joined: Sat Sep 24, 2005 11:25 am
Posts: 198
Doesn't look like you are flushing the session.


Top
 Profile  
 
 Post subject: still have the problem
PostPosted: Sun Jan 28, 2007 11:32 am 
Newbie

Joined: Sat Jan 27, 2007 8:59 pm
Posts: 3
Location: Troy, Michigan
Thank you for the reply Ayende, but flush() does not seem to be the problem.

I do not have trouble writing to the join file. I did put in the flush() just in case and it did not help. Here is an example: I have a record in the join file with a TASKID of "A2" and a DEVID of 4. When I instantiate a Developer object with session.Get with 4, I can see its that its Tasks property is populated with the A2 task object. But when I do session.Get on a Task object with "A2", I get the object back with its other properties (Description, ID) properly filled in, but the Developerz collection property is null (has no objects) !!

I am hoping somebody can throw some light on this, I am a newbie and pretty much stuck at this point.

_________________
Tis' the gift to be simple, tis the gift to be free, tis the gift to come down where we ought to be - Old Shaker Ballad
Go Pistons!


Top
 Profile  
 
 Post subject: Save instead of SaveOrUpdate
PostPosted: Mon Jan 29, 2007 12:45 am 
Beginner
Beginner

Joined: Mon Jan 08, 2007 11:59 pm
Posts: 31
NH documentation suggests that SaveOrUpdate call may misbehave in case of assigned identifiers. Can you try using Save instead of SaveOrUpdate?

Job Samuel


Top
 Profile  
 
 Post subject: Got it!!
PostPosted: Mon Jan 29, 2007 8:21 pm 
Newbie

Joined: Sat Jan 27, 2007 8:59 pm
Posts: 3
Location: Troy, Michigan
Alright guys, I figured this one out and it works fine now!!

Its got to be a pretty basic and well known gotcha, I must have missed it, if not watch out! this one coud get a newbie :-) Here is what happened:

In this line:
Code:
mytask = (Task)session.Get(typeof(BalaHiberDemo1.Task), inTasknum);


intasknum is a .net string variable that was showing up in the debugger with a length of 2 like so "A2" but the database field was char(99) which was expecting left justfied A2 with string of length 99. But I was getting the taskId from a textbox that was had a maxlenth of 2 which is why I believe it was being set to a length of 2. The string variable was working too hard behind the scenes with its dynamic lengths and tripped me up! If you think something different was happening here with the string feel free to post.

Since char(99) seemed like a silly waste of space for a task ID anyways, I did an ALTER TABLE to revise it to a more manageable char(5) and also expanded the texbox length to 5 so that there is no mismatch. Everything works now!

Thanks Job for your reply. I didnt know that saveorUpdate could be problematic, i will watch out for that too.

_________________
Tis' the gift to be simple, tis the gift to be free, tis the gift to come down where we ought to be - Old Shaker Ballad
Go Pistons!


Top
 Profile  
 
 Post subject: Re: Got it!!
PostPosted: Tue Jan 30, 2007 4:02 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
bkolluru wrote:
But I was getting the taskId from a textbox that was had a maxlenth of 2 which is why I believe it was being set to a length of 2.

AFAIK textbox will not rightpad the string to match the maxlength value, it only limits that length can be 5 or less. So, You should do it by sourself...

Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.