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.  [ 5 posts ] 
Author Message
 Post subject: Interface - Single class
PostPosted: Tue Oct 14, 2008 11:19 pm 
Newbie

Joined: Tue Oct 14, 2008 10:24 pm
Posts: 3
So i have the following setup:

IUser ITask
O O
| |
User --> Task

I have a simple one table scenario that I'm trying to implement, but am getting several errors. I'm not sure if using this scenario - requires subclass inheritance mappings or not. This is what I'm trying:

User mapping file
Code:
<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="SwiftToDo.BL" assembly="SwiftToDo.BL" default-lazy="false">
  <class name="User" table="tblUser" >
   
    <id column="Id" name="Id" >
      <generator class="native"/>
    </id>
    <property column="FirstName" name="FirstName" not-null="true"/>
    <property column="LastName" name="LastName" not-null="true"/>
    <property column="Email" name="Email" not-null="true"/>
    <property column="Password" name="Password" not-null="true"/>
    <property column="CreateDate" name="CreateDate" not-null="true"/>
    <bag name="Tasks"  table="tblTask"  inverse="true" cascade="all-delete-orphan">
      <key column="UserId"/>
      <one-to-many class="Task" not-found="exception"/>
    </bag>

  </class>
</hibernate-mapping>
 


Task mapping file:

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="SwiftToDo.BL" assembly="SwiftToDo.BL" default-lazy="false" >
  <class name="Task" table="tblTask">
   
    <id name="Id">
      <column name="Id" sql-type="int" not-null="true"/>
      <generator class="native" />
    </id>
    <many-to-one name="User" column="UserId" not-null="true" class="User"/>
    <property name="Name" column="Name" type="string" length="100" not-null="true"/>
    <property name="Description" column="Description" type="string" length="250" not-null="false"/>
    <property name="CreateDate" column="CreateDate" type="DateTime"/>
  </class>
</hibernate-mapping>



This is the error I get:

PropertyAccessException : Invalid Cast (check your mapping for property type mismatches); setter of SwiftToDo.BL.User
----> System.InvalidCastException : Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericBag`1[SwiftToDo.BL.ITask]' to type 'System.Collections.Generic.List`1[SwiftToDo.BL.ITask]'.


I can't seem to figure out what I'm doing wrong here? Before I implemented the interfaces on top of the classes (which I need elsewhere) this stopped working.

_________________
Brett


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 15, 2008 2:06 am 
Regular
Regular

Joined: Tue Jul 29, 2008 3:30 am
Posts: 74
Try to remove the "class" attribute from your many-to-one mapping. Then NHibernate will get the type of the property with reflection and it should work with your interface.

If you want to specify the class explicitly you should try the fully qualified name. Like "SwiftToDo.BL.IUser, Assemblyname".

Btw: I noticed that you didn't specify any type in your User mapping but all types in your Task mapping. Any reason for this?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 15, 2008 11:03 am 
Newbie

Joined: Tue Oct 14, 2008 10:24 pm
Posts: 3
Ok I did remove that class attribute - I shouldn't have pasted that in the code sample - it was something I had just tried (trial and error trying to get it to work).

The reason types were on the Task only was because I wanted to just try using them explicitly to see what kind of behavior I would see.


These are my BL classes - maybe you'll find something in here that might spark something?

Task Object
Code:
    public class Task : ITask
    {
        public Task() { }
        public Task(string taskName)
        {
            Name = taskName;
            CreateDate = DateTime.Now;
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public DateTime CreateDate { get; set; }
        public DateTime ModifiedDate { get; set; }
        public IUser User { get; set; }
        public override string ToString()
        {
            return Name;
        }
    }

User object
Code:
      public class User : IUser
    {
        public List<Task> Tasks { get;   set; }
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
        public DateTime CreateDate { get; set; }

        public void AddTask(Task t)
        {
            if (Tasks == null)
                Tasks = new List<Task>();
            t.User = this;
            Tasks.Add(t);
        }
        public override string ToString()
        {
            return FirstName + " " + LastName;
        }
    }   



I get the same error as in my previous post. If I change the type in the Task class from User to IUser I get this error:

Code:
  The type initializer for 'SwiftToDo.DL.NHDataProvider' threw an exception.
  ----> NHibernate.MappingException : An association from the table tblTask refers to an unmapped class: SwiftToDo.BL.IUser



Hopefully something jumps out at you ?

_________________
Brett


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 16, 2008 2:30 am 
Regular
Regular

Joined: Tue Jul 29, 2008 3:30 am
Posts: 74
Oh right, I forgot something:
If you want to use interfaces (by specifying class="IUser") you have to map your entities to interfaces too:
Code:
<class name="IUser" table="tblUser">

But then the following applies:
Quote:
It is perfectly acceptable for the named persistent class to be an interface. You would then declare implementing classes of that interface using the <subclass> element.


But I think I found your problem (I should have read your exception better, but your code of the User class made it clear):
You have to use IList<Task> instead of List<Task> for the collection.
Because NHibernate uses its own collections internally. These collections implement the .NET collection interfaces but can't be casted to the .NET collection classes of course.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 16, 2008 1:10 pm 
Newbie

Joined: Tue Oct 14, 2008 10:24 pm
Posts: 3
Thanks - I must have refactored that at some point because I totally missed that as well.

What a headache over one little letter! :)

_________________
Brett


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.