a ja tego nie chce mapować
Jeśli chcesz, żeby móc tam wrzucić wszystkie obiekty klas implementujących ten interfejs no to tak się nie da.
Problem wygląda tak, że NHibernate musi koniec końców stworzyć te tabelki w bazie. Jeśli w klasie A masz kolekcję obiektów klasy B, to w tabeli dla klasy B musi być coś takiego jak id klasy A, np mając klasy:
public class Post
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual ISet<Comment> Comments { get; set; }
public Post()
{
Comments = new HashSet<Comment>();
}
}
public class Comment
{
public virtual int Id { get; set; }
public virtual string Content { get; set; }
}
będzie coś takiego ostatecznym produktem:
i przez to, że tam musi być jakaś tabelka z tym id innej encji leżymy przy takim podejściu.
Na szczęście jest kilka innych:
- Potrzebujemy tam wrzucać obiekty tylko jednej konkretnej klasy, dla której mamy mapowania:
Kod modeli:
public class Post
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual ISet<ISomethingWithContent> Comments { get; set; } // Kolekcja z interfejsem!
public Post()
{
Comments = new HashSet<ISomethingWithContent>();
}
}
public interface ISomethingWithContent
{
string Content { get; set; }
}
public class Comment : ISomethingWithContent
{
public virtual int Id { get; set; }
public virtual string Content { get; set; }
}
Kod mapowań.
public class PostMappings : ClassMap<Post>
{
public PostMappings()
{
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.Title);
Map(x => x.Content);
HasMany<Comment>(x => x.Comments).Cascade.AllDeleteOrphan(); // Jawnie podajemy parametr generyczny na typ konkretnej klasy!!!
}
}
public class CommentMappings : ClassMap<Comment>
{
public CommentMappings()
{
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.Content);
}
}
I generalnie rozwiązanie powyżej ssie, bo po cholerę nam w takim przypadku interfejs.
Jest też inna opcja, że definiujemy klasę zamiast interfejsu i ją mapujemy na normalną tabelę. Później definiujemy klasy pochodne i już używamy SubclassMap<>
zamiast ClassMap<>
, przykład:
public class Post
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual ISet<Content> Contents { get; set; }
public Post()
{
Contents = new HashSet<Content>();
}
}
public class Content
{
public virtual int Id { get; set; }
public virtual string SomeContent { get; set; }
}
public class Comment : Content
{
public virtual bool IsApproved { get; set; }
}
public class NotComment : Content
{
public virtual DateTime DateTime { get; set; }
}
i mapowania:
public class PostMappings : ClassMap<Post>
{
public PostMappings()
{
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.Title);
Map(x => x.Content);
HasMany(x => x.Contents).Cascade.AllDeleteOrphan();
}
}
public class ContentMappings : ClassMap<Content>
{
public ContentMappings()
{
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.SomeContent);
}
}
public class CommentMappings : SubclassMap<Comment>
{
public CommentMappings()
{
Map(x => x.IsApproved);
}
}
public class NotCommentMappings : SubclassMap<NotComment>
{
public NotCommentMappings()
{
Map(x => x.DateTime);
}
}
I teraz diagram się prezentuje tak:
I NHibernate generalnie umie to obsługiwać.
Możesz tutaj poczytać więcej:
http://nhibernate.info/doc/nh/en/#inheritance
http://www.codeproject.com/Articles/232034/Inheritance-mapping-strategies-in-Fluent-Nhibernat
Mam nadzieję, że o to Ci mniej-więcej chodzi. :P
Ofc. Jeśli już będziesz skłonny napisać mapowanie dla tego interfejsu, to on jak najbardziej pasuje (nie musi być klasa, bo z tego co widzę w tych linkach wyżej o tym nie piszą).
Przykład:
public class Post
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual ISet<IContent> Contents { get; set; }
public Post()
{
Contents = new HashSet<IContent>();
}
}
public interface IContent
{
int Id { get; set; }
string SomeContent { get; set; }
}
public class Comment : IContent
{
public virtual int Id { get; set; }
public virtual string SomeContent { get; set; }
public virtual bool IsApproved { get; set; }
}
public class NotComment : IContent
{
public virtual int Id { get; set; }
public virtual string SomeContent { get; set; }
public virtual DateTime DateTime { get; set; }
}
public class PostMappings : ClassMap<Post>
{
public PostMappings()
{
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.Title);
Map(x => x.Content);
HasMany(x => x.Contents).Cascade.AllDeleteOrphan();
}
}
public class ContentMappings : ClassMap<IContent>
{
public ContentMappings()
{
UseUnionSubclassForInheritanceMapping();
Id(x => x.Id).GeneratedBy.Increment();
Map(x => x.SomeContent);
}
}
public class CommentMappings : SubclassMap<Comment>
{
public CommentMappings()
{
Map(x => x.IsApproved);
}
}
public class NotCommentMappings : SubclassMap<NotComment>
{
public NotCommentMappings()
{
Map(x => x.DateTime);
}
}