31.12.08

It’s the domain stupid!

OR mapping ,regardless of the mechanics employed, shifts the weight of enterprise software development from thinking about persistence to actually cogitating the problem space. I am now forced to think long and hard about the best aggregation or composition approaches for each of my domain objects. And this is precisely what my customer is paying me for. As Ayende says, “persistence is a solved problem”.

30.12.08

Mapping Subclasses in NHibernate

ContactTest.TestAddContactNotes : Failed

NHibernate.MappingException: No discriminator found for Zainco.YCW.Components.Domain.ContactNote. Discriminator is needed when 'single-table-per-hierarchy' is used and a class has subclasses

at NHibernate.Mapping.SingleTableSubclass.Validate(IMapping mapping)
at NHibernate.Cfg.Configuration.Validate()
at NHibernate.Cfg.Configuration.BuildSessionFactory()
at Zainco.YCW.Components.Utils.NHibernateHelper.get_Session() in NHibernateHelper.cs:line 13
at Zainco.YCW.Tests.ContactTest.TestAddContactNotes() in ContactTest.cs:line 94

This was due to an incorrect mapping strategy. Instead of using the table per hierarchy strategy, I resorted to using the table per subclass mapping strategy. The base table, Note, contains the elements common to my subclasses and the ContactNote maintains the association between the contact and the Note. I have a variety of Notes in the system(CommunityNotes, ParishNotes etc).

The mapping file for this strategy is:

<class name="Note" table="Note">
<
id name="Id" column="Id">
<
generator class="native"/>
</
id>
<
property name="Content"/>
<
property name="DatePublished"/>
<
joined-subclass name="ContactNote" table="ContactNote">
<
key column="NoteId"/>
<
many-to-one class="Contact" column="ContactId" name="Contact"/>
</
joined-subclass>
</
class>

20.12.08

Refactoring to DetachedNameQuery

The consequence of hiding the NHibernate ISession type from the client code is that I now have to rely on inline SQL which kind of makes me queasy. But this feeling is temporary because I can use a feature of NHibernate called DetachedNameQuery to achieve the following:


IRepository repository = new NHibernateRepository();
IDetachedQuery query = new DetachedNamedQuery("GetMaxTaskId");
ITask task = repository.Find<Task>(query);

GetMaxTaskId is defined in my NHibernate mapping file, Task.hbm.xml.

The entry takes the following form:

<query name ="GetMaxTaskId">
<
![CDATA[
select max(task.Id) from Task task
]]>
</query>

This really does feel good, especially when you type like I do

ITask task = new Task { Description = "Coding for fun", DueDate = DateTime.Now, IsCompleted = false, Categories = new HashedSet() };

contrast with the old way of doing things

ITask task = TaskFactory.Instance;
task.Description = "Yak Shaving";
task.IsCompleted = false;

.
.


It's the small things like this that make for a more productive coding experience. The intent is more direct and one quickly gets to the destination in a DRY way. Nice!

NHibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed

I have implemented a repository that essentially wraps up and centralises my calls to the NHibernate API. This facade is responsible for creating and disposing the NHibernate session.

Clients do not directly interact with the session.

So I use the IDetachedQuery interface to hold my queries like soz:

IDetachedQuery query = new DetachedQuery("...");

ITask task = repository.Find <Task>(query);

My task has a collection of categories which I am attempting to clear, but the session with which this collection is associated has already been disposed, so looks like I am going to have to force the collection to initialise before I return from the find method. The other option is to eagerly load the stuff i.e. set lazy loading to false.

As in Hibernate non-lazy loading is the default for loading collections in NHibernate. The solution to this problem was a case of setting the lazy attribute to false like this:

<set name="Categories" table="TaskCategory" lazy="false" cascade="all">

NHibernate can also be forced to initialize the collection by calling NHibernateUtil.Initialize(myObject) before the session is disposed.

18.12.08

Perhaps NHibernate Mapping attributes are poisonous

I have spent the best part of a working day experimenting with using NHibernate atrributes after starting off with .hbm.xml mapping files.

The result is a domain model that's very NHibernate aware, I cannot reuse the model without there being a whiff of NHibernate. This being the case, I have decided that xml mapping files are probably the way forward. I am aware of other mapping approaches, but perhaps, the verbosity and loosely coupled approach of mapping files has its advantages.

Yes attributes and mapping approaches use a declarative style, but one can not help feeling that embedding persitence crosscutting concerns in domain model could cause grief further down. Mapping files, you have a new friend.

9.12.08

An NHibernate Helper for working with the NHibernate.Mapping.Attributes API

Authoring, maintaining and managing NHibernate mapping files, hbm.xml, can quickly turn into a full-time job on large projects. One way of effectively accomplishing this vital, but burdensome task is to use the NHibernate contrib, NHibernate.Mapping.Attributes.


This will requires configuration information to be placed in an app.config file as documented in the NHibernate documentation. One is then required to have a single well known location from where to obtain an instance of the ISession(think PersistenceManager) type. The code below shows how to configure the serializer and return an ISession:


using System.IO;
using System.Reflection;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Mapping.Attributes;

namespace Zainco.YCW.Components.Utils
{
public sealed class NHibernateHelper
{
private static ISession _session;
public static ISession Session
{
get
{
if (_session == null)
using (MemoryStream stream = new MemoryStream())
{
HbmSerializer.Default.Validate = true;
HbmSerializer.Default.HbmNamespace = "Zainco.YCW.Components.Domain";
HbmSerializer.Default.HbmAssembly = "Zainco.YCW.Components";
HbmSerializer.Default.Serialize(stream, Assembly.GetExecutingAssembly());

stream.Position = 0;

Configuration cfg = new Configuration();
cfg.Configure();
cfg.AddInputStream(stream);
_session = cfg.Configure().BuildSessionFactory().OpenSession();

}

return _session;
}
}
}
}

System.Data.SqlClient.SqlException: Invalid object name 'hibernate_unique_key' when using SQL Server 2005

This problem occurs when attempting to persist an entity

the actual code that causes this is:

session.Save(contact);

The Id attribute on the contact entity is configured as:

[Id(Name = "Id", Type = "int")]
[Generator(Class = "hilo")]
public virtual int Id


ContactTest.TestAddContact : FailedSystem.Data.SqlClient.SqlException: Invalid object name 'hibernate_unique_key'.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()
at NHibernate.Id.TableGenerator.Generate(ISessionImplementor session, Object obj)
at NHibernate.Id.TableHiLoGenerator.Generate(ISessionImplementor session, Object obj)
at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.Save(Object obj)
at Tests.ContactTest.TestAddContact() in ContactTest.cs:line 20


The solution is to use the native option, this picks identity, sequence, hilo depending on the capabilities of the underlying RDBMS.

[Id(Name = "Id", Type = "int")]
[Generator(Class = "native")]
public virtual int Id
{

4.12.08

Permission error when trying to open a new database connection from an XBAP

If you get the SecurityException below whilst developing an XBAP application

{"Request for the permission of type 'System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed."} System.Exception {System.Security.SecurityException}


This is because the default security mode for an XBAP is partial trust. The XBAP is sandboxed and has restricted permissions to the file system, database etc. The .NET Framework uses code access security to limit what the XBAP can do. This is kind of consistent with the Flash, Java applets paradigm that XBAP tries to emulate.

It is tempting to assign the application trust via the following mechanism:

In VS2008, do the following:
Double click the VS projects' Properties node containing the XBAP-> Select Properties->Choose the security tab-> Select the option which says "This is a full trust application"->

However this Full Trust permissioning has potential drawbacks that require unpalatable workarounds.

The side effect of the change is that me XBAP can not now be run from a virtual directory or website.

This leaves me to wonder. Is what I need an XBAP, SilverLight application, a standalone XAML application or God forbid an ASP.NET app?

I still want the rich internet application experience and I still want to have a centralised web-like configuration management model. The last thing I want is to be touching each clients' machine to tweak a setting here and a setting there. Because this approach inevitably ends in tears.

I also do not want to implement orthogonal constructs that check for permissions and end up littering the codebase with try/catch blocks that test for permissions.

So in the end after careful consideration of my problem context, SilverLight is the way to go.

A unit testing framework in Turbo Pascal

Why Turbo Pascal? Because it reminds me of the joy that I went through trying to learn/reason about software construction and partly because of the turbo button on my first computer. I had it permanently on as if it that would make the world go faster. Now we have multi-core machines, hyperthreading, desktop Beowulfs and grids. Hey but I digress.

The main point of this exercise is to implement an xUnit testing framework using Pascal. This follows on from a segment in Kent Becks' book, Test Driven Development, in which Mr. Beck implements an xUnit framework in python.

TODO add code here.

Type registry and the Factory Method

When implementing the Gofian Factory Method creational pattern it is normally the case that the client requiring the instance needs to tell the object factory what kind of object it needs to make. The internals of the factory method that decide what object to return usually resembles the following

public class Creator
{
:
public static IVehicle Create(VehicleType vehicleType)
{
IVehicle vehicle = new Chisasa();
if(VehicleType.Sedan)
vehicle = new Sedan();
if(VehicleType.FourByFour)
vehicle = new FourByFour();

return vehicle;
}
}

This decision structure is easily refactored to an in-memory type registry which uses the lookup metaphor as demonstrated below:

private IDictionary<VehicleType,IVehicle> Vehicles
{
get
{
IDictionary<VehicleType,IVehicle> vehicles = new Dictionary<VehicleType,IVehicle>();
vehicles.Add(Vehicle.Sedan, new Sedan());
vehicles.Add(Vehicle.Mazembe, new Mazembe());
vehicles.Add(Vehicle.Chisasa, new Chisasa());
vehicles.Add(Vehicle.Chimbayambaya, new Chimbayambaya());
return vehicles;
}
}

public static IVehicle Find(VehicleType vehicleType)
{
return Vehicles[vehicleType];
}



If you are observant, you will notice that this changes the semantics of the implementation. We have now moved from creating objects to finding objects in a registry. Sound familiar? This emergent design shows us that the Factory Method is really a respository pattern in disguise. Refactoring a GOF pattern has teleported us to one of the basic tenets of Domain Driven Design, the Repository Pattern.

Some considerations to take into account would be deciding the best collection to use
to reduce the cost of lookup. It could also be possible to externalise the registry depending on the nature of the problem space.