An interface is implemented by more than one root-entity or no-root-entity, and thus by its own hierarchies, and it is used as a bidirection-one-to-manyTo explain the case I’ll use a chunk of Ayende’s nhibernate-blog-model a little bit complicated for the show-case.
public interface ITagable
{
string Title { get; }
string Summary { get; }
}
public class Blog : Entity, ITagable
{
public Blog()
{
Tags = new HashSet<Tag>();
}
public virtual string Title { get; set; }
public virtual string Subtitle { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public virtual string Summary
{
get { return Subtitle; }
}
}
public class Post : Entity, ITagable
{
public Post()
{
Tags = new HashSet<Tag>();
}
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public virtual string Summary
{
get { return Content != null ? Content.Substring(0, Content.Length < 300 ? Content.Length : 300) : Content; }
}
}
public class Tag : Entity
{
public virtual string Name { get; set; }
public virtual ITagable TagedItem { get; set; }
}
{
string Title { get; }
string Summary { get; }
}
public class Blog : Entity, ITagable
{
public Blog()
{
Tags = new HashSet<Tag>();
}
public virtual string Title { get; set; }
public virtual string Subtitle { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public virtual string Summary
{
get { return Subtitle; }
}
}
public class Post : Entity, ITagable
{
public Post()
{
Tags = new HashSet<Tag>();
}
public virtual string Title { get; set; }
public virtual string Content { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public virtual string Summary
{
get { return Content != null ? Content.Substring(0, Content.Length < 300 ? Content.Length : 300) : Content; }
}
}
public class Tag : Entity
{
public virtual string Name { get; set; }
public virtual ITagable TagedItem { get; set; }
}
- ITagable is implemented by two root-entities (two different hierarchies).
- In Blog and in Post the property Summary does not need to be persisted.
- Blog and in Post has a collection of Tag.
- Tag has a property of type ITagable where I can assign a Blog or a Post.
public static class Program
{
private static void Main(string[] args)
{
var nhinit = new NHibernateInitializer();
nhinit.Initialize();
nhinit.CreateSchema();
ISessionFactory sf = nhinit.SessionFactory;
using (ISession s = sf.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
var blog1 = new Blog();
blog1.Title = "NHibernate blog.";
blog1.Subtitle = "Tricks and tips about NHibernate.";
blog1.Tags.Add(new Tag {Name = "NHibernate", TagedItem = blog1});
var post1 = new Post();
post1.Title = "The difference between Get, Load and querying by id";
post1.Content = "One of the more common mistakes ...";
post1.Tags.Add(new Tag {Name = "NHibernate", TagedItem = post1});
post1.Tags.Add(new Tag {Name = "querying", TagedItem = post1});
s.Save(blog1);
s.Save(post1);
tx.Commit();
}
}
using (ISession s = sf.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
Blog blog1 = (from b in s.Query<Blog>() select b).Single();
Console.WriteLine("Blog: " + blog1.Title + " Tags:" + blog1.Tags.AsString());
Post post1 = (from p in s.Query<Post>() select p).Single();
Console.WriteLine("Post: " + post1.Title + " Tags:" + post1.Tags.AsString());
tx.Commit();
}
}
using (ISession s = sf.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
foreach (Tag tag in from t in s.Query<Tag>() select t)
{
Console.WriteLine("Tag: " + tag.Name);
Console.WriteLine(" Item :" + tag.TagedItem.Title);
Console.WriteLine(" Summary:" + tag.TagedItem.Summary);
}
tx.Commit();
}
}
Console.WriteLine("Work done!");
Console.ReadLine();
sf.Close();
nhinit.DropSchema();
}
private static string AsString(this IEnumerable<Tag> tags)
{
return string.Join(", ", tags.Select(x => x.Name).ToArray());
}
}
{
private static void Main(string[] args)
{
var nhinit = new NHibernateInitializer();
nhinit.Initialize();
nhinit.CreateSchema();
ISessionFactory sf = nhinit.SessionFactory;
using (ISession s = sf.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
var blog1 = new Blog();
blog1.Title = "NHibernate blog.";
blog1.Subtitle = "Tricks and tips about NHibernate.";
blog1.Tags.Add(new Tag {Name = "NHibernate", TagedItem = blog1});
var post1 = new Post();
post1.Title = "The difference between Get, Load and querying by id";
post1.Content = "One of the more common mistakes ...";
post1.Tags.Add(new Tag {Name = "NHibernate", TagedItem = post1});
post1.Tags.Add(new Tag {Name = "querying", TagedItem = post1});
s.Save(blog1);
s.Save(post1);
tx.Commit();
}
}
using (ISession s = sf.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
Blog blog1 = (from b in s.Query<Blog>() select b).Single();
Console.WriteLine("Blog: " + blog1.Title + " Tags:" + blog1.Tags.AsString());
Post post1 = (from p in s.Query<Post>() select p).Single();
Console.WriteLine("Post: " + post1.Title + " Tags:" + post1.Tags.AsString());
tx.Commit();
}
}
using (ISession s = sf.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
foreach (Tag tag in from t in s.Query<Tag>() select t)
{
Console.WriteLine("Tag: " + tag.Name);
Console.WriteLine(" Item :" + tag.TagedItem.Title);
Console.WriteLine(" Summary:" + tag.TagedItem.Summary);
}
tx.Commit();
}
}
Console.WriteLine("Work done!");
Console.ReadLine();
sf.Close();
nhinit.DropSchema();
}
private static string AsString(this IEnumerable<Tag> tags)
{
return string.Join(", ", tags.Select(x => x.Name).ToArray());
}
}
You can implements the class NHibernateInitializer as you want, what is important is that you have to create the DB using NHibernate without touch it by hands and then, obviously, you have to see right results.
One dream one soul one prize one goal
The mapping using ConfORM is:
public HbmMapping GetMapping()
{
var domainEntities = new[] {typeof (Blog), typeof (Post), typeof (Tag)};
var orm = new ObjectRelationalMapper();
var mapper = new Mapper(orm, new CoolPatternsAppliersHolder(orm));
orm.Patterns.PoidStrategies.Add(new HighLowPoidPattern(new {max_lo = 100}));
orm.Patterns.Sets.Add(new UseSetWhenGenericCollectionPattern());
orm.TablePerClass(domainEntities);
orm.Cascade<Blog, Tag>(Cascade.All);
orm.Cascade<Post, Tag>(Cascade.All);
mapper.Customize<Post>(cm => cm.Property(p => p.Content, pm => pm.Type(NHibernateUtil.StringClob)));
return mapper.CompileMappingFor(domainEntities);
}
{
var domainEntities = new[] {typeof (Blog), typeof (Post), typeof (Tag)};
var orm = new ObjectRelationalMapper();
var mapper = new Mapper(orm, new CoolPatternsAppliersHolder(orm));
orm.Patterns.PoidStrategies.Add(new HighLowPoidPattern(new {max_lo = 100}));
orm.Patterns.Sets.Add(new UseSetWhenGenericCollectionPattern());
orm.TablePerClass(domainEntities);
orm.Cascade<Blog, Tag>(Cascade.All);
orm.Cascade<Post, Tag>(Cascade.All);
mapper.Customize<Post>(cm => cm.Property(p => p.Content, pm => pm.Type(NHibernateUtil.StringClob)));
return mapper.CompileMappingFor(domainEntities);
}
When something exceeds your ability to understand how it works, it becomes magical.
ConfORM a kind of magic.