Monday, April 8, 2013

Start Fluent NHibernate



Introduction

Start your project from Visual Studio and say GoodBye to SQL Server and Tables.
What is NHibernate? Why do we use this technology? How to start using NHibernate?
NHibernate is an ORM (Object Relational Mapping) that maps relational data and objects. When you use NHibernate, you don't have to start from creating tables but all you have is to write your entities classes according to your business and NHibernate will create the tables for you.
We (applications developers) use NHibernate to avoid the stress of using, analyzing and changing the database. Using NHibernate will avoid the need from even entering your DBMS, When you have to change anything in some table, all you have is just modify your entity rather than enter the DB and change columns and relations... etc.
This article will give all what you need to get the confidence and continue with NHibernate.

Step 1: Create Your Business Entities

The first step is creating your entities in your project:
public class Employee
    {
        public virtual int Id {get; set;}
        public virtual string FirstName {get; set;}
        public virtual string Position {get; set;}
        public virtual Department EmployeeDepartment  
  {get; set;} // Represent the relation between Employee and Department
    }
public class Department
    {
        public virtual int Id {get; set;}
        public virtual string Name {get; set;}
        public virtual string PhoneNumber {get; set;}
    }
Remember to add virtual keyword to your property, that is used by NHibernate that will create proxy at runtime to allow lazy load (you can skip it for now, I will discuss in depth in my next article.)

Step 2: Create the Map Entities

Now you have to create a map entity for every entity created before that represents the heart of NHibernate. Any future change that happened on the entity should change the map here too:
class EmployeeMap : ClassMap<employee /><Employee>
    {
        //Constructor
        public EmployeeMap()
        {
            Id(x => x.Id);

            Map(x => x.FirstName);

            Map(x => x.Position);

            References(x => x.EmployeeDepartment).Column("DepartmentId");

            Table("Employee");
        }
    }
class DepartmentMap : ClassMap<department /><Department>
    {
        //Constructor
        public DepartmentMap()
        {
            Id(x => x.Id);

            Map(x => x.Name);

            Map(x => x.PhoneNumber);

            Table("Department");
        }
    }
Remember to add virtual keyword to your property, that is used by NHibernate that will create proxy at runtime to allow lazy load (in my articles, I focus on how we use this technology more than why we use it and what are the issues that need a lot of discussion, if you need more).
NHibernate methods (keywords):
  • Map: Used to create column for the selected property
  • References: Used to create many-to-one relation, applied in the many side
  • Table: Determine the name of the table (optional)

Step 3: Create the Configuration

Now you have to write the configuration lines that will be written just one time, every execution for your program will execute these lines that will modify the database according to your update:
public class NHibernateHelper
    {
        private static ISessionFactory _sessionFactory;

        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)

                    InitializeSessionFactory();
                return _sessionFactory;
            }
        }

        private static void InitializeSessionFactory()
        {
            _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008
                  .ConnectionString(
                  @"Server=(local);initial catalog=xxxxx;
  user=xxxxx;password=xxxxx;") // Modify your ConnectionString
                              .ShowSql()
                )
                .Mappings(m =>
                          m.FluentMappings
                              .AddFromAssemblyOf<Program>())
                .ExposeConfiguration(cfg => new SchemaExport(cfg)
                                                .Create(true, true))
                .BuildSessionFactory();
        }

        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }
    }
Now all you have is just run your application and go to the SQL Server to see your tables.
Note: Don't forget to modify the ConnectionString.

Step 4: Insert your Data to Test the Project

Now you have to save some rows into your database by writing these lines in the MAIN:
static void Main(string[] args)
        {
            using (var session = NHibernateHelper.OpenSession())
             {
                 using (var transaction = session.BeginTransaction())
                 {
                     var DepartmentObject = new Department 
   {Name = "IT", PhoneNumber = "962788700227" };
                     session.Save(DepartmentObject);
                     transaction.Commit();
                     Console.WriteLine("Department Created: " + DepartmentObject.Name);
                 }
             }
        }
Hope this article will give you the fundamentals of Fluent NHibernate.

Original URL 

Monday, March 25, 2013

NHibernate: playing with mapping by code



GallettiAllaBraceNHibernate 3.2.0GA is going to be released and, around the NET, there are various questions about how use its “sexy-mapping”… “sexy-mapping” is not a serious definition? well… I’m bored by zero-one definitions.

I think that the “problem” is that I have explicitly avoided to call something “best practice” writing  my examples (as I done with ConfORM) and the new mapping-by-code is very flexible and you have various ways to achieve your target.
In this example I’ll try to resume the answers to various questions.

This time nobody sent me a domain so the case is not real… it is a domain just for  the exercise.



The domain

public class Entity
{
    public virtual int Id { getset; }
}
public class Customer : Entity
{
    public virtual string CommercialName { getset; }
    public virtual string TaxId { getset; }
    public virtual IEnumerable<Order> Orders { getset; }
}
public class Order : Entity
{
    public virtual Customer Customer { getset; }
    public virtual DateTime EmissionDay { getset; }
    public virtual IEnumerable<OrderItem> Items { getset; }
}
public class OrderItem : Entity
{
    public virtual Order Order { getset; }
    public virtual string Product { getset; }
    public virtual decimal Price { getset; }
}


The incomplete class-by-class mapping

In our mapping-process we can start from various points depending on our knowledge of NHibernate, our knowledge of the domain, how much we known our conventions, how much we really known the relations between classes and so on. For this exercise I’ll start from a very incomplete class-by-class mapping as the follow:
public class EntityMapping<T> : ClassMapping<T> where T : Entity
{
    public EntityMapping()
    {
        Id(x => x.Id);
    }
}
public class CustomerMapping : EntityMapping<Customer>
{
    public CustomerMapping()
    {
        Property(x => x.CommercialName);
        NaturalId(map => map.Property(x => x.TaxId));
        Bag(x => x.Orders, map => map.Key(km => km.Column("CustomerId")));
    }
}
public class OrderMapping : EntityMapping<Order>
{
    public OrderMapping()
    {
        ManyToOne(x => x.Customer, map => map.Column("CustomerId"));
        Property(x => x.EmissionDay, map => map.Type(NHibernateUtil.Date));
        Bag(x => x.Items, map => map.Key(km => km.Column("OrderId")));
    }
}
public class OrderItemMapping : EntityMapping<OrderItem>
{
    public OrderItemMapping()
    {
        ManyToOne(x => x.Order, map => map.Column("OrderId"));
        Property(x => x.Product);
        Property(x => x.Price);
    }
}
If you have studied the mapping-by-code you know that you can define everything using class-by-class mapping but I want show you how little is the step between explicit-mapping and conventions/defaults-mapping.


The ModelMapper

In this exercise I’ll use the ModelMapper. The ModelMapper delegates some responsibilities to others classes. You can see all classes involved analyzing all ModelMapper constructors overloads. If you have a look at the most simple constructor you will find that the ModelMapper uses, by default, the class ExplicitlyDeclaredModel. The ExplicitlyDeclaredModel does not apply any special behavior other than what was explicitly declared or NHibernate’s convetions about table/columns names and types. Using class-by-class mapping the basic usage of the ModelMapper can look as:
var mapper = new ModelMapper();
mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes());
HbmMapping domainMapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
yes!, that is all… then you have to add the domainMapping to the NHibernate’s configuration instance before BuildSessionFactory.


Applying tables-naming conventions over ModelMapper

The first convention required is : “All table names are lowercase”
Any kind of convention, customization have to be declared before get all mappings so we can do something like this:
var mapper = new ModelMapper();
mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes());

mapper.BeforeMapClass += (mi, t, map) => map.Table(t.Name.ToLowerInvariant());
mapper.BeforeMapJoinedSubclass += (mi, t, map) => map.Table(t.Name.ToLowerInvariant());
mapper.BeforeMapUnionSubclass += (mi, t, map) => map.Table(t.Name.ToLowerInvariant());

HbmMapping domainMapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
As you can see you can add all conventions even after add all mappings to the ModelMapper.


Applying property-types “conventions” over ModelMapper

“All properties defined as decimal have to be mapped as currency”
mapper.BeforeMapProperty += (mi, propertyPath, map) =>
{
    if (typeof(decimal).Equals(propertyPath.LocalMember.GetPropertyOrFieldType()))
    {
        map.Type(NHibernateUtil.Currency);
    }
};

 

Applying collections “conventions” over ModelMapper

“All Bags are bidirectional-one-to-many and the batch size is 10”
mapper.BeforeMapBag += (mi, propPath, map) =>
{
    map.Cascade(Cascade.All.Include(Cascade.DeleteOrphans));
    map.BatchSize(10);
};
Is that enough to accomplish the target ? No, is not. We have defined only some attributes of the collections declared as Bag but we haven’t defined which is the relation between the collection ReflectedType and the collection-item-type. We can’t define the one-to-many relation using the ModelMapper because the responsibility to define/discover all relation is delegated to the IModelInspector injected to the ModelMapper instance (note that I wrote instance). Out-of-the-box you can find some implementations of IModelInspector but if you want continue maintaining most of things under your control and you want learn the new mapping-by-code step-by-step you can simply use a class inherited from the “”default”” ExplicitlyDeclaredModel. In this case the implementation can be simply:
public class MySimpleModelInspectorExplicitlyDeclaredModel
{
    public override bool IsOneToMany(MemberInfo member)
    {
        if(IsBag(member))
        {
            return true;
        }
        return base.IsOneToMany(member);
    }
}
and its usage is:
var modelInspector = new MySimpleModelInspector();
var mapper = new ModelMapper(modelInspector);

 

Applying POID strategy “conventions” over ModelMapper

At this point of the mapping-process we have a working an ready-to-work mapping for our above model but, where not defined, the default POID strategy is “assigned”. In this exercise I want use the HighLow strategy (aka HiLo) but not the simple version; I want use the per-entity-High-Low strategy.
Knowing how we are giving the name of the table (we wrote it just few lines above) the mapping of the convention is:
mapper.BeforeMapClass += (mi, type, map) =>
    map.Id(idmap => idmap.Generator(Generators.HighLow,
        gmap => gmap.Params(new
        {
            table = "NextHighVaues",
            column = "NextHigh",
            max_lo = 100,
            where = string.Format("EntityName = '{0}'", type.Name.ToLowerInvariant())
        })));
Is it enough ? Yes! It is… mmm… perhaps it is enough but not for me. By default NHibernate will generates a table for HighLow but will not insert all records needed by per-entity-High-Low. What we need is a smartIAuxiliaryDatabaseObject… something simple as:
private static IAuxiliaryDatabaseObject CreateHighLowScript(IModelInspector inspector, IEnumerable<Type> entities)
{
    var script = new StringBuilder(3072);
    script.AppendLine("DELETE FROM NextHighVaues;");
    script.AppendLine("ALTER TABLE NextHighVaues ADD EntityName VARCHAR(128) NOT NULL;");
    script.AppendLine("CREATE NONCLUSTERED INDEX IdxNextHighVauesEntity ON NextHighVaues (EntityName ASC);");
    script.AppendLine("GO");
    foreach (var entity in entities.Where(x => inspector.IsRootEntity(x)))
    {
        script.AppendLine(string.Format("INSERT INTO [NextHighVaues] (EntityName, NextHigh) VALUES ('{0}',1);", entity.Name.ToLowerInvariant()));
    }
    return new SimpleAuxiliaryDatabaseObject(script.ToString(), nullnew HashedSet<string> { typeof(MsSql2005Dialect).FullName, typeof(MsSql2008Dialect).FullName });
}

 

Conclusions

Even if we started from a bored declarative (and incomplete) class-by-class-mapping we have changed its behavior without touch the initial mapping. The last step of the exercise is the integration with NHibernate3.2.0 and it is:
var configuration = new Configuration();
configuration.DataBaseIntegration(c =>
{
    c.Dialect<MsSql2008Dialect>();
    c.ConnectionString = @"Data Source=localhost\SQLEXPRESS;Initial Catalog=IntroNH;Integrated Security=True;Pooling=False";
    c.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
    c.SchemaAction = SchemaAutoAction.Create;
});
configuration.AddMapping(domainMapping);
configuration.AddAuxiliaryDatabaseObject(CreateHighLowScript(modelInspector, Assembly.GetExecutingAssembly().GetExportedTypes()));

var factory = configuration.BuildSessionFactory();
// we are now ready to work with NHibernate
After build the session-factory in our db we will have:
PlatWithMappingByCode
For Tommaso guys (non crede finché non tocca)
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                   namespace="PlayWithMappingByCode" 
                   assembly="PlayWithMappingByCode" 
                   xmlns="urn:nhibernate-mapping-2.2">
  <class name="Customer" table="customer">
    <id name="Id" type="Int32">
      <generator class="hilo">
        <param name="table">NextHighVaues</param>
        <param name="column">NextHigh</param>
        <param name="max_lo">100</param>
        <param name="where">EntityName = 'customer'</param>
      </generator>
    </id>
    <natural-id>
      <property name="TaxId" />
    </natural-id>
    <property name="CommercialName" />
    <bag name="Orders" cascade="all,delete-orphan" batch-size="10">
      <key column="CustomerId" />
      <one-to-many class="Order" />
    </bag>
  </class>
  <class name="Order" table="order">
    <id name="Id" type="Int32">
      <generator class="hilo">
        <param name="table">NextHighVaues</param>
        <param name="column">NextHigh</param>
        <param name="max_lo">100</param>
        <param name="where">EntityName = 'order'</param>
      </generator>
    </id>
    <many-to-one name="Customer" column="CustomerId" />
    <property name="EmissionDay" type="Date" />
    <bag name="Items" cascade="all,delete-orphan" batch-size="10">
      <key column="OrderId" />
      <one-to-many class="OrderItem" />
    </bag>
  </class>
  <class name="OrderItem" table="orderitem">
    <id name="Id" type="Int32">
      <generator class="hilo">
        <param name="table">NextHighVaues</param>
        <param name="column">NextHigh</param>
        <param name="max_lo">100</param>
        <param name="where">EntityName = 'orderitem'</param>
      </generator>
    </id>
    <many-to-one name="Order" column="OrderId" />
    <property name="Product" />
    <property name="Price" type="Currency" />
  </class>
</hibernate-mapping>

NHibernate's mapping-by-code - the summary


NHibernate's mapping-by-code - the summary

Six weeks ago, when I started my experiments with NHibernate's 3.2 new mapping feature - mapping-by-code, I was a loyal Fluent NHibernate user and a fan of method chains in APIs. My first impression about mapping-by-code was that it seems to be a good direction, but it's still immature and - what's important - not documented at all. I decided to have a deeper look and it turned into almost twenty parts series exploring all the possible mappings - probably the only complete guide to mapping-by-code on the web so far. Time to sum the series up.
Let's start with what mapping-by-code is. It is an XML-less mapping solution being an integral part of NHibernate since 3.2, based on ConfORM library. Its API tries to conform to XML naming and structure. There's a strong convention in how the mapping methods are built. Its names are almost always equal to XML elements names. The first parameter points to the mapped property, second is for its options corresponding XML attributes (and XML <key> element, if applicable) and the rest of parameters, if any, corresponds to nested XML elements. It's very convenient for those familiar with XML schema or for documentation readers.
Mapping-by-code also came with very powerful mapping by convention tool - ConventionModelMapper. It is highly flexible and customizable, but customizing it may not even be needed, as by default it is able to figure out mappings even for components or maps. The only thing it can't map automatically are bidirectional relationships - but it was pretty easy to fix this using conventions (I've updated my conventions since first published - it now supports all kinds of collections, inheritance and more -feel free to use it).
Here is the full table of contents of my mapping-by-code series.
  1. First impressions
  2. Naming convention resembling Fluent
  3. Property
  4. Component
  5. ManyToOne
  6. inheritance
  7. dynamic component
  8. Set and Bag
  9. OneToMany and other collection-based relation types
  10. concurrency
  11. OneToOne
  12. Join
  13. Any
  14. ListArrayIdBag
  15. Map
  16. IdNaturalId
  17. composite identifiers
  18. entity-level mappings
And what about Fluent NHibernate? Hiding the XML was a great idea, but simplifying the mappings went too far, in my opinion. I've already mentioned the mess caused by concept name changes made in Fluent NHibernate (1) (2) - I wouldn't repeat it again. Moreover, XML mapping is a tree structure and it just doesn't fit into single method chains. Fluent NHibernate's API bypasses this limitations by prefixing method names (like KeyColumn) or by falling back to the interface that uses Action<T> (i.e. in Join or Component mapping), quite similiar to mapping-by-code API. Method chaining also makes it hard to reuse the same concepts in different contexts. It's lot easier in mapping-by-code way - i.e. Column mapping is the same in every mapped feature and it is handled by exactly the same code.
Don't get me wrong. I think FNH was a good and useful project. But I've used it as the only existing alternative to cumbersome and verbose XML mapping. And now, when we have an alternative that is integrated into NHibernate (no external dependency and versioning issues), more efficient (no XML serialization) and with better API (no ambiguity, NH naming kept), the purpose of FNH's existence is highly reduced.

(Original URL: http://notherdev.blogspot.com/2012/02/nhibernates-mapping-by-code-summary.html)