Lesser-Known NHibernate Features: Mapping By Attributes

Some O/RMs do their mapping based on attributes. LINQ to SQL and Entity Framework are good examples, although Entity Framework also supports mapping by code. I’m not saying this is good or bad – some people think it “pollutes” POCOs, other think it makes them easier to understand -, but, likewise, NHibernate also allows to map entities by attributes, let’s see how.

First, add a reference to the NHibernate.Mapping.Attributes NuGet package:

image

Next, go to your entity and start adding some attributes:

[NHibernate.Mapping.Attributes.Class(Table = "blog", Lazy = true)]

public class Blog

{

    public Blog()

    {

        this.Posts = new List<Post>();

    }


    [NHibernate.Mapping.Attributes.Id(0, Column = "blog_id", Name = "BlogId")]

    [NHibernate.Mapping.Attributes.Generator(1, Class = "hilo")]

    public virtual Int32 BlogId { get; set; }


    [NHibernate.Mapping.Attributes.Property(Name = "Picture", Column = "picture", NotNull = false, TypeType = typeof(ImageUserType), Lazy = true)]

    public virtual Image Picture { get; set; }


    [NHibernate.Mapping.Attributes.Property(Name = "PostCount", Formula = "(SELECT COUNT(1) FROM post WHERE post.blog_id = blog_id)")]

    public virtual Int64 PostCount { get; protected set; }


    [NHibernate.Mapping.Attributes.ManyToOne(0, Column = "user_id", NotNull = true, Lazy = NHibernate.Mapping.Attributes.Laziness.NoProxy, Name = "Owner", Cascade = "save-update")]

    [NHibernate.Mapping.Attributes.Key(1)]

    public virtual User Owner { get; set; }


    [NHibernate.Mapping.Attributes.Property(Name = "Name", Column = "name", NotNull = true, Length = 50)]

    public virtual String Name { get; set; }


    [NHibernate.Mapping.Attributes.Property(Name = "Creation", Column = "creation", NotNull = true)]

    public virtual DateTime Creation { get; set; }


    [NHibernate.Mapping.Attributes.List(0, Name = "Posts", Cascade = "all-delete-orphan", Lazy = NHibernate.Mapping.Attributes.CollectionLazy.True, Inverse = true, Generic = true)]

    [NHibernate.Mapping.Attributes.Key(1, Column = "blog_id", NotNull = true)]

    [NHibernate.Mapping.Attributes.Index(2, Column = "number")]

    [NHibernate.Mapping.Attributes.OneToMany(3, ClassType = typeof(Post))]

    public virtual IList<Post> Posts { get; protected set; }

}

Basically, you will use:

  • ClassAttribute for marking a class as an entity;
  • IdAttribute: for declaring the id property;
  • GeneratorAttribute: for the id generator strategy;
  • PropertyAttribute: a mapped property;
  • BagAttribute/ListAttribute/SetAttribute/ArrayAttribute/etc: kinds of collections;
  • KeyAttribute: the key in a relation;
  • ElementAttribute: an element of an indexed collection;
  • IndexAttribute: the index in an indexed collection;
  • OneToManyAttribute/ManyToOneAttribute/OneToOneAttribute/ManyToManyAttribute: an endpoint property.

All these attributes live in the NHibernate.Mapping.Attributes namespace and are named very closely to the equivalent HBM.XML elements, which means they must be ordered (notice the first number on some attributes). Now, in order to actually make sense of these attributes, you need to:

var cfg = new Configuration();

var serializer = new HbmSerializer() { Validate = true };


using (var stream = serializer.Serialize(assemblyContainingEntitiesWithAttributes))

{

    cfg.AddInputStream(stream);

}

And that’s all it takes! Have fun! Winking smile

Published by

Ricardo Peres

Team Leader at Dixons Carphone. Microsoft MVP.

Leave a Reply

Your email address will not be published. Required fields are marked *