Øyvind
Øyvind

Reputation: 1610

Specifying the Primary Key when using Fluent NHibernate and AsList()

I have a scenario in which a User entity has a list of country ids, held as IList.

public virtual IList<int> TradeCountries { get; protected set; }

Currently this is mapped as

HasMany(x => x.TradeCountries).Element("TradeCountryId").AsList(x => x.Column("TradeCountryIndex"));

And the resulting table is defined like this

create table TradeCountries (
    User_id INT not null,
   TradeCountryId INT null,
   TradeCountryIndex INT not null,
   primary key (User_id, TradeCountryIndex)
)

This all works fine - however I'd like to make the PK on TradeCountries be User_id, TradeCountryId. I cannot seem to find a way of doing this when mapping with AsList(). Any ideas?

Upvotes: 0

Views: 1194

Answers (1)

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123871

The conversion of collections used in Fluent NHibernate goes (as described here) this way:

// <set>
public virtual ISet<Child> Children { get; set; }    
HasMany(x => x.Children); // <set />

// <bag>
public virtual IList<Child> Children { get; set; }    
HasMany(x => x.Children); // <bag />

// <list>
public virtual IList<Child> Children { get; set; }    
HasMany(x => x.Children).AsList(...; // <list />

The essence / difference of these mappings is in detail described in documentation Understanding Collection performance and Ayende's post: <list>). Extract:

...while <set/> is an unordered collection, of unique elements, a <list/> is a collection of elements where the order matter, and duplicate elements are allowed...

Other words, when using <list> you have to keep PK on the key and index column, because there could be duplicates.

In your case, just <bag> mapping (without explicit .AsList() call) could be efficient enough, you can remove the index column, and move PK to key and element (User_id, TradeCountryId).

NOTE: C# IList still allows to have more "same" elements, you should check it on business layer

Upvotes: 3

Related Questions