4

I had a mapping for a IDictionary<StocksLocation,decimal> property, this was the mapping:

    HasMany<StocksLocation>(mq => mq.StocksLocation)
        .KeyColumn("IDProduct")
        .AsEntityMap("IDLocation")
        .Element("Quantity",  qt => qt.Type<decimal>()); 

Now i changed from decimal to a Value Object: Quantity.

Quantity has two properties, decimal Value and Unit Unit (where Unit is an enum).

I now have to map IDictionary<StocksLocation,Quantity>, how can i achieve this?

Thanks in advance

Miguel Marques
  • 2,386
  • 1
  • 20
  • 31
  • I don't know if creating an implementation IUserType is a possible solution, i must investigate more the uses of custom types. Is it a possibility? Then o would have: HasMany(mq => mq.StocksLocation) .KeyColumn("IDProduct") .AsEntityMap("IDLocation") .Element("Quantity", qt => qt.Type()); And would it ask for Quantity mapping? I'll give it a try... – Miguel Marques Mar 17 '10 at 14:45
  • Since it's a dictionary, did you mean `HasMany(...)` instead of `HasMany(...)`? – Daniel Schilling Mar 18 '10 at 03:01

1 Answers1

2

Option 1: Map it as an Entity

I'm guessing that your table looks similar to this:

CREATE TABLE Quantity (
    ID int NOT NULL,
    IDProduct int NOT NULL,
    IDLocation int NOT NULL,
    Value decimal(18,2) NOT NULL,
    Unit int NOT NULL,
    PRIMARY KEY (ID),
    FOREIGN KEY (IDProduct) REFERENCES Product (ID),
    FOREIGN KEY (IDLocation) REFERENCES StocksLocation (ID),
    UNIQUE KEY (IDProduct, IDLocation)
);

Go ahead and map Quantity as an entity class:

public class QuantityMap : ClassMap<Quantity>
{
    public QuantityMap()
    {
        Id(x => x.Id);
        References(x => x.Product, "IDProduct");
        References(x => x.Location, "IDLocation");
        Map(x => x.Value);
        Map(x => x.Unit);
    }
}

... and then change the Product.StocksLocation mapping to:

HasMany<StocksLocation, Quantity>(mq => mq.StocksLocation)
    .KeyColumn("IDProduct")
    .AsMap(x => x.Location); 

Option 2: Map it as a Component

Because you commented that you'd rather not map Quantity as an entity, let's consider how we would map this as a component instead. The *.hbm.xml mapping for the Product.StocksLocation dictionary would look like this:

<map name="StocksLocation" table="Quantity">
    <key column="IDProduct" />
    <index-many-to-many column="IDLocation" class="YourNamespace.StocksLocation, YourAssembly" />
    <composite-element class="YourNamespace.Quantity, YourAssembly">
        <property name="Unit" type="YourNamespace.Unit, YourAssembly" />
        <property name="Value" type="System.Decimal, mscorlib" />
    </composite-element>
</map>

How do we do this with FluentNHibernate? As far as I know, there isn't a method for doing this in the trunk, so you have a few options:

  1. Gabriel Schenker implemented a HasManyComponent method. He has a link to the source code for his project, but I don't know whether that source includes the changes he made to FluentNHibernate.
  2. If the source for his changes are not available, feel free to implement your own modifications to FluentNHibernate and submit them back to the community via Github.
  3. If that sounds like too much trouble, FluentNHibernate has an ultimate fallback when all else fails. It allows you to mix and match various mapping methods. Auto-map some of your classes, write ClassMap classes for others, and write a *.hbm.xml file for any classes that can't be mapped with FluentNHibernate.
tinonetic
  • 7,751
  • 11
  • 54
  • 79
Daniel Schilling
  • 4,829
  • 28
  • 60