Try fast search NHibernate

Showing posts with label ORM. Show all posts
Showing posts with label ORM. Show all posts

09 July 2011

Using ConfORM with modular application

I’m getting some questions about how use ConfORM in modular applications. The first commercial application mapped with ConfORM is a pretty complex modular application and if you have a look to the first ConfOrm example you can find the IModuleMapping.
Here I’ll try to explain how we have used it in that application writing a new example.

The IModuleMapper

/// <summary>
/// A template to perform a mapping using ConfOrm
/// </summary>
public interface IModuleMapper
{
    /// <summary>
    /// Register domain classes, persistent-strategies, relations and so on of a spefic module
    /// </summary>
    void DefineDomain();

    /// <summary>
    /// Register patterns of a module
    /// </summary>
    void RegisterPatterns();

    /// <summary>
    /// Customize persistence representations
    /// </summary>
    void Customize();

    /// <summary>
    /// Get all domain entities of the module.
    /// </summary>
    /// <returns>domain entities.</returns>
    IEnumerable<Type> GetEntities();
}
As you can see it is a simple template just to suggest how organize your mapping… nothing complicated.

The Domain

In the assembly Acme.ModuleA
using System;
using Acme.Domain.Common;

namespace Acme.ModuleA
{
    public class User: Entity
    {
        public string UserName { get; set; }
        public string Text { get; set; }
        public DateTime Birthday { get; set; }
    }
}
In the assembly Acme.ModuleB
using System;
using Acme.Domain.Common;
using Acme.ModuleA;

namespace Acme.ModuleB
{
    public class Article: Entity
    {
        public DateTime PublishedAt { get; set; }
        public string Title { get; set; }
        public string Text { get; set; }
        public User Author { get; set; }
    }
}

 

Some extensions

Just to not forget it later…
public static class ModuleMappingUtil
{
    public static IEnumerable<Type> MapModule(this IModuleMapper mapper)
    {
        mapper.DefineDomain();
        mapper.RegisterPatterns();
        mapper.Customize();
        return mapper.GetEntities();
    }

    public static bool IsOfModuleContaining<T>(this Type source)
    {
        return source.Assembly.Equals(typeof(T).Assembly);
    }
}

 

The mapping

You can organize the mapping of your modules in a single assembly, in general the same where you are generating the session factory, or in more than one assembly. In general you need just a little class to map a module so please don’t be exaggerated separating your application.
For this example I will show three implementations of ModuleMapper all implemented in the same assembly named Acme.Persistence.Wiring.
public class GeneralsPatternsModuleMapper : IModuleMapper
{
    private readonly Mapper mapper;
    private readonly ObjectRelationalMapper orm;

    public GeneralsPatternsModuleMapper(ObjectRelationalMapper orm, Mapper mapper)
    {
        this.orm = orm;
        this.mapper = mapper;
    }

    #region IModuleMapper Members

    public void DefineDomain()
    {
        // map .NET4 ISet<T> as a NHibernate's set
        orm.Patterns.Sets.Add(mi => mi.GetPropertyOrFieldType().GetGenericIntercafesTypeDefinitions().Contains(typeof (ISet<>)));
    }

    public void RegisterPatterns()
    {
        // all strings are length 50 characters
        mapper.PatternsAppliers.Property.Add(mi => typeof (string).Equals(mi.GetPropertyOrFieldType()), (mi, map) => map.Length(50));
      
        // when a DateTime seems to be a simple date apply NH's Date type
        mapper.PatternsAppliers.Property.Add(mi => typeof (DateTime).Equals(mi.GetPropertyOrFieldType()) && IsDate(mi.Name), (mi, map) => map.Type(NHibernateUtil.Date));

        // when a DateTime seems to not be a simple date apply NH's UtcDateTime type
        mapper.PatternsAppliers.Property.Add(mi => typeof (DateTime).Equals(mi.GetPropertyOrFieldType()) && !IsDate(mi.Name), (mi, map) => map.Type(NHibernateUtil.UtcDateTime));
    }

    public void Customize()
    {
        // Nothing to do
    }

    public IEnumerable<Type> GetEntities()
    {
        yield break;
    }

    #endregion

    public static bool IsDate(string name)
    {
        return name.EndsWith("Date") || name.StartsWith("Date") || name.EndsWith("Day") || name.EndsWith("day") || name.StartsWith("Day");
    }
}
The GeneralsPatternsModuleMapper register just part of my common convention for the current application. Then the mapping of my Acme.ModuleA:
public class ModuleAMapper : IModuleMapper
{
    private readonly Mapper mapper;
    private readonly ObjectRelationalMapper orm;

    public ModuleAMapper(ObjectRelationalMapper orm, Mapper mapper)
    {
        this.orm = orm;
        this.mapper = mapper;
    }

    public void DefineDomain()
    {
        // register all classes of my module (ConfORM will use it to discover polymorphic associations)
        orm.AddToDomain(typeof(User).Assembly.GetExportedTypes());

        // defines the persistence strategy for each root of each hierarchy
        orm.TablePerClass<User>();
    }

    public void RegisterPatterns()
    {
        // no specific patterns for this module
    }

    public void Customize()
    {
        // map a specific size (20) for a specific property of a specific class
        mapper.Class<User>(x => x.Property(user => user.UserName, map => map.Length(20)));
    }

    public IEnumerable<Type> GetEntities()
    {
        // all entities of this modules
        return typeof(User).Assembly.GetExportedTypes().Where(t=> typeof(Entity).IsAssignableFrom(t));
    }
}
The mapping of Acme.ModuleB:
public class ModuleBMapper : IModuleMapper
{
    private readonly Mapper mapper;
    private readonly ObjectRelationalMapper orm;

    public ModuleBMapper(ObjectRelationalMapper orm, Mapper mapper)
    {
        this.orm = orm;
        this.mapper = mapper;
    }

    public void DefineDomain()
    {
        // register all classes of my module (ConfORM will use it to discover polymorphic associations)
        orm.AddToDomain(typeof(Article).Assembly.GetExportedTypes());

        // defines the persistence strategy for each root of each hierarchy
        orm.TablePerClassHierarchy<Article>();
    }

    public void RegisterPatterns()
    {
        // patterns for this module

        // when a string property is named "Text" then apply StringClob type (note just for Acme.ModuleB)
        mapper.PatternsAppliers.Property.Add(
            mi => "text".Equals(mi.Name.ToLowerInvariant()) && typeof (string).Equals(mi.GetPropertyOrFieldType()) && mi.DeclaringType.IsOfModuleContaining<Article>(),
            (mi, map) => { map.Type(NHibernateUtil.StringClob); map.Length(int.MaxValue); });
    }

    public void Customize()
    {
        // nothing to do
    }

    public IEnumerable<Type> GetEntities()
    {
        // all entities of this modules
        return typeof(Article).Assembly.GetExportedTypes().Where(t => typeof(Entity).IsAssignableFrom(t));
    }
}

 

The NHibernate’s initialization

First you need a method to get all modules of your application, for simplicity here is a simple implementation:
private static IEnumerable<IModuleMapper> GetAllModulesMappers(ObjectRelationalMapper orm, Mapper mapper)
{
    yield return new GeneralsPatternsModuleMapper(orm, mapper);
    yield return new ModuleAMapper(orm, mapper);
    yield return new ModuleBMapper(orm, mapper);
}
and now you have all is needed to have the session factory:
  1. var orm = new ObjectRelationalMapper();
  2. var patternSet = new CoolPatternsAppliersHolder(orm);
  3. var mapper = new Mapper(orm, patternSet);
  4.  
  5. HbmMapping mappings = mapper.CompileMappingFor(GetAllModulesMappers(orm, mapper).SelectMany(x => x.MapModule()));
  6.  
  7. var configure = new Configuration();
  8. configure.SessionFactoryName("Demo");
  9. configure.DataBaseIntegration(db =>
  10. {
  11.     db.Dialect<MsSql2008Dialect>();
  12.     db.ConnectionStringName = "ToAcmeDb";
  13. });
  14.  
  15. configure.AddDeserializedMapping(mappings, "AcmeApplicationDomain");
  16.  
  17. ISessionFactory factory = configure.BuildSessionFactory();
In the line 5 I’m getting just one mapping document for the whole domain. You can use the method mapper.CompileMappingForEach without problems. The main matter here is the fact that I’m using just one instance of ObjectRelationalMapper and Mapper to give the whole picture of the domain of the application to ConfORM.

27 August 2010

ConfORM 1.0Alpha2

I’m happy to announce the first release of ConfORM binaries.

The release is tagged as Alpha2 just because we are using it in production, in four projects, since 3 months now (at least).

Thanks to JetBrains and CodeBetter you can inform your issues through YouTrack.

Welcome to ConfORM!!
There are times when a simple piece of code seems to have a soul.

Sound track

08 July 2010

Enhanced Query Object

One of the annoying thing in our daily work is the modification of the Repository/DAO interface, and implementation, each time a new use-case, of our application, needs a new query.

The three solutions available so far

1.
The Query Object pattern was described by Martin Fowler. I like its short definition:
An object that represents a database query.
What I don’t like so much is its long description:
A Query Object is an interpreter [Gang of Four], that is, a structure of objects that can form itself into a SQL query.
A good example of Query Object is our dear ICriteria with all its classes. The problem is that I can’t expose neither ICriteria nor a concrete class using it because I don’t want expose nothing using NHibernate.
2.
Another possible solution is the Specifications Pattern (by Eric Evans and Martin Fowler).
Specification is again very powerful especially because easy to test. In .NET we have various implementations/interpretations based on LINQ. The advantage is basically that you can test your specification and your specification-composition in RAM… sure… hoping for that your LINQ provider can then efficiently translate it in SQL.
3.
The last is a repository implementing IQueriable (as proposed here) with its pro/cons:
  • Easy to test.
  • LINQ queries, for persistence, wrote every where.
  • Hope that your LINQ provider can then efficiently translate it in SQL.


The fact

In NHibernate we have at least six ways to query our persistence (have a look to this post). I can choose the query-system that best fit my needs of balance between code-readability, code-maintainability and query-performance.
Why I should limit myself in using just one ?
What I need is a solution to avoid the continuous modification of the repository’s interface maintaining the advantage NHibernate gives to me.


Enhanced Query Object

An object that represent a query. The responsibility of a EQO is returns the query results.
In general you will express a EQO as an interface placed in the same assembly where you are putting your IRepository interfaces. An example could look like:
public interface IContactByNameQuery
{
    string PartialFirstNameOrLastName    { get; set; }
    IPagedResults<Contact> GetAll(int pageSize, int pageNumber);
}
because the EQO is responsible to return the results of the query, in its implementation I can use whatever the persistence framework gives to me. I can add EQOs to my system without touch existing code. Because a EQO is an interface I can easily mock it. Perhaps I can’t test it quickly in RAM… perhaps… but in general I prefer to write integration tests (tests hitting a well-known-DataBase) instead test my queries using a fake-database.
The implementation of the above EQO, for NHibernate, could look as:
public class ContactByNameQuery : IContactByNameQuery
{
    private readonly ISessionFactory sessionFactory;

    public ContactByNameQuery(ISessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
    }

    #region IContactByNameQuery Members

    public string PartialFirstNameOrLastName { get; set; }
    public IPagedResults<Contact> GetAll(int pageSize, int pageNumber)
    {
        var query = sessionFactory.GetCurrentSession().QueryOver<Contact>();
        if (!string.IsNullOrWhiteSpace(PartialFirstNameOrLastName))
        {
            query.Where(
                Restrictions.On<Contact>(c => c.FirstName).IsLike(PartialFirstNameOrLastName, MatchMode.Anywhere) |
                Restrictions.On<Contact>(c => c.LastName).IsLike(PartialFirstNameOrLastName, MatchMode.Anywhere)
                );
        }
        query.OrderBy(c => c.LastName).Asc.ThenBy(c => c.FirstName);

        var queryCount = query.ToRowCountQuery();

        var contacts = query.Take(pageSize).Skip((pageNumber -1) * pageSize).Future<Contact>();
        var count = queryCount.FutureValue<int>().Value;
        return new PagedResults<Contact>(count, contacts);
    }

    #endregion
}

but you are completely free to implement it using LINQ, HQL, Criteria, H-SQL, SQL, NamedQuery or whatever you feel comfortable with.

How create a concrete instance of EQO ?

Using exactly the same identical way you are using for your concrete implementation of Repositories or DAOs implementations.
Try it and let me know how you feel.

03 October 2009

How you shouldn’t write your mapping

More than one time, in my courses, in this blog and in various NH’s users list, I talked about a rule of thumb about mappings: not try to be clear because it obscures.

Have a look to this mapping:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<
class name="YourApp.Common.DataObjects.Address, YourApp"
table="Address">
<
id name="Id" type="Int32" unsaved-value="null">
<
column name="Id"
length="4" sql-type="int"
not-null="true" unique="true" index="PK_Address"/>
<
generator class="native" />
</
id>
<
property name="Address1" type="String">
<
column name="Address1" length="255"
sql-type="varchar" not-null="true"/>
</
property>
<
property name="Address2" type="String">
<
column name="Address2" length="255"
sql-type="varchar" not-null="false"/>
</
property>
<
property name="City" type="String">
<
column name="City" length="255"
sql-type="varchar" not-null="true"/>
</
property>
<
property name="State" type="String">
<
column name="`State`" length="2"
sql-type="varchar" not-null="true"/>
</
property>
<
property name="Zip" type="String">
<
column name="Zip" length="12"
sql-type="varchar" not-null="true"/>
</
property>
<
many-to-one name="Contact" class="YourApp.Common.DataObjects.Contact, YourApp">
<
column name="Contact_Id" length="4"
sql-type="int" not-null="false"/>
</
many-to-one>
<
bag name="BillToOrderHeaders" inverse="true" lazy="true" cascade="all-delete-orphan">
<
key column="BillToAddress_Id"/>
<
one-to-many
class="YourApp.Common.DataObjects.OrderHeader, YourApp"/>
</
bag>
<
bag name="ShipToOrderHeaders" inverse="true" lazy="true" cascade="all-delete-orphan">
<
key column="ShipToAddress_Id"/>
<
one-to-many
class="YourApp.Common.DataObjects.OrderHeader, YourApp"/>
</
bag>
</
class>
</
hibernate-mapping>

This is how it may look having the same result:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="YourApp"
namespace="YourApp.Common.DataObjects">

<
class name="Address">
<
id name="Id">
<
generator class="native" />
</
id>
<
property name="Address1" not-null="true" />
<
property name="Address2"/>
<
property name="City" not-null="true"/>
<
property name="State" length="2" not-null="true"/>
<
property name="Zip" length="12" not-null="true"/>
<
many-to-one name="Contact" column="Contact_Id"/>
<
bag name="BillToOrderHeaders" inverse="true" cascade="all-delete-orphan">
<
key column="BillToAddress_Id"/>
<
one-to-many class="OrderHeader"/>
</
bag>
<
bag name="ShipToOrderHeaders" inverse="true" cascade="all-delete-orphan">
<
key column="ShipToAddress_Id"/>
<
one-to-many class="OrderHeader"/>
</
bag>
</
class>
</
hibernate-mapping>
In this second representation we can understand immediately which are the difference with the NHibernate convention and, over all, you are not hurting your eyes reading it ;-) .

13 September 2009

Repository or DAO?: Repository

such question, no?
The definition of Repository pattern is extremely clear (as usual coming from where it come). What was not absolutely clear is how developers are using it… perhaps my interpretation of these words is a little bit extreme.
A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection.
In .NET a Repository should look like:
public interface IRepository<T> : ICollection<T> { }
You may have just one implementation or you may have more than one especially to prevent the calls to Clear.
For example:
public class ProductRepository : IRepository<Product>
{
private readonly ISessionFactory sessionFactory;

public ProductRepository(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}

public void Add(Product item)
{
sessionFactory.GetCurrentSession().Save(item);
}

public void Clear()
{
throw new NotSupportedException();
}
...
}
The other part of the pattern definition say:
Client objects construct query specifications declaratively and submit them to Repository for satisfaction.
With .NET3.5 the Repository should look like:
public interface IRepository<T> : ICollection<T>, IQueryable<T> { }
And the generic implementation for NHibernate should look like:
public class Repository<T>: IRepository<T>
{
private readonly ISessionFactory sessionFactory;

public Repository(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}

#region Implementation of IQueryable

public Expression Expression
{
get { return sessionFactory.GetCurrentSession().Linq<T>().Expression; }
}

public Type ElementType
{
get { return sessionFactory.GetCurrentSession().Linq<T>().ElementType; }
}

public IQueryProvider Provider
{
get { return sessionFactory.GetCurrentSession().Linq<T>().Provider; }
}

#endregion
...
}
That’s all ? … yes that’s all… or that’s should be all.
LINQ is a powerful OO query language but was not designed, in specific, for persistence; in many cases we will must divide the execution in two parts: the part to run in the server and the part to run in RAM. Actually NHibernate has the same concept, through IQuery/ICriteria (server-side) and IResultTransformer (client-side), the main difference is that you are in charge of the decision about “where-run-what”. Implement a LINQ-provider, which is able taking such decisions, is the real feat (I have shown an simple example in this post). So far I didn’t see a persistent-layer that is in condition, always, to take some of these decisions and, frankly, I think it will be very hard; probably, in some cases, we will back to “user decision” with an explicit separation of a linq-sentence in two parts.
Using a Repository interpretation like the above there is another side effect: the responsibility of “how query the persistence” is completely delegated to the business-logic developer. There is no problem because, in general, he is the same guy ? perhaps… I’m not the same guy when I’m implementing the BL than when I’m implementing a DAO (I have tried to explain the problem to my psychologist but he doesn’t understand the problem). In practice Fabio-BL is worried only by OO matters where Fabio-DAL is worried by some OO-matters and, over all, by RDBMS issues. If Fabio-BL has a request like “give me a way to have all Products”, Fabio-DAL will give him a IPaginable<Product> with some restrictions about page-size, or, after some negotiations, an IEnumerable<Product> limited to the first 500 products (no more negotiable).
And before LINQ come in play ?
Here is where I saw everything else than Repository. For example:
public interface IProductRepository
{
Product GetById(int id);
IEnumerable<Product> FindByDecription(string template);
IEnumerable<Product> FindByPrice(IRange<decimal> priceRange);
void Add(Product product);
void Remove(Product product);
}

public interface ICustomerRepository
{
Customer GetCustomerById(string id);
IEnumerable<Customer> FindByName(string name);
void AddCustomer(Customer customer);
}
We can call the two implementations Repository as we can call it Juan, John or whatever; obviously “Repository” sound cool.
The correct way to implements Repository, before LINQ come in play, is using another pattern (the same defined for DAO) : Query object pattern.
The methods in your generic repository may look like:
IEnumerable<T> Retrieve(IQuery<T> query);
long Count(IQuery<T> query);
The challenge, here, is write a good generic IQuery<T> interface.
A little step back : “Repository mediates between the domain and data mapping layers”
Which “data mapping layers” ?
As the DAO even the Repository shouldn’t expose the implementation of the persistent-layer outside the Repository implementation itself and for that reason you shouldn’t use directly “a cooked” query object as NHibernate.ICriteria.
From here on any consideration we can make over “how query the domain” using Repository is applicable to DAO.

Next post DAO.

11 September 2009

NHibernate: Tree Re-parenting

Did you heard about NHibernate and Hibernate re-parenting issue?

I heard it many times in these years including in our JIRA.

Depending on how you are managing your system there are various solutions to manage the re-parenting issue. The most common is set the cascade style to “all” and manage orphaned nodes in some way.

The last time the user said:

Nhibernate should handle cases where child objects are moved from one parent to another by updating the foreign key column in the child record.
Nhibernate should handle cases where child objects are removed from a parent by deleting the orphan objects.

From my understanding I would like cascade=all-delete-orphan to be intelligent enough to handle orphans as orphans and children with new parents not as orphans (they have parents, just not the same ones)
Make sense?

NHibernate is a persistent-layer and rules about how manage a tree are out from persistent-layer scope. The fact that NHibernate offer you the cascade-feature does not mean that it can work in any of your cases especially when the logic is your logic.

Words as “intelligent”/”smart” or “silly” are subjective opinions. In my opinion what is really important is not if a framework is silly or not but if the framework give me the opportunity to define what is intelligent for me.

That said let go to see if NHibernate is the framework I’m looking for.

The repository

Domain

private void FillDb()
{
var rep = new List<Node>();
for (int i = 0; i < 2; i++)
{
var gp = new Node {Description = "N" + i.ToString("00")};
rep.Add(gp);
for (int j = 0; j < 5; j++)
{
var c = new Node { Description = gp.Description + "-" + j.ToString("00") };
gp.AddChild(c);
for (int k = 0; k < 4; k++)
{
var cc = new Node { Description = c.Description + "-" + k.ToString("00") };
c.AddChild(cc);
}
}
}
using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
foreach (var node in rep)
{
s.Save(node);
}
tx.Commit();
}
}

Two roots, each with five children and each child with four children.

The target

Usage of delete-orphan cascade-style, making even your DAO/Repository persistence ignorant (no overhead to manage orphans delete).

The test

[Test]
public void TryingDisaster()
{
FillDb();

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var tree = s.CreateQuery("from Node n where n.Parent is null").List<Node>();


// Move first 2 children of root-0 to root-1
var children = new List<Node>(tree[0].Children);

tree[1].AddChild(children[0]);
tree[1].AddChild(children[1]);

// remove others children from root-1
children = new List<Node>(tree[0].Children);
foreach (var child in children)
{
tree[0].RemoveChild(child);
}

// move all nodes from actual root-1-child-0 to root-0
ReparentingAllChildren(tree[1].Children.First(), tree[0]);

tx.Commit();
}

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var tree = s.CreateQuery("from Node n where n.Parent is null").List<Node>();

tree.Count.Should("have only two roots").Be.EqualTo(2);

tree.Should("one should have four children")
.Satisfy(a => a.Any(x => x.Children.Count() == 4));

// get the root-1
var root1 = tree.FirstOrDefault(x => x.Children.Count() == 7);

root1.Should("have 7 children").Not.Be.Null();

// one of children should be empty (children was moved to root-0)
root1.Children.Should()
.Satisfy(a => a.Any(x => x.Children.Count() == 0));

// others children, should be intact
root1.Children.Count(c=> c.Children.Count() == 4).Should().Be.EqualTo(6);

tx.Commit();
}
ClearDb();
}

enough ?

The solution

Mapping
<class name="Node">
<
id name="Id">
<
generator class="hilo">
<
param name="max_lo">99</param>
</
generator>
</
id>
<
property name="Description"/>
<
many-to-one name="Parent" access="field.camelcase"/>
<
set name="Children" collection-type="TreeNodesCollectionType"
inverse="true" cascade="all, delete-orphan" access="field.camelcase">
<
key column="Parent"/>
<
one-to-many class="Node"/>
</
set>
</
class>
Custom collection type
public class TreeNodesCollectionType: IUserCollectionType
{
#region Implementation of IUserCollectionType

public IPersistentCollection Instantiate(ISessionImplementor session, ICollectionPersister persister)
{
return new PersistentNodeSet(session);
}

public IPersistentCollection Wrap(ISessionImplementor session, object collection)
{
return new PersistentNodeSet(session, (ISet<Node>)collection);
}

public IEnumerable GetElements(object collection)
{
return (IEnumerable)collection;
}

public bool Contains(object collection, object entity)
{
return ((ISet<Node>)collection).Contains((Node)entity);
}

public object IndexOf(object collection, object entity)
{
throw new NotSupportedException();
}

public object ReplaceElements(object original, object target, ICollectionPersister persister, object owner, IDictionary copyCache, ISessionImplementor session)
{
var result = (ISet<Node>)target;
result.Clear();

foreach (var o in (IEnumerable)original)
result.Add((Node)o);

return result;
}

public object Instantiate(int anticipatedSize)
{
return new HashedSet<Node>();
}

#endregion
}
Custom persistent collection
public class PersistentNodeSet : PersistentGenericSet<Node>
{
public PersistentNodeSet() {}

public PersistentNodeSet(ISessionImplementor session) : base(session) {}

public PersistentNodeSet(ISessionImplementor session, ISet<Node> original) : base(session, original) {}

public override System.Collections.ICollection GetOrphans(object snapshot, string entityName)
{
return base.GetOrphans(snapshot, entityName)
.Cast<Node>()
.Where(n=> ReferenceEquals(null,n.Parent))
.ToArray();
}
}

The custom type and custom persistent collection can be implemented in a more reusable way; where needed we can publish the implementation in uNhAddIns.

Conclusion

Perhaps NHibernate is silly but give you the opportunity to demonstrate your intelligence.

Code available here.

10 September 2009

NHibernate : Queries

How you can query your repository using NHibernate ?

In the NHibernate box you actually having seven ways:

  1. HQL
  2. Criteria
  3. QueryOver
  4. LINQ
  5. H-SQL
  6. SQL
  7. Custom DSL

HQL

HQL is the anachronism of : Hibernate Query Language. HQL, perhaps, is one of the most old and powerful ObjectOriented query system (at list in .NET). In JAVA HQL can be used to query entities persisted even in XML.

In my opinion HQL is the most powerful query system specific for a persistence-layer. Unfortunately, so far, we can’t change the .NET compiler integrating HQL to C# so, HQL is expressed in a string. In JAVA world they have an Eclipse plug-in to support intellisense and refactoring even for HQL but… in our world (.NET) we haven’t it, at least so far (look here ).

HQL does support even DML (obviously all still OO).

You can easy extend HQL through a custom implementation of Dialect.

Criteria

Criteria is a OO query API and is the better solution for dynamic queries (to avoid string concatenation of HQL).

Criteria is even extensible through implementations of ICriterion and IProjection. Using Criteria you can solve the problem of string-concatenation but you still have strings to specify properties names so: you can use Criteria for dynamic queries but there is no reason to use it for static queries.

QueryOver

QueryOver is a new way that will be available in NH3.0.0 (the next mayor release). QueryOver is based on Criteria (with same limitations/power) but, using lambdas expressions, the result clause is more readable and it support property-renaming because it does not suffer the “string” problem.

An example is here.

LINQ

Well… you should know what is LINQ. With NH2.1.0GA (the last release) we have deployed one implementation of a LINQ-provider based on Criteria (with the same limitations Criteria has). Steve Strong is working in a new provider and it will be available with NH3.0.0.

LINQ is a very powerful OO query system but not so specific for persistence. This fact give you a powerful system in memory but make the translation to SQL something complicated.

An example of this fact was reported by Steve in our dev-list

var q = from o in db.Orders
select new
{
o.OrderId,
DiscountedProducts =
from od in o.OrderLines
where od.Discount > 0.0m
select od, FreeShippingDiscount = o.Freight
};

to be efficiently executed we need a part translated to SQL and executed in one db-roundtrip and the other part should be executed in memory. The problem here is that you can’t optimize which should be the behavior with the persistent part as you can do in HQL using the “join fetch” clause.

H-SQL

An H-SQL is basically an standard SQL with some special tags. An example will be better than many words:

var q = session.CreateSQLQuery("select {sim.*} from Simple {sim} where {sim}.date_ = :fred")
.AddEntity("sim", typeof(Simple))
.SetTimestamp("fred", sim.Date);

Specials tags are “{sim.*}” and “{sim}”. The advantage of H-SQL is that you can use any kind of sentence supported by your specific RDBMS mixed we some more OO “tags”.

SQL

SQL is perhaps the most powerful DataCentric language. As HQL and H-SQL you can write your SQL in the mappings and use it through Named-Queries feature so you can write different SQL for different RDBMS without touch your C# code.

If you have a pure DataCentric task to do and you know how do it using SQL you don’t have a valid reason to find its translation using an OO query. For example:

SELECT ID,ClientID,
(SELECT COUNT(*) FROM Clock WHERE ClientID=c.ID AND Status='ON') AS ClocksUp
(SELECT COUNT(*) FROM Clocks WHERE ClientID=c.ID AND Status='OFF') AS ClocksDown
FROM Client AS c

Obviously you can use SQL even as DML

session.CreateSQLQuery("delete from VEHICLE where (TofC = 21) and (Owner = :owner)")
.SetString("owner", "NotThere")
.ExecuteUpdate();

DSL

You can even define your own DSL, to query your domain, and inject the translator through NHibernate’s configuration… but it is absolutely not a trivial task.

NHibernate actually have two available translators: one named “Classic query translator” and the other based on “HQL ANTLR-parser”.

Conclusion

When you have an issue using a “query system” leave the style/taste/fashion matters to Fashion TV and, as a good IT guy, have a look in your tool-box avoiding any kind of fundamentalism.

03 September 2009

Why don't choose NHibernate

Well… I’m here again over the same matter… again performance.

This post is about some thoughts after this thread on nhusers list and not strictly a comparison between NHibernate vs EntityFramework.

The comparison

To compare performances I have used again the same environment and the same domain used in this post but, this time, with 50 companies having 50 employees having 50 reports; total entities 127550.

So far I’m NOT an expert in EntityFramework (I’m waiting for EF4) so I have used the same configuration Gergely Orosz have used in his performance test. The code used for NHibernate is the same of the previous post and the code used, to materialize all entities, for EntityFramework is the follow:

using (var ctx = new EFContainer())
{
var companies = from c in ctx.EFCompanySet select c;
foreach (var company in companies)
{
company.Employees.Load();
foreach (var employee in company.Employees)
{
employee.Reports.Load();
}
}
}

The results of the test are

EntityFramework:

Store data seconds: 209,25 ( 209249 miliseconds)
Read data seconds: 57,77 ( 57773 miliseconds)

NHibernate:

Store data seconds: 24,29 ( 24287 miliseconds)
Read data seconds: 24,6 ( 24603 miliseconds)

Which is your conclusion ? NHibernate is faster than EntityFramework ? NHibernate is slow because the materialization of 127550 entities took 24.6” ?

That is what you are seeing ?

My conclusions

The first time I chose NHibernate was because:

  • I’m looking for a persistent-layer based on ORM
  • the license is LGPL
  • its development is based on the mature, and standard de-facto, JAVA world persistent-layer: Hibernate

On what is based your daily work ?

TDD? DDD? code maintainability? business request? YAGNI? easy to implements? XP? dead-line? elegant-code solutions? performance? sprint?

If the performance is the most important concept why you are not programming using assembler instead C# ?

Are you applying only one of these concepts or your work is a continuous balance of each ?

What I’m seeing, in many teams, is that, for various reasons, we are loosing the most important concept: the balance of each.

In front of the question “why you chose this solution ?” many times the answer is “because the dead-line is tomorrow” or “because it is the minimal code to pass my test” and so on. The worst results is not the mere answer itself but what will happen after… perhaps when you have a performance issue. If you saw that the solution you have chose does not satisfy the expectance why, rethink the whole solution, shouldn’t be an option ?

Have a quick look to your toolbox perhaps you having the right tool to solve the issue. What ? using that tool the code is not elegant ? it will be more hard to maintain ? it is more hard to implements ?… and? which is the main target of that specific task ?

As you can see above a persistent-layer based on ORM is not the right tool to perform bulk operations, is not the right tool to perform massive data mining, is not the right tool to provide data for OLAP cube… this mean that a persistent-layer based on ORM is not a good tool ? absolutely NOT my friend, that only mean that in your application you have a lot of different tasks and you should choose the right tool for each specific task…have a look to your toolbox!!!

01 August 2009

From DB to RAM: WellKnowInstanceType

How many times we are putting something in DB even if it is not needed ? No one ? sure ?

In these days I’m reviewing an application after four year rolling. I have checked the persistent states of some entities and they are in exactly the same state they was four years ago; why entities should not persist in compiled code ?

The enum is a special kind of these entities. If the value of the enum is enough for your needs all is fine. If you need something more than the value, as for example de description, some workaround may be enough. If you need something more than a value to persist and a “in memory description” ?

Example

A classic example of this situation is the entity Country. A possible simplification is:

public class Country
{
public int Id { get; protected set; }

public string Name { get; set; }
public short PhonePrefix { get; set; }
}

In this case, and let me say in various others cases in a real world application, an enum is not enough and a “DB persisted” entity is too much.

How many times you add a Country in your DB ? How many times you are changing the persistent state of a State/Province ? How many times you are deploying your application ?

From DB to RAM

This is the state of the art before change it

public class User
{
public virtual string Name { get; set; }
public virtual Country Country { get; set; }
}
<class name="User">
<
id type="int">
<
generator class="hilo"/>
</
id>
<
property name="Name"/>
<
many-to-one name="Country"/>
</
class>

To transform the entity Country in a well-know-instance, maintaining the logical relationship but simplifying all access to DB (remove possible N+1, lazy-loading, joins and so on), the best candidate, using NHibernate, is an implementation of IUserType but… a special one because I have a Identifier stored in the DB and I need some others properties.

the Countries repository

First of all I need a little change to the Country implementation

public class Country
{
internal Country(int id)
{
Id = id;
}

then a repository of countries.

public class Countries : ReadOnlyCollection<Country>
{
public static Country Argentina =
new Country(1) {Name = "Argentina", PhonePrefix = 54};
public static Country Italy =
new Country(2) {Name = "Italy", PhonePrefix = 39};

public Countries() : base(new[] {Argentina, Italy}) {}
}
the custom type

Here I will show only the ctor:

protected WellKnowInstanceType(
IEnumerable<T> repository,
Func<T, int, bool> findPredicate,
Func<T, int> idGetter)

The implementation of IUserType need:

  • The full repository (Countries)
  • The Func<T, int, bool> to convert an actual value stored in DB to an instance of the entity (Country)
  • The Func<T, int> to get the value to store in DB (the Country id)

My custom implementation of IUserType is:

public class CountryType : WellKnowInstanceType<Country>
{
public CountryType() : base(new Countries(), (e, k) => e.Id == k, e => e.Id) {}
}

The new mapping is:

<typedef name="Country"
class="uNhAddIns.Test.UserTypes.CountryType, uNhAddIns.Test"/>

<
class name="UserMitaMita">
<
id type="int">
<
generator class="hilo"/>
</
id>
<
property name="Name"/>
<
property name="Country" type="Country"/>
</
class>
Implications

Perhaps you will need to change some queries removing “join fetch” or “FetchMode.Eager” but believe me that your RDBMS will be happy for that (I don’t know how happy will be your DBA).

This is the example of queries extracted from uNhAddIns tests:

[Test]
public void Queries()
{
sessions.EncloseInTransaction(s =>
{
s.Save(new UserMitaMita { Name = "Fabio", Country = Countries.Argentina });
s.Save(new UserMitaMita { Name = "Maulo", Country = Countries.Italy });
});

sessions.EncloseInTransaction(s =>
{
var l = s.CreateQuery("from UserMitaMita u where u.Country in (:countries)")
.SetParameterList("countries", new[] { Countries.Argentina, Countries.Italy })
.List<UserMitaMita>();
l.Should().Have.Count.EqualTo(2);
});
sessions.EncloseInTransaction(s =>
{
var l = s.CreateQuery("from UserMitaMita u where u.Country = :country")
.SetParameter("country", (object)Countries.Argentina)
.List<UserMitaMita>();
l.Should().Have.Count.EqualTo(1);
l[0].Name.Should().Be.EqualTo("Fabio");
});
sessions.EncloseInTransaction(s => s.CreateQuery("delete from UserMitaMita").ExecuteUpdate());
}

The implementation of WellKnowInstanceType<T> is available in uNhAddIns (if you prefer copy&paste the code is available here).

The phrase

“The database only exist because we have not found a way to secure energy, in a permanent manner, to our servers” (by Angel java Lopez)