My model looks like this:
public class SelectionItem : BaseEntity // BaseEntity ==> id, timestamp stuff
{//blabla}
public class Size : SelectionItem
{//blabla}
public class Adultsize : Size
{//blabla}
I would like to use class-hierarchy-per-table-method of fluent nhibernate
public class SelectionItemMap : BaseEntityMap<Entities.SelectionItem.SelectionItem>
{
public SelectionItemMap()
{
Map(x => x.Name);
Map(x => x.Picture);
Map(x => x.Code);
DiscriminateSubClassesOnColumn("SelectionItemType");
}
}
and reset a DiscriminateSubClassesOnColumn on the following subclass:
public class SizeMap : SubclassMap<Size>
{
DiscriminateSubClassesOnColumn("SizeType")
}
public Adultsize : SubclassMap<Adultsize>
{}
But this doesn't work.
I found a solution on the web: link text
but this method is depreciated according to resharper.
How to solve it? thank you for further informations.
When you use class-hierarchy-per-table-method use use one column as discriminator and then define the value of that descriminator for each concrete class.
Try something like this:
public class SelectionItem : ClassMap<SelectionItem>
{
public SelectionItem()
{
Id(x => x.Id);
DiscriminateSubClassesOnColumn("SelectionItemType");
}
}
public class Size : SubclassMap<Size>
{
public Size()
{
DiscriminatorValue("Size")
DiscriminateSubClassesOnColumn("SizeType");
}
}
public class Adultsize : SubclassMap<Adultsize>
{
public Adultsize()
{
DiscriminatorValue("Adult")
}
}
This doesn't work, DiscriminateSubClassesOnColumn() isn't available in a SubclassMap.
You don't need to add DiscriminateSubClassesOnColumn() in the SubclassMap. It takes the classname as discriminator value.
Correct version of code
public class SelectionItem : ClassMap<SelectionItem>
{
public SelectionItem()
{
Id(x => x.Id);
DiscriminateSubClassesOnColumn("SelectionItemType");
}
}
public class Size : SubclassMap<Size>
{
}
public class Adultsize : SubclassMap<Adultsize>
{
}
Related
I want to upgrade my application to use NHiberante 3 instead of NHibernate 2.1.2 but faced some problems with the new LINQ provider. This question is about one of them. Assume that I have a following hierarchy of classes:
public abstract class PageData
{
public int ID { get; set; }
public string Title { get; set; }
}
public class ArticlePageData : PageData
{
public DateTime PublishedDate { get; set; }
public string Body { get; set; }
}
public class ExtendedArticlePageData : ArticlePageData
{
public string Preamble { get; set; }
}
I use Fluent NHibernate to map these classes to the database:
public class PageDataMap : ClassMap<PageData>
{
public PageDataMap()
{
Table("PageData");
Id(x => x.ID);
Map(x => x.Title);
DiscriminateSubClassesOnColumn("PageType");
}
}
public class ArticlePageDataMap : SubclassMap<ArticlePageData>
{
public ArticlePageDataMap()
{
Join("ArticlePageData", p =>
{
p.KeyColumn("ID");
p.Map(x => x.PublishedDate);
p.Map(x => x.Body);
});
}
}
public class ExtendedArticlePageDataMap : SubclassMap<ExtendedArticlePageData>
{
public ExtendedArticlePageDataMap ()
{
Join("ExtendedArticlePageData", p =>
{
p.KeyColumn("ID");
p.Map(x => x.Preamble);
});
}
}
And then I want to query all pages and do some filtering:
IQueryable<PageData> pages = session.Query<PageData>();
...
var articles = pages.OfType<ArticlePageData>().Where(x => x.PublishedDate >= (DateTime.Now - TimeSpan.FromDays(7))).ToList();
NHibernate 3.0.0 fails with the NotSupported exception in this case, but there is bugfix NH-2375 in the developing version of NH which leads this code to work. But, unfortunately, OfType() method filters the objects by exact type and only selects objects of ArticlePageData class. The old Linq to NH provider selects ArticlePageData and ExtendedArticlePageData in the same case.
How can I do such filtering (select only objects of class T and its subclasses) with the new Linq to NH provider?
session.Query<T>().OfType<SubT>() makes little sense, and it won't let you filter on properties of the subclass. Use session.Query<SubT>() instead.
You can use
var articles = pages.AsEnumerable().OfType<ArticlePageData>().Where(x => x.PublishedDate >= (DateTime.Now - TimeSpan.FromDays(7))).ToList();
and wait for NHibernate 3.0.1.
or maybe you can use
session.Query<ArticlePageData>()
instead of
session.Query<PageData>()
How to override the mapping of generic class?
I have this class:
public abstract class TranslatableEntity<TTranslation, TEntity> : Entity
{
public virtual String Name { get;set; }
// ...
}
And I whant to do this:
public class TranslatableEntityMap<T> : IAutoMappingOverride<TranslatableEntity<T>>
{
public void Override(AutoMapping<TranslatableEntityMap<T>> mapping)
{
mapping.IgnoreProperty(x => x.Name);
}
}
How can I do this?
Thank you!
AFAIK It is not possible. More over it has no sense to map generic class sice mapping requires the real class with implementation.
I don't think it is possible to map generic classes with NHibernate.
I am currently using component maps like this:
public class UserMapping
{
public UserMapping()
{
Id(c => c.Id).GeneratedBy.HiLo("100");
Map(c => c.UserName);
Component(c => c.Country, CountryComponentMapping.Map);
}
}
public sealed class CountryComponentMapping
{
public static void Map(ComponentPart<Country> part)
{
part.Map(x => x.CountryName)
part.Map(x => x.CountryAlpha2)
}
}
I like this becuase I only have to define the mapping for the component/value object in one place.
How would I go about using the same semantics for a collection of the component? (e.g. lets assume we wanted to change this to a collection of countries on the user entity)
You can map this as a Component Collection. Unfortunately there is no overload to HasMany().Component() in Fluent NHibernate that allows you to specify that you want to use a derived class of ComponentMap. You can use a modification of your technique above though.
public sealed class UserMap : ClassMap<User> {
public UserMap() {
Id(c => c.Id).GeneratedBy.HiLo("100");
Map(x => x.Name);
HasMany(x => x.Countries).Component(CountryComponentMapping.Map);
}
}
public sealed class CountryComponentMapping {
public static void Map(CompositeElementBuilder<Country> part) {
part.Map(x => x.CountryName);
part.Map(x => x.CountryAlpha2)
}
}
public class MyObjectMap : IAutoMappingOverride<MyObject>
{
public void Override(AutoMapping<MyObject> mapping)
{
mapping.IgnoreProperty(x => x.InterfaceProperty);
}
}
I am currently doing this in every map... how can I make this into a convention? I am adding conventions like so:
private Action<IConventionFinder> GetConventions()
{
return c =>
{
c.Add<ForeignKeyConvention>();
c.Add<HasManyConvention>();
c.Add<HasManyToManyConvention>();
c.Add<ManyToManyTableNameConvention>();
c.Add<PrimaryKeyConvention>();
c.Add<ReferenceConvention>();
c.Add<TableNameConvention>();
};
}
I think this is not something related to Convention,however it is subject to Mapping Overriding, try this:
public class AutoMapDefaultConfig : DefaultAutomappingConfiguration
{
public override bool ShouldMap(FluentNHibernate.Member member)
{
if (member.Name == "InterfaceProperty")
return false;
return base.ShouldMap(member);
}
}
i haven't try this actually, but I think it may help,and notice that the DefaultAutomappingConfiguration is in Fluent-NHibernate V1.1
I am trying to find the syntax for changing the automap behavior of Fluent NHibernate.
How would I modify the code below to map the UserId property to a column named UserIdentifier (as an example)?
public class MyTypeMap : ClassMap<MyType>
{
public MyTypeMap()
{
Table("MyTypes");
Id(x => x.InstanceId).GeneratedBy.Guid().UnsavedValue(Guid.Empty);
Map(x=> x.UserId);
}
}
Thanks
public class MyTypeMap : ClassMap<MyType>
{
public MyTypeMap()
{
Table("MyTypes");
Id(x => x.InstanceId).GeneratedBy.Guid().UnsavedValue(Guid.Empty);
Map(x=> x.UserId).Column("UserIdentifier");
}
}
public class MyTypeMap : ClassMap<MyType>
{
public MyTypeMap()
{
Id (x => x.InstanceId).Column ("UserIdentifier").GeneratedBy.Guid().UnsavedValue(Guid.Empty);
}
}