how to do a classmapping (nh3.2) and a many_to_many set

31 views
Skip to first unread message

ike

unread,
Aug 12, 2011, 5:26:15 PM8/12/11
to nhusers
Hi,

I'm looking at the new classmapping stuff that got added in the 3.2
release of nh.

To test this out, I'm converting the hbm-mappings of the alexandria
project to classmappings.
However, I'm running into a problem when mapping a set or a list.
Exception: unknown column "elt".
Clearly there's something wrong in the my mappings, but I just can't
seem to figure it out.

Alexandria:
https://github.com/ayende/Alexandria

I will paste a portion of the hbm (which works)
<set name="CurrentlyReading" table="UsersReadingBooks">
<key column="`User`"/>
<many-to-many class="Book" column="Book"/>
</set>

portion of my mapping (which doesn't work)
Set(x => x.CurrentlyReading, mapper =>
{

mapper.Table("UsersReadingBooks");
mapper.Key(y =>
y.Column("`User`"));
}, element =>
{
element.ManyToMany(y
=>
{

y.Class(typeof (Book));

y.Column("Book");

y.ForeignKey("Book");
});
element.Element(y =>
y.Column("Book"));
});
My guess was that y.Column in the manytomany would be sufficient, but
it's not. That's why I tried all the things that looked like it could
be that too. But it still doesn't work.

Can someone see what's wrong with my mapping?

Thanks,
Ike

letspirate

unread,
Aug 13, 2011, 6:48:26 AM8/13/11
to nhusers
hi guys

does anyone know how to create many-to-may relationship in mapping by
code in NHibernate 3.2?

thanks in advance

Fabio Maulo

unread,
Aug 13, 2011, 4:34:46 PM8/13/11
to nhu...@googlegroups.com
Where you wrote:
element.Element(y => y.Column("Book")); 
which are the others methods of "element" ?

ike

unread,
Aug 15, 2011, 4:33:15 PM8/15/11
to nhusers
Hi Fabio,

I think you want me to find the solution by guiding me to it (which is
cool), but I still don't see it (or I didn't understand your remark).

element has following methods
-> Component (if I use this, complains that "Book" is mapped as an
entity and a component (ambigues mapping))
-> Element -> using this one
-> ManyToAny (and a generic one) -> it's manytomany
-> ManyToMany -> using this one
-> OneToMany -> it's manytomany

Best regards,
Ike

José F. Romaniello

unread,
Aug 17, 2011, 8:56:46 AM8/17/11
to nhu...@googlegroups.com
ike, for me it seems that with your fluent code you  are trying to map a "Dictionary" instead of a plain collection... something like this should work:

           mapper.Class<YourClass>(map => map.Set(p => p.CurrentlyReading,
                                         set => set.Cascade(Cascade.All),
                                         rel => rel.ManyToMany()));

ike

unread,
Aug 17, 2011, 4:05:16 PM8/17/11
to nhusers
Hi José,

I'm using classmapping
public class UserMapping : ClassMapping<User>

but the "Set" method looks the same as doing it directly via the
mapper.Class method.

The difference I see, is the cascade that got added and the rest that
is ommited.
I have tried the code above, but I get the same results.

I have added below my entire code (entities, mapping and a bit of
dbinfo), that might help pinpoint my problem.

Thanks,
Ike


Here's the full code of the entities
public class User
{
public virtual long Id { get; set; }

public virtual string Name { get; set; }
public virtual Address Address { get; set; }

public virtual IList<Book> Recommendations { get; set; }
public virtual IList<Book> Queue { get; set; }
public virtual ICollection<Book> CurrentlyReading { get; set; }
public virtual ICollection<Subscription> Subscriptions { get; set; }
}
public class Book
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual string ImageUrl { get; set; }
public virtual byte[] Image { get; set; }
public virtual string Author { get; set; }
}
public class Address
{
public virtual string Street { get; set; }
public virtual string Country { get; set; }
public virtual string City { get; set; }
public virtual string ZipCode { get; set; }
public virtual string HouseNumber { get; set; }
}
public class Subscription
{
public virtual long Id { get; set; }
public virtual int NumberOfPossibleBooksOut { get; set; }
public virtual decimal MonthlyCost { get; set; }
public virtual string CreditCard { get; set; }
public virtual User User { get; set; }
public virtual DateTime Start{ get; set; }
public virtual DateTime End { get; set; }
}


Here's my mapping code
public class UserMapping : ClassMapping<User>
{
public UserMapping()
{
Table("Users");

Id(x => x.Id, mapper =>
mapper.Generator(Generators.HighLow));

Property(x => x.Name, mapper =>
mapper.NotNullable(false));

Component(x => x.Address, mapper =>
{
mapper.Property(y =>
y.Street);
mapper.Property(y =>
y.Country);
mapper.Property(y =>
y.City);
mapper.Property(y =>
y.ZipCode);
mapper.Property(y =>
y.HouseNumber);
});

List(x => x.Queue, mapper =>
{
mapper.Table("UsersWaitingBooks");
mapper.Key(y =>
y.Column("`User`"));
mapper.Index(y =>
y.Column("`Index`"));
}, element =>
{
element.ManyToMany(y =>
{

y.Class(typeof (Book));

y.Column("Book");
});
element.Element(y =>
y.Column("Book"));
});

List(x => x.Recommendations, mapper =>
{

mapper.Table("UsersRecommendedBooks");
mapper.Key(y =>
y.Column("`User`"));
mapper.Index(y =>
y.Column("`Index`"));
}, element =>
{

element.ManyToMany();
element.Element(y
=> y.Column("Book"));
});
Set(x => x.CurrentlyReading, mapper =>
{

mapper.Cascade(Cascade.All);

mapper.Table("UsersReadingBooks");
mapper.Key(y =>
y.Column("`User`"));
}, element =>
{
element.Element(er =>
er.Column("Book"));
element.ManyToMany(z
=> z.ForeignKey("Book"));
});
Set(x => x.Subscriptions, mapper => mapper.Key(y =>
y.Column("`User`")), element => element.OneToMany());
}
}

public class SubscriptionMapping : ClassMapping<Subscription>
{
public SubscriptionMapping()
{
Table("Subscriptions");

Id(x => x.Id, mapper =>
mapper.Generator(Generators.HighLow));

Property(x => x.NumberOfPossibleBooksOut, mapper =>
mapper.NotNullable(false));
Property(x => x.CreditCard, mapper =>
mapper.NotNullable(false));
Property(x => x.MonthlyCost, mapper =>
mapper.NotNullable(false));
Property(x => x.Start, mapper =>
mapper.NotNullable(false));
Property(x => x.End, mapper =>
{
mapper.NotNullable(false);
mapper.Column("`End`");
});
ManyToOne(x => x.User, mapper =>
{
mapper.Column("`User`");
mapper.NotNullable(true);
});
}
}

public class BookMapping : ClassMapping<Book>
{
public BookMapping()
{
Table("Books");

Id(x => x.Id, mapper =>
mapper.Generator(Generators.HighLow));

Property(x => x.Name, mapper =>
mapper.NotNullable(false));
Property(x => x.ImageUrl, mapper =>
mapper.NotNullable(false));
Property(x => x.Image, mapper =>
{
mapper.NotNullable(false);
mapper.Length(131072);
});
Property(x => x.Author, mapper =>
mapper.NotNullable(false));
}
}

The database has UserS, BookS, UsersReadingBooks tables.
The UsersReadingBooks has 2 columns (Book, User)

ike

unread,
Aug 19, 2011, 4:44:54 PM8/19/11
to nhusers
Hi,

I think there might be a bug here.
It has to do with the "casing"

The mapping.
Set(x => x.CurrentlyReading, mapper =>
{
mapper.Table("UsersReadingBooks");
mapper.Key(y => y.Column("`User`"));
}, element =>
{
element.ManyToMany(y =>
{
y.Class(typeof(Book));
y.Column("Book");
//y.Column("book");
});
});

Generated sql:
SELECT currentlyr0_.[User] as User1_1_, currentlyr0_.elt as elt1_,
book1_.Id as Id4_0_, book1_.Name as Name4_0_, book1_.ImageUrl as
ImageUrl4_0_, book1_.Image as Image4_0_, book1_.Author as Author4_0_
FROM UsersReadingBooks currentlyr0_ left outer join Books book1_ on
currentlyr0_.elt=book1_.Id WHERE currentlyr0_.[User]=?

The problem is the "currentlyr0_.elt"-column that doesn't exists. This
should be "currentlyr0_.Book".

However is I use y.Column("book") -> all in lowercase, then the
generated sql is as it should be

Best regards,
Ike
Reply all
Reply to author
Forward
0 new messages