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.  [ 4 posts ] 
Author Message
 Post subject: <any> and <many-to-any> How do they work?
PostPosted: Mon Aug 11, 2008 3:13 pm 
Newbie

Joined: Fri Nov 16, 2007 6:20 pm
Posts: 15
I've got a situation where I have two tables that basically hold similar entities (but not identical). For business reasons they need to be separate. I want to map them to the same entity if possible although right now I have a wrapper class that just has two sets, one for each entity type.

I can modify the OtherSite table as I wish, but the CTRSite table is outside of my control and in another database.

I'm finding this relationship I've got hard to describe so here is some code:

Code:
public class User : PersistentObjectWithTypedId<Guid>
{
   // Most of the stuff removed for simplicity sake
   public virtual string Name {get; set;}
   public virtual string UserName {get; set;}
   [b]public virtual IList<WorksiteHistory> WorksiteHistories { get; set;} [/b]   
}


Code:
public class WorksiteHistory : PersistentObjectWithTypedId<Guid>
{
   public virtual Boolan Active {get; set;}
   public virtual DateTime DateCreated {get; set;}
   public virtual User User {get; set;}
   // The actual site that may be one of two different entity types (and in different tables)
   [b]public virtual ISite Site {get; set;}[/b]
}


Table:
Code:
CREATE TABLE [dbo].[wsdot_WorksiteHistory](
   [WorksiteHistoryId] [uniqueidentifier] NOT NULL,
   [CTRSiteId] [int] NULL,
   [UserId] [uniqueidentifier] NOT NULL,
   [Active] [bit] NOT NULL,
   [DateCreated] [datetime] NOT NULL,
   [OtherSiteId] [uniqueidentifier] NULL,
    CONSTRAINT [PK_wsdot_WorksiteHistory] PRIMARY KEY CLUSTERED
)


Mapping file This does not work quite like I want!:
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="WSDOT.Core" namespace="WSDOT.Core.Domain">
  <class name="WorksiteHistory" table="wsdot_WorksiteHistory">
    <id name="ID" type="Guid" column="WorksiteHistoryId">
      <generator class="guid.comb" />
    </id>
    <property name="Active" column="Active" type="Boolean" />
    <property name="DateCreated" column="DateCreated" type="DateTime" />
    <many-to-one name="User" column="UserId" class="User" />
    <!--<many-to-one name="Worksite" column="WorksiteId" class="Worksite" />-->
    <any name="Site" meta-type="string" id-type="System.Guid" >
      <meta-value value="CTR" class="CTRSite"/>
      <meta-value value="Other" class="OtherSite"/>
      <column name="CTRSiteId"/>
      <column name="OtherSiteId"/>

    </any>
  </class>
 
</hibernate-mapping>


Code:
public interface ISite
    {
        string Name { get; set;}
        string Address { get; set; }
        string City { get; set; }
        string State { get; set; }
        string Zip { get; set; }
        bool Active { get; set; }
        object ID { get; }
        SiteType Type { get; }
    }


I then have two entities (one table each) that implement ISite:


Code:
public class OtherSite : PersistentObjectWithTypedId<Guid>, ISite
{
public virtual string Name { get; set; }
        public virtual string Address { get; set; }
        public virtual string City { get; set; }
        public virtual string State { get; set; }
        public virtual string Zip { get; set; }
        public virtual bool Active { get; set; }
        public virtual string Owner { get; set; }
        public object ID
        {
            get { return base.ID; }
        }

        public SiteType Type
        {
            get { return SiteType.Other; }
        }
}


Note: CTRSite and OtherSite have different Primary Key types. I can modify them to be the same.

Code:
// Primary key is of Int type
public class CTRSite : PersistentObject, ISite
    {
        public virtual string Name { get; set; }
        public virtual string Address { get; set; }
        public virtual string City { get; set; }
        public virtual string State { get; set; }
        public virtual string Zip { get; set; }
        public virtual bool Active { get; set; }

        public object ID
        {
            get { return base.ID; }
        }

        public SiteType Type
        {
            get { return SiteType.CTR; }
        }
        public virtual Organization Organization { get; set; }
        public virtual IList<Project> Projects { get; set; }


I'm kind of stuck. I don't even know if I'm using the right approach. Thoughts and/or suggestions?

Thanks
Jack


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 10, 2008 5:29 am 
Newbie

Joined: Sun Feb 18, 2007 1:05 pm
Posts: 16
Hi Jack,
I am also in a similar scenario.
Have you got solution for your issue?
Is this the right approch?

Shaiju


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 10, 2008 11:53 am 
Newbie

Joined: Tue Sep 09, 2008 12:48 pm
Posts: 6
Just a guess, here's what I see wrong with your mapping. The column specifier should be Type and ID. One column will hold your class type, specified by the value of your meta tages (CTR or Other), and the other will hold the ID that is owned by that class mapped in NHibernate. So it should look something like this.

Code:
<any name="Site" meta-type="string" id-type="System.Guid" >
      <meta-value value="CTR" class="CTRSite"/>
      <meta-value value="Other" class="OtherSite"/>
      <column name="SiteType"/>
      <column name="SiteId"/>
</any>


Also, your ISite interface should be a GUID for the ID type, instead of an object. That's assuming you don't have that mapped in the CTRSite or OtherSite class.

It would help if you could show the mappings you've got going for CTRSite and OtherSite, that seems to be the missing piece here.

Basically you'd want them to look something like:
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="WSDOT.Core" namespace="WSDOT.Core.Domain">
  <class name="OtherSite" table="wsdot_OtherSite">
    <id name="ID" type="Guid" column="OtherSiteID">
      <generator class="guid.comb" />
    </id>
    <property name="Address" column="Address"  />
    <property name="City" column="City"  />
    <property name="State" column="State"  />
    <property name="Zip" column="Zip"  />
    <property name="Active" column="Active"  />
    <property name="Owner" column="Owner"  />
  </class>
</hibernate-mapping>


then:
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="WSDOT.Core" namespace="WSDOT.Core.Domain">
  <class name="CTRSite" table="wsdot_CTRSite">
    <id name="ID" type="Guid" column="CTRSiteID">
      <generator class="guid.comb" />
    </id>
    <property name="Address" column="Address"  />
    <property name="City" column="City"  />
    <property name="State" column="State"  />
    <property name="Zip" column="Zip"  />
    <property name="Active" column="Active"  />
    <property name="Owner" column="Owner"  />
    <many-to-one name="Organization" column="OrganizationID" class="Organization" />
     <bag name="Projects" cascade="save-update" inverse="true" lazy="true">
    <key column="CTRSiteId"/>
    <one-to-many class="Project" />
  </class>
</hibernate-mapping>


So, something like that (you can use sets instead of bags, but since you're using an IList, I figured bags would be preferable).

But you definately need the mappings for your two Site classes. Otherwise your Any mappings have no clue what to do.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 10, 2008 1:14 pm 
Newbie

Joined: Fri Nov 16, 2007 6:20 pm
Posts: 15
Cool, responses. :) I've actually created a work-around that sort of works. It isn't optimal, and I will have to re-examine it at some point.

Keep in mind I can not modify the CTRSites table structure and it does NOT have a type identifier. This may change, but at the moment that is the way it is.

Mappings:

CTRSite:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping schema="CTRE.dbo" xmlns="urn:nhibernate-mapping-2.2" assembly="WSDOT.Core" namespace="WSDOT.Core.Domain">
  <class name="CTRSite" table="ut_Sites">
    <id name="ID" type="Int32" column="siteKey">
      <generator class="identity" />
    </id>
    <many-to-one name="Organization" column="siteComp" class="Organization" fetch="join" outer-join="false"/>
    <property name="Name" column="siteTitle" type="String" />
    <property name="Address" column="siteAddress" type="String" />
    <property name="City" column="siteCity" type="String" />
    <!--<property name="State" column="siteState" type="String" />-->
    <property name="Zip" column="siteZip" type="String" />
    <property name="Active" column="siteActive" type="Boolean" />
    <bag name="Projects" table="wsdot_SitesInProjects" cascade="save-update" inverse="false" lazy="true" schema="WSDOT_CommuteLog.dbo">
      <key column="siteId" />
      <many-to-many column="projectId" class="Project" />
    </bag>
  </class>
</hibernate-mapping>


OtherSite:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="WSDOT.Core" namespace="WSDOT.Core.Domain">
  <class name="OtherSite" table="wsdot_OtherSites">
    <id name="ID" type="System.Guid" column="SiteId">
      <generator class="guid.comb" />
    </id>
    <property name="Name" column="Name" type="String" />
    <property name="Address" column="Address" type="String" />
    <property name="City" column="City" type="String" />
    <property name="State" column="State" type="String" />
    <property name="Zip" column="Zip" type="String" />
    <property name="Active" column="Active" type="Boolean" />
    <bag name="Projects" table="wsdot_OtherSitesInProjects" cascade="save-update" inverse="false" lazy="true" schema="WSDOT_CommuteLog.dbo">
      <key column="OtherSiteId" />
      <many-to-many column="projectId" class="Project" />
    </bag>
  </class>
</hibernate-mapping>



My current implementation "works", but is cumbersome.

EDIT - WorkSiteHistory has changed too:
Code:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="WSDOT.Core" namespace="WSDOT.Core.Domain">
  <class name="WorksiteHistory" table="wsdot_WorksiteHistory">
    <id name="ID" type="Guid" column="WorksiteHistoryId">
      <generator class="guid.comb" />
    </id>
    <property name="Active" column="Active" type="Boolean" />
    <property name="DateCreated" column="DateCreated" type="DateTime" />
    <many-to-one name="User" column="UserId" class="User" />
    <many-to-one name="CTRSite" class="CTRSite" column="CTRSiteId" />
    <many-to-one name="OtherSite" class="OtherSite" column="OtherSiteId" />
  </class>
 
</hibernate-mapping>


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