Try fast search NHibernate

22 December 2008

Implementing Conversation per Business Transaction

In the previous post I talked about the theory behind the pattern. This post is about its implementation.

Introduction

If you read my blog you know how much I like “Program to an interface and not to an implementation”; this mean that first of all you will see interfaces instead of classes.
One of the targets of this implementation is maintain the same style of the others “Session Easier” of uNhAddIns; this mean:

The big picture

IConversation
IConversation
Is a representation of a “Persistence conversation” I showed in the previous post. In addition there are some events.
ConversationException
Is the base exception for “all” conversation implementations.
IConversationFactory
So far I “don’t know” which will be the real implementation of the “Persistence conversation” (may be ADO.NET, may be NHibernate); its factory is needed.
IConversationContainer
As I said, in a IM, we may have more than one conversation happening at the same time. This fact still true for “Persistence conversation”. For a winForm application it is pretty easy to understand because, in the same application (mean same Thread), the user may activate more than one independent business-transaction. In a WEB application it still true because the user may open more than one browser-tab, in the same browser instance sharing the same HttpSession, activating various independent business-transaction (or better he sure hope that each tab are working in a independent persistence context).
IConversationsContainerAccessor
In my application I need something to access to the ConversationContainer instance (a sort of a specific ServiceLocator for ConversationContainer implementation) especially if I want allow the use of a formal DI container.

The implementation

ConversationImpl1
AbstractConversation
Encapsulation of the behavior of a generic Persistence conversation. The implementation, basically, define that each conversation have an ID defined at the moment of its creation, implements the EqualityComparer based on the ID, implements the Disposable pattern and implements the events managements. The real hard work will be done in the five abstract methods: DoStart, DoPause, DoResume, DoEnd, DoAbort.
NhConversation
At the end, I have arrived to the Persistence Conversation implemented for NHibernate. The base behavior was described at the end of the previous post, what I would explain here is the role of the two injected fields: factoriesProvider, wrapper.
The factoriesProvider is an implementation of ISessionFactoryProvider that is the class responsible to provide all ISessionFactory needed by our application. In uNhAddIns you have two available implementations to work with one or more than one RDBMS, respectively SessionFactoryProvider and MultiSessionFactoryProvider. In the MultiSessionFactoryProvider you can inject an instance of IMultiFactoryConfigurator or use the default implementation.
The wrapper is an implementation of ISessionWrapper. The main target of a wrapped session is the interception of the Close and Dispose. In uNhAddIns the base implementation are doing something more: it are ensuring that you are working applying a best practice for session&transaction management. The implementation of ISessionWrapper is the responsible to wrap a session and recognize a wrapped instance. In uNhAddIns, so far, you have two available implementations using Castle.DynamicProxy2 and LinFu.DynamicProxy. Obviously you can write your own implementation without transaction protection.
NHibernate Conversation solved, now the implementation of the others interfaces to work with Conversation-per-Business-Transaction pattern.
ConversationImpl2
DefaultConversationFactory
Nothing special to say, its implementation is trivial.
AbstractConversationContainer
Encapsulation of the behavior of the conversation container. What I’m not defining here is which will be the real context where the container are running, that mean where all conversation will be stored and where will be stored the current conversation id. The Store of conversation is a Dictionary<string, IConversation> where the key is the ConversationId and the value is an instance of an started conversation.
ThreadLocalConversationContainer
This is the implementation of the ConversationContainer for a winForm, or WPF, application. As you can see the CurrentId and the Store are two ThreadStatic fields.
ThreadLocalConversationalSessionContext
As I said at the begin of this post the “story” end when I have an implementation of ICurrentSessionContext. The implementation, at this point, is trivial but the advantage of an implementation of ICurrentSessionContext is really big:
  • Your DAOs/Repositories are wired only with NHibernate and nothing more than its SessionFactory.
  • You can change the strategy of session-handling without change absolutely nothing in your DAOs/Repositories
To be clear, about the advantage of an implementation of ICurrentSessionContext, take a look on how may appear an implementation of a simple DAO
public class SillyDao : ISillyDao
{
private readonly ISessionFactory factory;

public SillyDao(ISessionFactory factory)
{
this.factory = factory;
}

public Silly Get(int id)
{
return factory.GetCurrentSession().Get<Silly>(id);
}

public IList<Silly> GetAll()
{
return factory.GetCurrentSession().CreateQuery("from Silly").List<Silly>();
}

public Silly MakePersistent(Silly entity)
{
factory.GetCurrentSession().SaveOrUpdate(entity);
return entity;
}

public void MakeTransient(Silly entity)
{
factory.GetCurrentSession().Delete(entity);
}
}

As you can see I’m using factory.GetCurrentSession() this mean that my DAOs don’t know who and how the session is provided; don’t know nothing about uNhAddIns, don’t know nothing about conversation management.

Conclusion

The next step, perhaps before a working example, will be “Aspect Conversation-per-BusinessTransaction” to have the “Full cream” working together. If you are inpatient you can see it by your self.


kick it on DotNetKicks.com


21 December 2008

Conversation-per-Business-Transaction

In this post I will intent to describe a “new” pattern for NHibernate session management.

The Story

This pattern born some years ago, with another name “session-per-UseCase”, when I looking for a pattern to manage nh-sessions in Win-Form applications. The first implementation was not so clear and, before make it public, I have continued looking for some, well described, existing pattern. Two or three moths ago I was involved in another WinForm application, using NHibernate as persistence-layer, and I have re-begun the search for a pattern for session-handling in a rich-client application. This time my exigencies was something different because what I really want is a pattern to manage the session in complex applications even in web. By “complex-application” I mean an application where business-transactions involving more than one request is the norm and not the exception (for example a ERP of a big company). Using our best friend, Google, I find some few words about a pattern, used in JAVA, named “session-per-application-transaction” but his implementation is not so clear and is wired to some JAVA-world feature… unusable for me.

Session handling

When you read something about NHibernate-session-management is because we want abstract/”aspect” NH-session’s stuff from the code are using it. In general, or I hope so, you are using the session in something like a DAO/Repository and, in a use-case, you are calling more than one DAO/Repository. Open a new session in each DAO/Repository is an anti-pattern called session-per-call (or very closer to it). What we are searching is something to manage the session in an high-layer but without wire that layer with NHibernate. In a WEB environment it is pretty easy because we can manage the session using an implementation of a IHttpModule, or in the HttpApplication, “intercepting” the request (two patterns mentioned here). In a winForm, or WPF, aplication it is not so clear where the abstraction have place. In this post I will use an “artifact” named Model to represent the “abstraction-point” (in my mind the Model is the business-object that are using DAOs/Repository and domain-entities); in an MVC based application, probably, the abstraction have place in the Controller.

The Conversation

Perhaps you have idea about what is a “business-transaction” in your application but, what mean “conversation” ?

To describe the conversation I have imagined a chat between two persons. A chat may Start, Pause, Resume, and End. By “End” I mean: the end with some formal conclusion. Not all chats are terminated with “some formal conclusion” so, an event like Abort is needed. Resuming, in a conversation we may use five actions: Start, Pause, Resume, End, Abort. When I’m working in my PC, in general, I have more than one started chat, with more than one person. In my IM client, each chat is identified by an open form. In each chat I’m chatting about one specific matter, that mean that each chat have a specific context.

Resuming my conversation have: Id and Context properties, Start, Pause, Resume, End, Abort actions.

Can I apply the same concept to a persistence-conversation ?

Let me try…

ConversationSequence

First of all I have tried it using pure ADO.NET. In the ADO.NET scenario the Start and Resume of the conversation open a DbConnection and begin a DbTransaction, the Pause commit the DbTransaction and close the DbConnection; the End open a DbConnection, begin a DbTransaction, execute all pending db actions register in the UoW, commit the DbTransaction, close DbConnection, Dispose the UoW (obviusly I don’t spent so much time writing a good implementation of a PersistenceLayer nor UoW).

The Conversation with NHibernate

In NHibernate we have a well know and well described pattern named long-session (aka session-per-conversation). The description of the pattern is available in NHiA. For brevity here is the picture (extracted from Hibernate site)

session_conversation

As you can see there are various similar concepts between the session-per-conversation and Conversation-per-Business-Transaction. In Conversation-per-Business-Transaction there is one main difference: the Conversation is not a conceptual abstract description of what are happening but it is an interface with its concrete implementation.

To better understand let me explain what happen in Conversation-per-Business-Transaction:

  • Context: one object of the conversation context is the session (or better all sessions of all sessionFactories we are managing in a multi-RDBMS application).
  • Start : open a new session and hold it in the conversation-context (FlushMode.Never).
  • Resume : begin a nh-transaction
  • Pause : commit the nh-active transaction
  • End : begin a nh-transaction, Flush the session, commit the transaction
  • Abort : Close the session without Flush it

These are the base concepts behind the pattern.

If you want see one implementation of the pattern, even using Castle.Windsor to solve AOP, you can download uNhAddIns. I hope to have the time to write something more about the actual implementation soon.


kick it on DotNetKicks.com

15 December 2008

Identity: The never ending story

How many times you heard us saying “don’t use identity POID generator!” ?
To understand it better you must move your mind to an application, or a use-case, where the pattern open-session-in-view (aka session-per-request) is not applicable.

The Unit of Work

The Unit of Work (UoW) is a pattern described by Martin Fowler. When you work with NHibernate the real implementation of the pattern is the NH-Session (more exactly in PersistentContext inside de session). The commit and rollback, described in the pattern, are respectively the session.Flush() and the session.Close() (the close mean when close the session without Flush it). As usual the pattern described by Fowler is short and very clear so an explication is unneeded; here I want put more emphasis in two phrases:
“You can change the database with each change to your object model, but this can lead to lots of very small database calls, which ends up being very slow.”
“A Unit of Work keeps track of everything you do during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database as a result of your work.”
In addition, note, Fowler are talking about business transaction (repeat business-transaction).
In NHibernate, setting the FlushMode to FlushMode.Never (MANUAL in Hibernate), if you begin a NH-Transaction and commit it, but without a session.Flush, nothing happen in DB.

Analyze Session-per-conversation

SessionPerConversation
The session-per-conversation pattern is an example of a business transaction that spans multiple requests. As described by Fowler the nh-session (the real UoW) spans the whole business-transaction and in each request we are begin-commit a NH-Transaction. At the end of the conversation, inside a NH-Transaction, we will chose to Flush or Close the NH-session (mean commit or rollback the UoW).
In session-per-conversation we don’t want have a NH-Transaction (that, in this moment, mean a ADO.NET transaction) open for the whole conversation because not only is “impractical”, as said Fowler, but, in my opinion, it break the concept of ACID.

How to break all ?

If you want break the UoW pattern, and session-per-conversation pattern, you have a very easy way:use identity as your POID strategy.
The identity strategy mean :
  • change the database with each change to your object model (see the phrase above)
  • if you run a session.Save in the first request you will have a new record in the DB, and you can’t rollback this change without run an explicit Delete.
In addition I want say that using identity you are “disabling” the ADO-batcher NH’s feature for inserts.
You can continue using identity but you must know what you are loosing, and only you know what you are winning (I don’t know what you are winning using identity when you are working with a spectacular persistence layer as NHibernate is).

12 December 2008

WOW!

Si en mi “sucutrucho” logro hacer lo que hago, que pasaría con algo como esto ?

Me divorcio ? hmmmm me parece lo mas probable.

Artorius

A week ago I started a new project in uNhAddIns; the code-name is Artorius.

The base target of Artorius is the HQL-AST (perhaps is better to think about it as nHQL-AST).

The picture

ArtoriusStruct

The Story

The port of the string-AST-parser is an old task in NHibernate (perhaps one of my first occupation). Hibernate are using an old version of ANTLR Parser Generator and more than one year ago Ayende and I had tried the port of that code, in two different ways, but without a usable result. After that work I found GOLD and Diego Jancic (aka “The economist”) had begin a work to implement an string-AST-parser based on GOLD; unfortunately the work on OSS is hard to maintain and perhaps the state of NHibernate code-base, at that moment, was not ready to receive the new parser.

In uNhAddIns , after a request of my friend and after implement DetachedQuery, in a weekend born something like a game, named: DetachedDynQuery

The first time I think about Artorius was as an evolution of DetachedDynQuery; a real AST representation of an HQL query. I must admit that was a loooong thinking, without touch my keyboard, for various reason (the first is that now we have LINQ).

The Situation

To have a better idea about what nHQL-AST must support, I have begun the work from the string-AST-parser based on GOLD. The actual parser are passing the test available here (basically to test the grammar).

Browsing the code you can see that there are some other incomplete work but before start the real implementation of the nHQL-AST I prefer to complete the grammar. If you want navigate the BNF, of the actual grammar, you can download the HQL.htm file from here.

05 December 2008

The light

Yesterday I saw the light at the end of the tunnel.

The Oslo project.

Do you want avoid XML to map your domain ? Which language you want use to configure NH ? Why not English or Spanish or Italian ?

http://wm.microsoft.com/ms/msdn/oslo/mwindowexample.wmv

NHibernate have a lot of fireflies… the EntityMode.Xml are allowing something like this but using XML mappings.

Well…sorry it is incomparable.

The same base concept was provided by AjGenesis some years ago, but even if today AjGenesis are supporting text, instead XML, the MGrammar appear as a very powerful tool to create our DSL to generate all artifacts, including NHibernate mappings of course (I know… I know… AjGenesis is a project of “good soul”, behind MGrammar there is Microsoft).

28 November 2008

NHibernate: CALIDAD no se logra por casualidad

En estos últimos meses he visto, más de una vez, una serie de lindos “dibujos”, con colores, que pretendían demostrar la dudosa calidad de NHibernate. Como, por mi edad, he superado, ya hace tiempo, la celosía sobre código producido, la primera vez que vi ese análisis me pareció interesante sobre todo para aplicarla a algún otro proyecto. Todas las otras veces (7 u 8 en 5 meses) que vi ese link, con comentarios tipo “good luck to NH team” o “NH team should fix this problem”, ya empezó a parecerme un poco pesado sobre todo porque se evidencia un “posible problema”, una y otra vez, sin ocuparse de mostrar una “posible solución”. Tengo toda la sensación que se está usando NHibernate como medio para publicitar un producto comercial en lugar de hacer una crítica para mejorar NHibernate; si hubiera otra intención veríamos, adjunto a la crítica, una propuesta de cambios (por este motivo no publico el link a ese producto).

Les quiero dar mi personal opinión sobre la calidad de NHibernate analizándolo desde otro punto de vista; los hechos.

“por peso”

NH2.0.0 tuvo más de un año de desarrollo con más de 100.000 líneas de código entre modificadas y nuevas respecto a la versión anterior. NH2.0.1 tuvo más de 20.000 downloads en menos de 2 meses. NH2.0.x tiene más de 1400 tests entre tests unitarios y behavior-tests. En el team nadie tiene permiso de crear aunque sea un branch-official donde se pueda romper un solo test.

NH2.1.0 es el nombre de la próxima versión (el actual trunk). Por suerte, o tal vez por confianza y calidad, NHibernate tiene bastantes usuarios del trunk. NH2.1.0 posee casi 1600 tests que operan sobre más de 1100 clases por un total de casi 180.000 líneas de código C#.

¿Qué resultado da todo esto?

A hoy 80 bugs (o posibles bugs) de varios niveles, y más de 100 issues entre pedidos de nuevas features y mejorías; que representa 80 sobre la cantidad de lo que hay atrás, y las funcionalidades que NH ofrece, se lo dejo calcular a ustedes.

No sé a cuanta gente les preocupa como está hecho NH por adentro (a parte que para juzgarlo hay que conocerlo bien) pero que hasta el trunk se pueda considerar estable no es poca cosa.

Conclusión

La CALIDAD no se logra por casualidad; la calidad de un software se logra con muchos tests, reglas férreas en el team, y manteniendo la conciencia y el anhelo de mejorarse todos los días.

27 November 2008

La encuesta se terminó

Después de un mes la encuesta “How you are testing your persistence” se terminó.

La muestra no es para nada significativa y por lo que veo de los estadísticos de Google, sobre visitas a este blog, queda evidente que son muy pocos lo que le interesa dar a conocer como trabaja.

Lo resultados fueron:

Unit tests of entity and it's mapping  16 (53%)

From DAO / Repository  13 (43%)

From Model  1 (3%)

From user Interface  0 (0%)

Por lo menos me puedo quedar tranquilo que nadie votó por “From user Interface”.

26 November 2008

Entities behavior injection

If you are working with NH you know that NH likes POCOs and you must have a default constructor without parameters. Starting from today that is the past.

The domain

image

The implementation of Invoice is:

public class Invoice : IInvoice
{
private readonly IInvoiceTotalCalculator calculator;

public Invoice(IInvoiceTotalCalculator calculator)
{
this.calculator = calculator;
Items = new List<InvoiceItem>();
}

#region IInvoice Members

public string Description { get; set; }
public decimal Tax { get; set; }
public IList<InvoiceItem> Items { get; set; }

public decimal Total
{
get { return calculator.GetTotal(this); }
}

public InvoiceItem AddItem(Product product, int quantity)
{
var result = new InvoiceItem(product, quantity);
Items.Add(result);
return result;
}

#endregion
}

Are you observing something strange ?


  • There is not a property for the Id
  • There is not a default constructor without parameter

The Invoice entity are using an injectable behavior to calculate the total amount of the invoice; the implementation is not so important…

public class SumAndTaxTotalCalculator : IInvoiceTotalCalculator
{
#region Implementation of IInvoiceTotalCalculator

public decimal GetTotal(IInvoice invoice)
{
decimal result = invoice.Tax;
foreach (InvoiceItem item in invoice.Items)
{
result += item.Product.Price * item.Quantity;
}
return result;
}

#endregion
}

The full mapping:

<class name="Invoice" proxy="IInvoice">
<
id type="guid">
<
generator class="guid"/>
</
id>
<
property name="Description"/>
<
property name="Tax"/>
<
list name="Items" cascade="all">
<
key column="InvoiceId"/>
<
list-index column="pos"/>
<
composite-element class="InvoiceItem">
<
many-to-one name="Product"/>
<
property name="Quantity"/>
</
composite-element>
</
list>
</
class>

<
class name="Product">
<
id name="Id" type="guid">
<
generator class="guid"/>
</
id>
<
property name="Description"/>
<
property name="Price"/>
</
class>

The Test

[Test]
public void CRUD()
{
Product p1;
Product p2;
using (ISession s = sessions.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
p1 = new Product {Description = "P1", Price = 10};
p2 = new Product {Description = "P2", Price = 20};
s.Save(p1);
s.Save(p2);
tx.Commit();
}
}

var invoice = DI.Container.Resolve<IInvoice>();
invoice.Tax = 1000;
invoice.AddItem(p1, 1);
invoice.AddItem(p2, 2);
Assert.That(invoice.Total, Is.EqualTo((decimal) (10 + 40 + 1000)));

object savedInvoice;
using (ISession s = sessions.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
savedInvoice = s.Save(invoice);
tx.Commit();
}
}

using (ISession s = sessions.OpenSession())
{
invoice = s.Get<Invoice>(savedInvoice);
Assert.That(invoice.Total, Is.EqualTo((decimal) (10 + 40 + 1000)));
}

using (ISession s = sessions.OpenSession())
{
invoice = (IInvoice) s.Load(typeof (Invoice), savedInvoice);
Assert.That(invoice.Total, Is.EqualTo((decimal) (10 + 40 + 1000)));
}

using (ISession s = sessions.OpenSession())
{
IList<IInvoice> l = s.CreateQuery("from Invoice").List<IInvoice>();
invoice = l[0];
Assert.That(invoice.Total, Is.EqualTo((decimal) (10 + 40 + 1000)));
}

using (ISession s = sessions.OpenSession())
{
using (ITransaction tx = s.BeginTransaction())
{
s.Delete("from Invoice");
s.Delete("from Product");
tx.Commit();
}
}
}

In the previous week I tried to pass the test without change NH’s code-base. The first result was that I found a bug in NH and probably in Hibernate3.2.6, the second result was that it is completely possible to use NH with “fat” entities, without default constructor and using an IoC framework to inject behavior to an entity. After that work I realize that some little “relax” are needed in NH-code-base (NH-1587,NH-1588,NH-1589).

How pass the test

A very simple solution, to use an IoC with NH, is write a custom implementation of IInterceptor and use the Instantiate method to create an entity instance using an IoC container. The problem with this solution is that you still need a default constructor and… well… you must use the same interceptor for all sessions.

Another possible solution, for NH2.1 (trunk), is the use of a custom <tuplizer> for EntityMode.POCO. Probably I will write another blog-post about it.

If you are using the ReflectionOptimizer (used by default) there is a simple short-cut: I can write a IBytecodeProvider implementation based on Castle.Windsor container. The BytecodeProvider is another injectable piece of NH, trough the NHibernate.Cfg.Environment, before create the configuration. The BytecodeProvider has two responsibility: provide the ProxyFactoryFactory and provide the ReflectionOptimizer.

public class BytecodeProvider : IBytecodeProvider
{
private readonly IWindsorContainer container;

public BytecodeProvider(IWindsorContainer container)
{
this.container = container;
}

#region IBytecodeProvider Members

public IReflectionOptimizer GetReflectionOptimizer(Type clazz, IGetter[] getters, ISetter[] setters)
{
return new ReflectionOptimizer(container, clazz, getters, setters);
}

public IProxyFactoryFactory ProxyFactoryFactory
{
get { return new ProxyFactoryFactory(); }
}

#endregion
}
In this case, obviously, the ProxyFactoryFactory class is NHibernate.ByteCode.Castle.ProxyFactoryFactory.

Now the ReflectionOptimizer (using the fresh NH’s trunk):

public class ReflectionOptimizer : NHibernate.Bytecode.Lightweight.ReflectionOptimizer
{
private readonly IWindsorContainer container;

public ReflectionOptimizer(IWindsorContainer container, Type mappedType, IGetter[] getters, ISetter[] setters)
: base(mappedType, getters, setters)
{
this.container = container;
}

public override object CreateInstance()
{
if (container.Kernel.HasComponent(mappedType))
{
return container.Resolve(mappedType);
}
else
{
return container.Kernel.HasComponent(mappedType.FullName)
? container.Resolve(mappedType.FullName)
: base.CreateInstance();
}
}

protected override void ThrowExceptionForNoDefaultCtor(Type type)
{
}
}

As last, a quick view to the configuration:

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<
session-factory name="EntitiesWithDI">
<
property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<
property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<
property name="connection.connection_string">
Data Source=localhost\SQLEXPRESS;Initial Catalog=BlogSpot;Integrated Security=True
</property>
</
session-factory>
</
hibernate-configuration>

As you can see the configuration is minimal and, in this case, I don’t need to configure the “proxyfactory.factory_class” property because I will inject the whole BytecodeProvider.

[TestFixtureSetUp]
public void TestFixtureSetUp()
{
ConfigureWindsorContainer();
Environment.BytecodeProvider = new BytecodeProvider(container);
cfg = new Configuration();
cfg.AddAssembly("EntitiesWithDI");
cfg.Configure();
cfg.Interceptor = new WindsorInterceptor(container);
new SchemaExport(cfg).Create(false, true);
sessions = (ISessionFactoryImplementor) cfg.BuildSessionFactory();
}

The BytecodeProvider injection is the line after the configuration of Windsor container.

The configuration of the container is very simple:

protected override void ConfigureWindsorContainer()
{
container.AddComponent<IInvoiceTotalCalculator, SumAndTaxTotalCalculator>();
container.AddComponentLifeStyle(typeof (Invoice).FullName,
typeof (IInvoice), typeof (Invoice), LifestyleType.Transient);
}

Conclusions


  • The default ctor without parameter constraint was removed.
  • Use an IoC to inject behavior to an entity is possible and easy.

NOTE: Even if is possible to write an entity without the Id, the feature is not fully supported.

Code available here.



kick it on DotNetKicks.com

13 November 2008

NH with Multiple Assembly versions in GAC

I know that the title have something strange because NH don’t have nothing to do with GAC, but in NH-JIRA we have an issue with this title: “NHibernate does not support multiple versions of the same assembly for entity mapping”

Perhaps I don’t understand what that issue mean; I can’t understand what mean work we two mappings versions of the same entity… mean it work with two tables versions in the same DB at the same time ?

If the problem is not the mapping but the class implementation, NH are using, this is the solution.

Domain version 1.0.0.0

public class Person
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }

public virtual string FullName
{
get { return string.Concat(FirstName, "-", LastName); }
}
}

The mapping is:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Company.Domain"
namespace="Company.Domain">
<
class name="Person">
<
id name="Id">
<
generator class="native"/>
</
id>
<
property name="FirstName"/>
<
property name="LastName"/>
</
class>
</
hibernate-mapping>

Note: In the mapping I don’t write anything about the version of the assembly.

Sign, and compile the domain, and add it to the GAC.

GACAdded

Domain version 1.1.0.0

public class Person
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }

public virtual string FullName
{
get { return string.Concat(LastName, "*", FirstName); }
}
}

As you can see there is a different implementation of the property FullName.

Compile and add the new version to the GAC.

GACAddedBoth

The Test

Without make a completely automated test…

[Test]
public void SomebodySaidIsABug()
{
var version = typeof (Person).Assembly.GetName().Version.ToString();
Console.WriteLine("Running version {0}", version);

object savedId;
using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var a = new Person {FirstName = "Pasqual", LastName = "Angulo"};
savedId = s.Save(a);
tx.Commit();
}

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var a = s.Get<Person>(savedId);
if(version == "1.0.0.0")
Assert.That(a.FullName, Is.EqualTo("Pasqual-Angulo"));
else
Assert.That(a.FullName, Is.EqualTo("Angulo*Pasqual"));
tx.Commit();
}

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
s.Delete("from Person");
tx.Commit();
}
}

I’m showing the loaded version used in tests (that, in this, case represent the assembly with the responsibility of DataAccess) and changing the expected value of FullName according with the assembly version.

The assembly referenced by the test project, at design time, is not important.

The App.config of the test is:

<configSections>
<
section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"/>
</
configSections>

<
hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<
session-factory name="Company">
<
property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<
property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<
property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<
property name="connection.connection_string">
Data Source=localhost\SQLEXPRESS;Initial Catalog=BlogSpot;Integrated Security=True
</property>
<
property name="show_sql">false</property>
<
property name="use_outer_join">true</property>
<
property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
<
property name="command_timeout">60</property>
<
property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>

<
mapping assembly="Company.Domain"/>

</
session-factory>
</
hibernate-configuration>
I’m loading the assembly with all mappings, trough the session-factory configuration, another time without specify the assembly strong name.
Compile the test project and close VisualStudio. Now go to the output folder (bin/Debug) and delete the Company.Domain.dll file. Then open NUnit.Gui.
The situation at this point is:
  • Two version of Company.Domain.dll in the GAC.
  • Visual Studio Closed
  • The test compiled and the Company.Domain.dll removed
  • NUnit.GUI opened
Because I'm not using the strongly name of Company.Domain.dll, running the test what I expect is that it fail
NunitNoOk0  
Perfect!! Assembly not found. Now I can start to play with the compiled configuration file (DiffAssemblyVersion.dll.config) using the NotePad.
    <runtime>
<
assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" applies-to="v2.0.50727">
<
qualifyAssembly partialName="Company.Domain"
fullName="Company.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5c41dce254553643" />
</
assemblyBinding>
</
runtime>

Now, if I reload the assembly in NUnit.GUI, the assembly will be loaded from GAC.

NunitOk10

Now I want run the test but using the 1.1.0.0 version. Using NotePad again the new config is:

<runtime>
<
assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" applies-to="v2.0.50727">
<
qualifyAssembly partialName="Company.Domain"
fullName="Company.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5c41dce254553643" />
<
dependentAssembly>
<
assemblyIdentity name="Company.Domain"
publicKeyToken="5c41dce254553643"/>
<
bindingRedirect oldVersion="1.0.0.0"
newVersion="1.1.0.0"/>
</
dependentAssembly>
</
assemblyBinding>
</
runtime>

Reload the assembly in NUnit.GUI and re-run it:

NunitOk11

Work done.

Code available here.

Technorati Tags:

12 November 2008

Mapping Source: How map a class without use XML

I don’t know how many times you heard a mad man talking about “mapping source” in NHibernate…

Map a class in NH without use XML at all ? only a crazy man can say that.

Hello! I’m that mad man.

As usual an entity implementation:

public class Animal
{
public virtual int Id { get; private set; }
public virtual string Description { get; set; }
}

Is a simple class because map something else, and begin a new framework, is not the target of this post.

Now an empty method, to write an integration test, of a new class inherited from the NHibernate configuration class:

public class Configuration : NHibernate.Cfg.Configuration
{
public void Register(Type entity){}
}

The integration test, basically, include the SchemaExport, a CRUD and an HQL; what is interesting here is only the setup of the test:

protected Configuration cfg;
protected ISessionFactoryImplementor sessions;

[TestFixtureSetUp]
public void TestFixtureSetUp()
{
cfg = new Configuration();
cfg.Configure();
cfg.Register(typeof(Animal));
new SchemaExport(cfg).Create(false, true);
sessions = (ISessionFactoryImplementor)cfg.BuildSessionFactory();
}

As you can see is similar to a common setup except for cfg.Register(typeof(Animal)). The others parts of the test are available from the download link.

Now I can start the dance…

In NHibernate all classes metadata are completely decoupled from XML; this mean that SchemaExport, and everything else in NH, absolutely don’t need XML files to be used. What I must do is inject everything after call the method cfg.Configure(). The place where all metadata are available is the namespace NHibernate.Mapping. The holder of metadata is the class Configuration trough the class NHibernate.Cfg.Mappings. The provider of an instance of NHibernate.Cfg.Mappings is the Configuration itself trough the method:

/// <summary>
///
Create a new <see cref="Mappings" /> to add classes and collection
/// mappings to.
/// </summary>
public Mappings CreateMappings(Dialect.Dialect dialect)

That method stay there from loooong time ago.

As we are doing in NH-Core each “binder” must use at least two classes (to create new metadata):

  1. an instance of NHibernate.Cfg.Mappings
  2. the instance of the configured Dialect

The configuration extension

public class Configuration : NHibernate.Cfg.Configuration
{
public void Register(Type entity)
{
Dialect dialect = Dialect.GetDialect(Properties);
Mappings mappings = CreateMappings(dialect);
SetDefaultMappingsProperties(mappings);
new EntityMapper(mappings, dialect).Bind(entity);
}

private static void SetDefaultMappingsProperties(Mappings mappings)
{
mappings.SchemaName = null;
mappings.DefaultCascade = "none";
mappings.DefaultAccess = "property";
mappings.DefaultLazy = true;
mappings.IsAutoImport = true;
mappings.DefaultNamespace = null;
mappings.DefaultAssembly = null;
}
}

For each class, I’m going to register, I’m getting the configured dialect and a new instance of Mappings class. Then I’m setting some default values and at the end I’m biding the entity type (EntityMapper(mappings, dialect).Bind(entity)).

The EntityMapper

Without boring you, with the full code, the heart is here

public void Bind(Type entity)
{
var rootClass = new RootClass();
BindClass(entity, rootClass);
}

private void BindClass(Type entity, PersistentClass pclass)
{
pclass.IsLazy = true;
pclass.EntityName = entity.FullName;
pclass.ClassName = entity.AssemblyQualifiedName;
pclass.ProxyInterfaceName = entity.AssemblyQualifiedName;
string tableName = GetClassTableName(pclass);
Table table = mappings.AddTable(null, null, tableName, null, pclass.IsAbstract.GetValueOrDefault());
((ITableOwner) pclass).Table = table;
pclass.IsMutable = true;
PropertyInfo[] propInfos = entity.GetProperties();

PropertyInfo toExclude = new IdBinder(this, propInfos).Bind(pclass, table);

pclass.CreatePrimaryKey(dialect);
BindProperties(pclass, propInfos.Where(x => x != toExclude));
mappings.AddClass(pclass);

string qualifiedName = pclass.MappedClass == null ? pclass.EntityName : pclass.MappedClass.AssemblyQualifiedName;
mappings.AddImport(qualifiedName, pclass.EntityName);
if (mappings.IsAutoImport && pclass.EntityName.IndexOf('.') > 0)
{
mappings.AddImport(qualifiedName, StringHelper.Unqualify(pclass.EntityName));
}
}

Including everything the EntityMapper.cs have 198 lines.

Metadata classes used are: RootClass, PersistentClass, Table, SimpleValue, Property and Column.

Conclusions

To use NHibernate without write a single XML mapping, is possible. Create mapped classes or others artifacts (as typedef, database-objects, named-queries, stored-procedures, filters and so on) without use XML, is possible. Because I’m extending the NHibernate.Cfg.Configuration, add some other artifacts or override mapping written using XML is possible. Write a “bridge” using EntityFramework attributes instead XMLs, is possible.

Write a new framework avoiding XML at all, is possible that is completely different than “is easy”. In general a framework is to make something easy to the framework users and not to the framework developers.

Code available here.


Technorati Tags: ,

07 November 2008

La concorrenza é l’anima del commercio

Que linda frase es esa: La competencia es el alma del comercio.

Hace un tiempo largo en NHibernate implementé IProxyFactoryFactory (porting, con adaptación, desde Hibernate). Como me está pasando, últimamente, nadie entendía para que “esa cosa” es necesaria, hasta que un día un committer me escribe en privado diciéndome: “al final hay alguien que entiende para que hiciste ese trabajo” y me engancha un link. El link llevaba al blog de William C. Pierce que usó IProxyFactoryFactory junto a un tool para generar proxies que pudieran trabajar en médium-trust. Junto con la movida que hicimos para dar a la luz NH-Forge, Bill Pierce, no solo aceptó entrar en NHibernate-Contrib si no que aceptó “rever” su trabajo y cambiarle de nombre a NHibernate.ProxyGenerators (notar el plural). Hasta ese entonces el plural era, lamentablemente, solo una mera intención…

Un día, de la nada, aparece un branch en NH-Core que llevaba todo el código de NH y una implementación de un ProxyFactoryFactory para usarlo con PostSharp (come venia pensándolo hace un tiempo); el problema del branch es que todavía estaba todo incrustado a parte que no pasa la mayoría de los tests de NH. Quédense en este día porque fue el disparador…

En todo este periodo había unos asuntos que me estaban molestando no poco:

  • Pocos son lo que entienden que el hecho de declarar métodos “virtual” no es una invasión de NH.
  • NH parecía no funcionar si no existiera Castle.
  • Quien usa Spring igualmente se tiene que llevar Castle.
  • En Castle no quieren liberar release y quieren que todos trabajemos con el trunk.
  • NH tenía una dependencia a algo sin versiones.
  • La gente que usaba NH con Castle Windsor y/o ActiveRecord se volvía loca al intentar mantener todos los proyectos sincronizado.

De buen tano calentón que soy (tano=Italiano en Buenos Aires) ese día me cansé y decidí dedicar el día a “separar los tantos” y la mañana siguiente pude anunciar la anhelada separación de dependencia desde Castle.DynamicProxy2 versión x.y.z (cualquiera porque no tiene, nunca fue liberado desde casi dos años).

Bueno… lo único que faltaba era solo empezar a generar alternativas… Den una vista a este link, al fondo, y fíjense cuan larga fue esta historia; falta muy poco para que cumpla un año. Hoy puedo anunciar la primera alternativa a Castle.DynamicProxy2 en NHibernate. Nació NHibernate.ProxyGenerators.LinFuDynamicProxy.

LinFuDynamicProxy será, probablemente, la alternativa que usarán quien no usa ningún IoC-FW en su proyecto ya que es una sola DLL, pesa 23KB (para NET3.5) y tiene una leve mejora en performance respecto a Castle (no estoy completamente seguro pero me pareció midiendo los tiempos de ejecución de los tests de NH).

Para quien usamos IoC falta un paso; ¿no se imaginan cual? No sé exactamente para cuando, pero espero pronto sea disponible NHibernate.ProxyGenerators.SpringDynamicProxy.

¡A ver si se logra trabajar con algo que tenga versión! ;-)

 Technorati Tags: ,,,,

26 October 2008

entity-name in action: Entity Abstraction

Another time I start from :

“Program to an interface and not to an implementation”

I want have the same approach, I’m using for DAOs, Models, Presenters, Validation, and so on, for my domain.

The domain:

public interface IEntity<TIdentity>: IEquatable<IEntity<TIdentity>>
{
TIdentity Id { get; }
}

public interface IAnimal : IEntity<int>
{
string Description { get; set; }
}

public interface IReptile : IAnimal
{
float BodyTemperature { get; set; }
}

public interface IHuman : IAnimal
{
string Name { get; set; }
string NickName { get; set; }
DateTime Birthdate { get; set; }
}

public interface IFamily<T> : IEntity<int> where T : IAnimal
{
T Father { get; set; }
T Mother { get; set; }
ISet<T> Childs { get; set; }
}

Because I’m going to work with interfaces I will need a sort of factory to have transient-instances of my entities. For this example I’m going to use something simple and more “general purpose”; a class resolver:

public interface IClassResolver : IDisposable
{
T Resolve<T>() where T : class;
T Resolve<T>(string service) where T : class;
}

The responsibility of the IClassResolver implementor is return an instance for a given Type where the Type is an interface (well… in general is an interface). The concrete implementation of a IClassResolver will be injected using some IoC framework but for this post I will use a simple static exposer:

public class DI
{
private static IClassResolver resolver;
private DI() {}

public static IClassResolver Resolver
{
get
{
if (resolver == null)
{
throw new InvalidOperationException("Resolver was not initialized. Use StackResolver.");
}

return resolver;
}
}

public static void StackResolver(IClassResolver dependencyResolver)
{
resolver = dependencyResolver;
}
}

As you can see nothing so complicated.

Now I have all needed to write a test for my domain:

[Test]
public void DomainAbstraction()
{
using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var rf = DI.Resolver.Resolve<IReptile>();
rf.Description = "Crocodile";

var rm = DI.Resolver.Resolve<IReptile>();
rm.Description = "Crocodile";

var rc1 = DI.Resolver.Resolve<IReptile>();
rc1.Description = "Crocodile";

var rc2 = DI.Resolver.Resolve<IReptile>();
rc2.Description = "Crocodile";

var rfamily = DI.Resolver.Resolve<IFamily<IReptile>>();
rfamily.Father = rf;
rfamily.Mother = rm;
rfamily.Childs = new HashedSet<IReptile> { rc1, rc2 };

s.Save(rfamily);
tx.Commit();
}

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var hf = DI.Resolver.Resolve<IHuman>();
hf.Description = "Flinstone";
hf.Name = "Fred";

var hm = DI.Resolver.Resolve<IHuman>();
hm.Description = "Flinstone";
hm.Name = "Wilma";

var hc1 = DI.Resolver.Resolve<IHuman>();
hc1.Description = "Flinstone";
hc1.Name = "Pebbles";

var hfamily = DI.Resolver.Resolve<IFamily<IHuman>>();
hfamily.Father = hf;
hfamily.Mother = hm;
hfamily.Childs = new HashedSet<IHuman> { hc1 };

s.Save(hfamily);
tx.Commit();
}

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
var hf = s.CreateQuery("from HumanFamily").List<IFamily<IHuman>>();

Assert.That(hf.Count, Is.EqualTo(1));
Assert.That(hf[0].Father.Name, Is.EqualTo("Fred"));
Assert.That(hf[0].Mother.Name, Is.EqualTo("Wilma"));
Assert.That(hf[0].Childs.Count, Is.EqualTo(1));

var rf = s.CreateQuery("from ReptilesFamily").List<IFamily<IReptile>>();

Assert.That(rf.Count, Is.EqualTo(1));
Assert.That(rf[0].Childs.Count, Is.EqualTo(2));

tx.Commit();
}

using (ISession s = sessions.OpenSession())
using (ITransaction tx = s.BeginTransaction())
{
s.Delete("from HumanFamily");
s.Delete("from ReptilesFamily");
tx.Commit();
}
}

Note: s.Save(hfamily) <<=== there isn’t a string for the entity-name; now NH are supporting it.

As you can see the users of my domain (the test in this case), are working only using interfaces; there isn’t a reference to a concrete implementation of my domain. The concrete implementation of the domain is trivial and you can see it downloading the code. The main thing you will notice, in the implementation, is the absence of the virtual modifier.

Wiring…

To wire the interface, with its concrete implementation, I want use NHibernate. The mapping is similar to the previous:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="EntityNameInAction.Abstraction.Entities.Impl"
namespace="EntityNameInAction.Abstraction.Entities.Impl.Naturalness"
default-access="backfield">

<
class name="MyAnimal" abstract="true"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IAnimal, EntityNameInAction.Abstraction.Entities"
entity-name="Animal">
<
id name="id" access="field">
<
generator class="hilo"/>
</
id>
<
discriminator column="kind"/>
<
property name="Description"/>
</
class>

<
subclass name="MyHuman"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IHuman, EntityNameInAction.Abstraction.Entities"
extends="Animal"
entity-name="Human">
<
property name="Name"/>
<
property name="NickName"/>
<
property name="Birthdate" type="Date"/>
</
subclass>

<
subclass name="MyReptile"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IReptile, EntityNameInAction.Abstraction.Entities"
extends="Animal"
entity-name="Reptile">
<
property name="BodyTemperature"/>
</
subclass>

<
class name="MyFamily`1[[EntityNameInAction.Abstraction.Entities.Naturalness.IReptile, EntityNameInAction.Abstraction.Entities]]"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IFamily`1[[EntityNameInAction.Abstraction.Entities.Naturalness.IReptile, EntityNameInAction.Abstraction.Entities]], EntityNameInAction.Abstraction.Entities"
table="Families" discriminator-value="Reptile" where="familyKind = 'Reptile'"
entity-name="ReptilesFamily">
<
id name="id" access="field">
<
generator class="hilo"/>
</
id>
<
discriminator column="familyKind"/>
<
many-to-one name="Father" cascade="all" entity-name="Reptile"/>
<
many-to-one name="Mother" cascade="all" entity-name="Reptile"/>
<
set name="Childs" generic="true" cascade="all">
<
key column="familyId" />
<
one-to-many entity-name="Reptile"/>
</
set>
</
class>

<
class name="MyFamily`1[[EntityNameInAction.Abstraction.Entities.Naturalness.IHuman, EntityNameInAction.Abstraction.Entities]]"
proxy="EntityNameInAction.Abstraction.Entities.Naturalness.IFamily`1[[EntityNameInAction.Abstraction.Entities.Naturalness.IHuman, EntityNameInAction.Abstraction.Entities]], EntityNameInAction.Abstraction.Entities"
table="Families" discriminator-value="Human" where="familyKind = 'Human'"
entity-name="HumanFamily">
<
id name="id" access="field">
<
generator class="hilo"/>
</
id>
<
discriminator column="familyKind"/>
<
many-to-one name="Father" cascade="all" entity-name="Human"/>
<
many-to-one name="Mother" cascade="all" entity-name="Human"/>
<
set name="Childs" generic="true" cascade="all">
<
key column="familyId" />
<
one-to-many entity-name="Human"/>
</
set>
</
class>
</
hibernate-mapping>

Mapping highlight


  • class/subclass name: are my concrete classes (implementors of domain)
  • proxy : is the interface (the domain); using it as proxy I can avoid virtual methods in the implementation because the underlining Dynamic-Proxy will inherit from the interface. Using interface I have many others vantages but is to long explain each (only one for example: I can cast a proxy-instance to an interface)
  • entity-name :  is the name I will use for persistence and represent another abstraction-level. For persistence stuff I can use a “conceptual-name” of the entity without take care about its representation in C#. As you can see the entity-name are playing on each association/aggregation/extends; not the concrete class nor the interface.
  • As in this post the domain is represented in two tables.

Class Resolver

In the implementation of IClassResolver I’m going to use the NHibernate’s mapping to wire the interface of the domain (ex: IHuman) to its concrete class (ex: MyHuman) trough the entity-name. Is it not clear ? ok perhaps the code will be more clear

public class NhEntityClassResolver : IClassResolver
{
private readonly Dictionary<Type, string> serviceToEntityName = new Dictionary<Type, string>();
public NhEntityClassResolver(ISessionFactoryImplementor factory)
{
if(factory == null)
{
throw new ArgumentNullException("factory");
}
Factory = factory;
InitializeTypedPersisters();
}

private void InitializeTypedPersisters()
{
foreach (var entityName in Factory.GetAllClassMetadata().Keys)
{
serviceToEntityName
.Add(Factory.GetEntityPersister(entityName)
.GetConcreteProxyClass(EntityMode.Poco), entityName);
}
}

public ISessionFactoryImplementor Factory { get; private set; }

#region Implementation of IDisposable

public void Dispose()
{
}

#endregion

#region
Implementation of IClassResolver

public T Resolve<T>() where T : class
{
string entityName;
if(serviceToEntityName.TryGetValue(typeof(T), out entityName))
{
return Resolve<T>(entityName);
}
return null;
}

public T Resolve<T>(string service) where T: class
{
return Factory.GetEntityPersister(service).Instantiate(null, EntityMode.Poco) as T;
}

#endregion
}

The ISessionFactoryImplementor is one of the interfaces implemented by the NH SessionFactory. The method Resolve<T>(string) are using the parameter service as the entity-name. The hard-work is done by the method InitializeTypedPersisters; what I’m doing there is map each interface with its entity-name… nothing more.

Conclusions

“Program to an interface and not to an implementation” is really wonderful.

Do you really have some doubt about how NHibernate implements “Persistence ignorance” ?

Code available here.