Try fast search NHibernate

19 July 2011

Azure Storage initialization

More than a post about “how initialize the Azure storage” this is a “bottle to sea” to check if somebody else known a best-practice, a recommendation or whatever you call it.

In the past year we had experimented the very nice and useful exception starting our Web-Role… if you have an application on Azure I’m pretty sure you saw it too:

TheNiceAzureError

Very nice and informative, even better than some of our exceptions in NHibernate.

The matter is that at some point you need the CloudStorageAccount and, at some point, you have to initialize the storage. We thought that the better place to initialize the storage is the HttpApplication.Application_Start() but… error; then we have tried the WebRole class and again… error. With no lucky I have tried to find some guideline about where initialize the storage, then I have opted for a “lazy initialization” at the first time an action with the storage is required but, again… error!!

Today I tried a new solution and hopefully it is the final-cut to the story. Here is the code:

public override bool OnStart()
{
    // For information on handling configuration changes
    // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
    RoleEnvironment.Changing += RoleEnvironmentChanging;
    WaitForRoleAvailability();

    InitializeAzureStorage();

    return base.OnStart();
}

private static void WaitForRoleAvailability()
{
    bool accountAvailable = false;
    do
    {
        try
        {
            AzureAccount.DefaultAccount();
            accountAvailable = true;
        }
        catch (RoleEnvironmentException e)
        {
            Thread.Sleep(3000);
        }
    } while (!accountAvailable);
}

And for the initialization:

InitializeAzureStorage

Today the error is away from us… but I would know if you know something better.

17 July 2011

NHibernate: playing with mapping by code (2)

galletto-alla-mediterranea
In the previous post you saw a simple example about a way to use the new mapping-by-code of NHibernate 3.2.0.
The class-by-class mapping will be, probably, the most used way just because it is very similar to the XML mapping and the “feeling of loss of control” is near to zero (the quiet of sense).
If you want experiment more adrenaline you can try ConfORM but if you like just a little bit of more adrenaline you can use the NHibernate’s ConventionModelMapper.


Inside the ConventionModelMapper

To understand what really is the ConventionModelMapper let me show you a piece of its code:
public class ConventionModelMapper : ModelMapper
{
    public ConventionModelMapper()
        : base(new SimpleModelInspector())
    {
        AppendDefaultEvents();
    }
clear! no? The ConventionModelMapper is just a specialization of a ModelMapper where, instead the ExplicitlyDeclaredModel, we are injecting another implementation of IModelInspector. To “simplify” its usage, and obscure to you the real power of Dependency-Injection, the ConventionModelMapper exposes some methods as, for instance:
public void IsPersistentProperty(Func<MemberInfo, bool, bool> match)
What are those three parameters of the delegate ?
The name of the method is the question : is it a persistent property ?
The MemberInfo is the subject of the question. The bool parameter is an “help” to take a decision and it represent what was explicitly defined (we will see later where was defined). The last bool is the answer of the question.
What happen if we have a look to the implementation of the above method ?
public void IsPersistentProperty(Func<MemberInfo, bool, bool> match)
{
    SimpleModelInspector.IsPersistentProperty(match);
}
As you can see the implementation is completely passed to the SimpleModelInspector, nothing more than an “simplification” to allow you the usage of just one class.


ConventionModelMapper vs class-by-class mapping

This is not a matter. All these ways to perform the mapping-task, in NHibernate 3.2.0, are not one versus others because you can use all together. You can organize your mapping as you feel more confortable. There will be users who prefer explicit-class-by-class for the whole mapping; there will be users who prefer the usage of ConventionModelMapper and the method-based-mapping to specify convention-exceptions/overrides; there will be users who prefer the usage of ConventionModelMapper and the class-by-class as an organization of convention-exceptions/overrides; there will be users who implements their IModelInspector based on attributes; there will be users who implements their IModelInspector based on a custom DSL.


The new mapping

Taking the domain of the previous post, and some conventions already defined there, we can start from something like this:
  1. var mapper = new ConventionModelMapper();
  2.  
  3. mapper.BeforeMapClass += (mi, t, map) => map.Table(t.Name.ToLowerInvariant());
  4. mapper.BeforeMapJoinedSubclass += (mi, t, map) => map.Table(t.Name.ToLowerInvariant());
  5. mapper.BeforeMapUnionSubclass += (mi, t, map) => map.Table(t.Name.ToLowerInvariant());
  6.  
  7. mapper.BeforeMapProperty += (mi, propertyPath, map) =>
  8. {
  9.     if (typeof(decimal).Equals(propertyPath.LocalMember.GetPropertyOrFieldType()))
  10.     {
  11.         map.Type(NHibernateUtil.Currency);
  12.     }
  13. };
  14.  
  15. mapper.BeforeMapBag += (mi, propPath, map) =>
  16. {
  17.     map.Cascade(Cascade.All.Include(Cascade.DeleteOrphans));
  18.     map.BatchSize(10);
  19. };
  20.  
  21. mapper.BeforeMapClass += (mi, type, map) =>
  22.     map.Id(idmap => idmap.Generator(Generators.HighLow,
  23.         gmap => gmap.Params(new
  24.         {
  25.             table = "NextHighVaues",
  26.             column = "NextHigh",
  27.             max_lo = 100,
  28.             where = string.Format("EntityName = '{0}'", type.Name.ToLowerInvariant())
  29.         })));
  30.  
  31. Func<Type, bool, bool> matchRootEntity = (type, wasDeclared)=> typeof(Entity).Equals(type.BaseType);
  32. var entities = Assembly.GetExecutingAssembly().GetExportedTypes()
  33.     .Where(t => typeof(Entity).IsAssignableFrom(t) && !typeof(Entity).Equals(t)).ToList();
  34. mapper.IsEntity((type, wasDeclared) => entities.Contains(type));
  35. mapper.IsRootEntity(matchRootEntity);
  36. HbmMapping domainMapping = mapper.CompileMappingFor(entities);
More then the starting point (line 1), where I’m using just the constructor of ConventionModelMapper, the difference, so far, is from line 31 to 36. Because I have completely removed any kind of explicit mapping (that “incomplete class-by-class mapping”) I have to inform the ConventionModelMapper about:
  1. given a System.Type how recognize if it is an entity or not (line 32,33,34)
  2. given a System.Type how recognize if it is a root-entity (the top class of a hierarchy); line 31,35
  3. which are the classes that the ConventionModelMapper have to map (line 32, 36)
Which is the advantage ? With the mapping of the previous post each time I’m adding a class to the domain I have to add its mapping; using this new mapping I can add a class to the domain without touch the mapping.
The mapping process is not completed because in the removed class-by-class mapping there was two specifications outside our required conventions: the Customer.TaxId as natural-id and the Order.EmissionDay as Date. To specify only these two convention-exceptions I can use the method-based-mapping in this way:
mapper.Class<Customer>(map => map.NaturalId(nm => nm.Property(c => c.TaxId)));
mapper.Class<Order>(map => map.Property(o=> o.EmissionDay, pm=> pm.Type(NHibernateUtil.Date)));
You can put the two lines in any place before call mapper.CompileMappingFor(entities).


The result

The integration is pretty the same:
  1. var configuration = new Configuration();
  2. configuration.DataBaseIntegration(c =>
  3. {
  4.     c.Dialect<MsSql2008Dialect>();
  5.     c.ConnectionString = @"Data Source=localhost\SQLEXPRESS;Initial Catalog=IntroNH;Integrated Security=True;Pooling=False";
  6.     c.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
  7.     c.SchemaAction = SchemaAutoAction.Create;
  8. });
  9. configuration.AddMapping(domainMapping);
  10. configuration.AddAuxiliaryDatabaseObject(CreateHighLowScript(Assembly.GetExecutingAssembly().GetExportedTypes().Where(t => matchRootEntity(t, false))));
The difference is just at line 10.
After build the session-factory we will have again

And the XML will be (please look it closer):
<?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="Customer" />
      <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" />
    <property name="EmissionDay" type="Date" />
    <bag name="Items" cascade="all,delete-orphan" batch-size="10">
      <key column="Order" />
      <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" />
    <property name="Product" />
    <property name="Price" type="Currency" />
  </class>
</hibernate-mapping>
The mapping is correct and it works but just for a “casualty”…

16 July 2011

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 { get; set; }
}
public class Customer : Entity
{
    public virtual string CommercialName { get; set; }
    public virtual string TaxId { get; set; }
    public virtual IEnumerable<Order> Orders { get; set; }
}
public class Order : Entity
{
    public virtual Customer Customer { get; set; }
    public virtual DateTime EmissionDay { get; set; }
    public virtual IEnumerable<OrderItem> Items { get; set; }
}
public class OrderItem : Entity
{
    public virtual Order Order { get; set; }
    public virtual string Product { get; set; }
    public virtual decimal Price { get; set; }
}


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 MySimpleModelInspector: ExplicitlyDeclaredModel
{
    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 smart IAuxiliaryDatabaseObject… 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(), null, new 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>