Help Fluent NHibernate Mapping a Generic Class
I'm hoping somebody can help me with this, I'm trying to write the mapping classes for a class that is subclassed into a generic class. Its easier to descibe with code, so here is my model...
public abstract class TagBase
{
public virtual int Id { get; pri开发者_JS百科vate set; }
public virtual TagTypeEnum TagType { get; set; }
public virtual string Value { get; set; }
public virtual bool IsSystemTag { get; private set; }
public virtual bool isDeleted { get; set; }
public TagBase()
{
}
public TagBase(TagTypeEnum tagType)
{
this.TagType = tagType;
}
public override string ToString()
{
return Value;
}
}
public class Tag<TLinkedItem> : TagBase where TLinkedItem : ITagged<TLinkedItem>
{
public virtual List<TLinkedItem> LinkedItems { get; set; }
}
As you can see Tag
is generic but is constrained to only those classes that implement ITagged<T>
The idea is that an entity has Tags and in turn a tag has a list of LinkedItems that are strongly typed.
Tags cannot be shared amongst different types of entity
I only have two entities in my model that support tagging so far thay are Display
and Asset
I've tried to map this with the following Fluent NHibernate code;
public class TagBaseMap : ClassMap<TagBase>
{
public TagBaseMap()
{
Table("Tag");
Id(tag => tag.Id);
Map(tag => tag.Value).Not.Nullable().Length(50);
Map(tag => tag.IsSystemTag).Not.Nullable();
Map(tag => tag.isDeleted).Not.Nullable();
Map(tag => tag.TagType).CustomType<Int32>().Not.Nullable();
}
}
public class DisplayTagMap : SubclassMap<Tag<Display>>
{
public DisplayTagMap()
{
HasManyToMany(displayTag => displayTag.LinkedItems).Inverse().Table("DisplayTagLink");
}
}
public class AssetTagMap : SubclassMap<Tag<Asset>>
{
public AssetTagMap()
{
HasManyToMany(assetTag => assetTag.LinkedItems).Inverse().Table("AssetTagLink");
}
}
When I try and build the database, I'm targetting Sql Server, from this mapping I'm getting this error "Incorrect syntax near '`'."
Am I right in thinking caused by .Net's naming of generic classes ie,
'{[Model.Tag'1[[Model.Asset, Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].LinkedItems, NHibernate.Mapping.Bag(Model.Tag'1[[Model.Asset, Saturn.ConnectVision.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].LinkedItems)]}'
Am I doing something daft here?
Is there a way around this problem?
Thanks in advance for any advice.
OK, I seemed to have worked around this problem for now.
Here is the mapping for the generic versions of Tag where T : ITagged
public class DisplayTagMap : SubclassMap<Tag<Display>>
{
public DisplayTagMap()
{
HasManyToMany(displayTag => displayTag.LinkedItems).Inverse().Table("DisplayTagLink").ParentKeyColumn("display_id").ChildKeyColumn("tag_id");
}
}
public class AssetTagMap : SubclassMap<Tag<Asset>>
{
public AssetTagMap()
{
HasManyToMany(assetTag => assetTag.LinkedItems).Inverse().Table("AssetTagLink").ParentKeyColumn("asset_id").ChildKeyColumn("tag_id");
}
}
So I'm overriding the generated column names that cause illegal Sql syntax, of course there is the reverse mapping to consider.
public class DisplayMap : ClassMap<Display>
{
public DisplayMap()
{
Id(display => display.Id);
Map(display => display.Name).Not.Nullable();
Map(display => display.DisplayGUID).Not.Nullable();
Map(display => display.Description);
HasManyToMany(display => display.Tags).Cascade.All().Table("DisplayTagLink").ParentKeyColumn("display_id").ChildKeyColumn("tag_id");
}
}
The only issue I now have is that if I put in a DiscriminateSubclassesOnColumn("TagType")
I get the same syntax issue creeping in.
If I miss out this declaration, I end up with two additional tables, Tag_Asset and Tag_Display that just contain a foreign key back to Tag. This is not such a big deal for now.
I've avoided DiscriminateSubClassOnColumn("TagType").SubClass<Tag<Display>>(.....
because this will cause me to have to modify this declaration for each subclass that I add.
精彩评论