Problem with Relationship to Aspnet_Users Username Field

35 views
Skip to first unread message

Josh Pollard

unread,
Jun 17, 2009, 2:16:57 PM6/17/09
to Fluent NHibernate
My database is using the aspnet membership provider for all of the
user stuff. I hate guids though, so our tables that have relationships
with the user tables are all tied back to the username field, not
userid. So the table that I'm trying to map is an Order table that has
a field called username in it. Here are my mapping classes:

public Aspnet_UserMap()
{
WithTable("aspnet_Users");


Id(x => x.UserId).GeneratedBy.Guid();
Map(x => x.ApplicationId);
Map(x => x.UserName);
Map(x => x.LoweredUserName);
Map(x => x.MobileAlias);
Map(x => x.IsAnonymous);
Map(x => x.LastActivityDate);

HasManyToMany(x => x.Roles)
.Cascade.All()
.WithTableName("aspnet_UsersInRoles")
.WithParentKeyColumn("UserId")
.WithChildKeyColumn("RoleId");

HasMany<Order>(x => x.Orders)
.AsBag().Cascade.All().Inverse().KeyColumnNames.Add
("UserName");
}

//// and here is the order map

public OrderMap()
{
Id(x => x.Id);
Map(x => x.Submitted);
Map(x => x.DateSubmitted);
/// .... some fields removed to keep this short

References(x => x.User).ColumnName("UserName");
}

But when I try to retrieve an Order by its Id, I get the following
exception:

System.FormatException: Guid should contain 32 digits with 4 dashes
(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)..

Josh Pollard

unread,
Jun 18, 2009, 6:47:47 AM6/18/09
to Fluent NHibernate
here are the hbm files that fluent is exporting:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-
access="">
<class name="Xipp.Model.Aspnet_User, Xipp.Model, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null" table="aspnet_Users"
xmlns="urn:nhibernate-mapping-2.2">
<id name="UserId" type="Guid" column="UserId">
<generator class="guid" />
</id>
<property name="ApplicationId" type="Guid">
<column name="ApplicationId" />
</property>
<property name="UserName" type="String">
<column name="UserName" />
</property>
<property name="LoweredUserName" type="String">
<column name="LoweredUserName" />
</property>
<property name="MobileAlias" type="String">
<column name="MobileAlias" />
</property>
<property name="IsAnonymous" type="Boolean">
<column name="IsAnonymous" />
</property>
<property name="LastActivityDate" type="DateTime">
<column name="LastActivityDate" />
</property>
<bag name="Roles" cascade="all" table="aspnet_UsersInRoles">
<key column="UserId" />
<many-to-many column="RoleId" class="Xipp.Model.Aspnet_Role,
Xipp.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>
<bag name="Orders" cascade="all" inverse="true">
<key column="UserName" />
<one-to-many class="Xipp.Model.Order, Xipp.Model,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>
</class>
</hibernate-mapping>

and the relevant part from the order mapping

<many-to-one foreign-key="UserName" name="User" column="UserName" />

James Gregory

unread,
Jun 18, 2009, 6:58:49 AM6/18/09
to fluent-n...@googlegroups.com
An entity has an Id, and a many-to-one to that entity uses that Id regardless of what the actual field that is the Id is called. All you're doing in your mapping is saying that the many-to-one uses a column called UserName that is a foreign-key to the Id of your Aspnet_User entity.

If you really must use a design like this, then the property-ref attribute is probably what you'll need to use. There's a PropertyRef method on References which should be what you need.

Josh Pollard

unread,
Jun 18, 2009, 7:05:45 AM6/18/09
to Fluent NHibernate
i guess i thought that my users -> orders relationship was a one to
many relationship. there isn't a third table between them that is
doing the mapping.

On Jun 18, 6:58 am, James Gregory <jagregory....@gmail.com> wrote:
> An entity has an Id, and a many-to-one to that entity uses that Id
> regardless of what the actual field that is the Id is called. All you're
> doing in your mapping is saying that the many-to-one uses a column called
> UserName that is a foreign-key to the Id of your Aspnet_User entity.
>
> If you really must use a design like this, then the property-ref
> attribute<http://www.nhforge.org/doc/nh/en/index.html#mapping-declaration-manyt...>is
> probably what you'll need to use. There's a PropertyRef method on
> References which should be what you need.
>

James Gregory

unread,
Jun 18, 2009, 7:15:00 AM6/18/09
to fluent-n...@googlegroups.com
You have two relationships, a one-to-many from user to orders, and a many-to-one from your order to user. The many-to-one can be fixed with the PropertyRef, but I'm not sure if you can have a one-to-many that doesn't use the primary key.

James Gregory

unread,
Jun 18, 2009, 7:16:11 AM6/18/09
to fluent-n...@googlegroups.com
So if you need both, the other alternative is to actually map the username column as the Id in your user mapping. Id(x => x.Username).GeneratedBy.Assigned()

Josh Pollard

unread,
Jun 18, 2009, 7:23:32 AM6/18/09
to Fluent NHibernate
thanks James, I'll give these a try when i get to the office in about
a half hour

On Jun 18, 7:16 am, James Gregory <jagregory....@gmail.com> wrote:
> So if you need both, the other alternative is to actually map the username
> column as the Id in your user mapping. Id(x =>
> x.Username).GeneratedBy.Assigned()
>
> On Thu, Jun 18, 2009 at 12:15 PM, James Gregory <jagregory....@gmail.com>wrote:
>
>
>
> > You have two relationships, a one-to-many from user to orders, and a
> > many-to-one from your order to user. The many-to-one can be fixed with the
> > PropertyRef, but I'm not sure if you can have a one-to-many that doesn't use
> > the primary key.
>

Josh Pollard

unread,
Jun 18, 2009, 9:08:47 AM6/18/09
to Fluent NHibernate
you rock James! That fixed it. And for anyone else who stumbles across
this post, here are my final mappings:

public class Aspnet_UserMap : ClassMap<Aspnet_User>
{
public Aspnet_UserMap()
{
WithTable("aspnet_Users");

Id(x => x.UserId);
Map(x => x.UserName);

Map(x => x.ApplicationId);
Map(x => x.LoweredUserName);
Map(x => x.MobileAlias);
Map(x => x.IsAnonymous);
Map(x => x.LastActivityDate);

HasManyToMany(x => x.Roles)
.Cascade.All()
.WithTableName("aspnet_UsersInRoles")
.WithParentKeyColumn("UserId")
.WithChildKeyColumn("RoleId");

HasMany<Order>(x => x.Orders)
.AsBag().Cascade.All().Inverse().KeyColumnNames.Add
("UserName");
}
}

and my references line in the Order class looks like this:

References(x => x.User).ColumnName("UserName").PropertyRef(x =>
x.UserName);
Reply all
Reply to author
Forward
0 new messages