How do I map a list of value objects?
Take this very simple "order / line item" example:
public class Order
{
public Guid Id { get; private set; }
public string Number { get; private set; }
public IEnumerable<LineItem> Items { get; private set; }
public Order() { } // For NHibernate
public Order(string orderNumber)
{
Number = orderNumber;
}
... Omitted: Methods for adding/removing line items, etc.
}
public class LineItem
{
public Order Order { get; private set; }
public string ProductName { get; private set; }
public int Units { get; private set; }
public decimal UnitPrice { get; private set; }
public LineItem() { } // For NHibernate
public LineItem(Order order, string productName, int units, decimal unitPrice)
{
Order = order;
ProductName = productName;
Units = units;
UnitPrice = unitPrice;
}
}
Order is an entity. LineItem is a value object - hence no id.
How can I map this? If I try this:
.HasMany<OrderLineItem>(x => x.Items)
.Table("OrderLineItems");
I get the error: "Association references unmapped class".
If I try to map LineItems, it complains that it doesn't have an Id (which it shouldn't, because it's not an entity and doesn't stand alone outside an order).
Any ideas? Thanks in advance for your help.
Comments are currently closed for this discussion. You can start a new one.
2 Posted by Jamie C on 19 Feb, 2010 10:00 PM
Holy cow, that got formatted very badly! Anyway, the gist of it is I have an Order object with a list of LineItems. The LineItems do not have Ids - they are value types that don't have any identity outside of an order. They have a reference to their order. The database has an Orders table and a LineItems table. The LineItems table has a column referencing the Order id. I'd like to be able to map this so I can load an Order with all of its LineItems. How would I do that?
Support Staff 3 Posted by James Gregory on 19 Feb, 2010 10:05 PM
I've fixed the formatting for you; it uses markdown (like Stack Overflow), and code blocks need to be indented with 4 spaces (or a tab, I believe).
As for your actual issue, I believe you need the
Component
method chained offHasMany
. For example:4 Posted by Jamie C on 19 Feb, 2010 10:53 PM
Thanks. That gets me closer. I get a good mapping and can use the schema export to see that it creates the tables correctly in in-memory SQLite. Now I can't get the unit test to pass. I try this - using "null" for the order parameter to LineItem since it tells me "order" isn't valid in that context:
That gives me this error:
Is that happening because of trying to save LineItems without a valid Order reference? If so, any idea how I'd get that reference in there? It doesn't take see "order". Is there a way to create the entire order object outside the creation of the PersistenceSpecification? Or is that error pointing to some other problem entirely?
Forgive my ignorance, first go-round with fluent nhibernate.
Support Staff 5 Posted by James Gregory on 19 Feb, 2010 11:14 PM
The
PersistenceSpecification
isn't my strong point, but there is aCheckComponentList
method which I believe you should use in these situations. Any improvement? If not, I'll do some digging.6 Posted by Jamie C on 20 Feb, 2010 03:53 PM
Thanks James! I didn't see that CheckComponentList method. Once I started using that (and fixed a typo in my Equals method) everything worked perfectly. Now if I can just figure out how to make a more generic convention for this (i.e. "Any time a property is a list of anything other than IEntity, treat it as a component list") then I'm all set!
Support Staff 7 Posted by James Gregory on 24 Feb, 2010 03:04 PM
Hey Jamie, how did you get on?
I'm not sure that you will be able to write a convention to do what you need currently; we've got a bit of an internal issue where you can't change what kind of collection is used once it's been initially decided, this is something we'll be fixing in the not too distant future.
8 Posted by Jamie C on 24 Feb, 2010 03:36 PM
Yeah, I ran into issues trying to create my convention. I don't know enough about fluent nhibernate yet to know if it's because it's not supported or just because I'm a novice and don't know how to do it. It's not too big a deal to use component overrides for it though. Still much less than I'd be writing with the old XML files.
Thanks for all of your help!
James Gregory closed this discussion on 04 Mar, 2010 01:13 PM.