FluentNHibernate: How to handle one-to-many values when the many is a simple enum
It seems like the following scenario shouldn't be uncommon, but I can't figure out how to handle it in FluenNHibernate:
public class Product: BaseEntity
{
public Product()
{
Categories = new List<Category>();
}
public virtual IList<Category> Categories { get; set; }
...
}
public enum Categories
{
Classic = 1,
Modern = 2,
Trendy = 3,
...
}
So, I need a ProductCategories table that allows me to map one product to many categories, but I don't think开发者_JAVA百科 NHibernate will handle this unless I have an actual Categories class and a Categories table with a many-to-many relationship specified. There are a number of reasons this is not desirable, not the least of which is that it's overkill.
I'm using AutoMapper - any way I can override to make this work?
Thanks!
This accepted answer worked for me, however the enum was mapped as in int.
To get it to map as a string (my preference) I adapted the mapping as follows:
public void Override(AutoMapping<Account> mapping)
{
mapping
.HasMany(x => x.Categories)
.Table("CategoriesProductsMap")
.Element("Category", e => e.Type<NHibernate.Type.EnumStringType<Category>>())
.AsSet();
}
I had tried the concatenated string in another instance like this, but I really wanted something that didn't need to be transformed every time. As it turns out, I found a very similar question here: Map to a list of Enums?. As described there, this override works:
public void Override(AutoMapping<Product> mapping)
{
mapping.HasMany(x => x.Categories).KeyColumn("ProductFk").Table("CategoriesProductsMap").Element("Category").AsBag();
}
There are a few ways to do this, none of them as straightforward as you might expect. While NHibernate and Fluent NHibernate do quite well with a single enum
, a collection is significantly more troublesom.
Here are a couple of approaches:
- Persist the collection to a single
nvarchar(?)
column by concatenating the members. - Mark the
enum
with theFlags
attribute and collapse the list as a bitmask (this will require just one integer column)
In either case, you can have NHibernate access a field that contains the "collapsed" values; the getters of the public properties will transform the collapsed values to collections. The getter of the collapsed value will transform the collection into a single string (1) or integer (2).
You'd have to map Product
explicitly:
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Id(x => x.Id);
Map(Reveal.Member<Product>("_categories"))
.Access.Field();
}
}
So although Product
exposes an IList<Category>
, NHibernate will only get and set the value of the _categories
field;
At work, while it did not concern a collection of enum value, we created a custom type (by implementing IUserType
to store a IDictionary<CultureInfo, string>
.
We converted the dictionary into a xml document (XDocument) and we stored the data in an Xml column in Sql Server, although any string column could store the value.
You can see this site for information about implementing IUserType
.
精彩评论