RJP Software Blog

.Net info and code snippets

Archive for February, 2012

NHibernate – Calling Stored Procs

without comments

Although not something you normally want to do with an ORM layer such as NH, it is possible to call a stored proc. To do this use the following code:

Session.GetNamedQuery("usp_MySproc")
   .SetParameter("Param1", myvariable1)
   .SetParameter("Param2", myVariable2)
   .SetResultTransformer(
      Transformers.AliasToBean(typeof(MyDowmainObject)))
        .List();

Written by Rich

February 27th, 2012 at 2:26 pm

Posted in NHibernate

SQL Script – Dropping Foreign Keys

without comments

I stumbled across the following script today which generates the SQL for dropping foreign keys:

SELECT 'ALTER TABLE ' + OBJECT_NAME(parent_object_id) +
   ' DROP CONSTRAINT ' + name FROM sys.foreign_keys
WHERE
   referenced_object_id in (object_id('TableName1'), object_id('TableName2'),
      object_id('TableName3'))

Written by Rich

February 15th, 2012 at 3:41 pm

Posted in SQL Server

Nhibernate – List, Set or Bag for collection mappings?

without comments

I found a useful snippet on StackOverflow that clears this up…

So, to quote:

NHibernate semantics:

  1. List: Ordered collection of entities, duplicate allowed. Use a .net IList in code. The index column will need to be mapped in NHibernate.
  2. Set: Unordered collection of unique entities, duplicates not allowed. Use Iesi.Collection.ISet in code. It is important to override GetHashCode and Equals to indicate the business definition of duplicate. Can be sorted by defining a orderby or by defining a comparer resulting in a SortedSet result.
  3. Bag: Unordered list of entities, duplicates allowed. Use a .net IList in code. The index column of the list is not mapped and not honored by NHibernate.

See the Stackoverflow here: set/bag and list/set in nhibernate

Written by Rich

February 15th, 2012 at 11:02 am

Posted in NHibernate

NHibernate 3.2 and SqlCE

without comments

I had some great fun configuring Nhibernate 3.2 with a Sql CE database today. As ever its easy when you know how! After an hour so so reading various blogs and dealing with some non illuminating NH error messages, I came up with a configuration that worked. So if you want to use NH with a Sql CE database (I am doing this for some integration tests) try the following:

  1. Add a reference to the System.Data.SqlServerCe assembly, then edit the properties and set Copy Local to true, see below:
  2. Add the SqlCE Dlls to your project ensuring that Copy to Output Directory is set to Copy if newer:
  3. Use the following NH configuration:
    configuration = new Configuration();
    configuration.DataBaseIntegration(c =>
    {
            c.Dialect<MsSqlCe40Dialect>();
            c.Driver<SqlServerCeDriver>();
            c.ConnectionString = "Data Source=App_Data/tests.sdf"; // connectionString;
    	c.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
    	c.Timeout = 10;
    	c.AutoCommentSql = false;
    	// Add this if you want your tests to create the schema.
    	c.SchemaAction = SchemaAutoAction.Update;
    });

Written by Rich

February 14th, 2012 at 1:02 pm

Posted in NHibernate

NHibernate 3.2 “Mapping By Code” Snippets

without comments

As I trawl through the vairous blogs piecing things together, I thought that I would put together a page with some code snippets for the new NH 3.2 mapping API.

Class Mappings

Mapping a basic entity

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

public class PersonMap : ClassMapping<Person>
{
	public PersonMap()
	{
                // Allow the DB to allocate the Id.
		Id(x => x.PersonId, m => m.Generator(Generators.Identity));
		Property(x => x.LastName);
		Property(x => x.FirstName, m => m.Length(200));
                // Specifiy a different column name for this propery.
		Property(x => x.Email, m => m.Column("EmailAddress"));
	}
}

Mapping int’s in the DB to Enum properties on the Domain Model

// The property to map
public class Person {
   public PersonType Type { get; set; }
}

public class PersonMapping : ClassMapping≶Person>
{
   // The mapping
   Property(x => x.PersonType ,
            m =>{
                m.Type<NHibernate.Type.EnumType<Type>>();
                m.Column("PersonTypeId"); });
}

Creating a Readonly Mapping

Add the following line in your mapping class. Alternatively you can configure this on individual properties.

public class Person
{
}

public class PersonMapping : ClassMapping
{
   // Add this to the mapping to make it readonly.
   Mutable(false);
}

A One To Many Mapping

You can create a one to many mapping as follows, remember to set Inverse(true), otherwise you may get more calls to the DB than you bargained for:

public class Invoice
{
   public IList<InvoiceItem> Items { get; set; }
}

public class InvoiceMap : ClassMapping<Invoice>
{
	public InvoiceMap()
	{
           Bag(x => x.Items ,
  	       c =>
	       {
                  // As mentioned this is important!!
		  c.Inverse(true);
                  // The column on the item table that refers back to the invoice.
		  c.Key(k => k.Column("InvoiceId"));
		  c.Cascade(Cascade.All);
	       },
	       ce => ce.OneToMany());
 	}
}

A Many To One Mapping

public class InvoiceItem
{
   public Invoice Invoice{ get; set; }
}

public class InvoiceItemMap : ClassMapping<InvoiceItem>
{
	public InvoiceItemMap ()
	{
            ManyToOne(d => d.Invoice);
 	}
}

Conventions

Conventions provide a useful mechanism for making assumptions when mapping the DB. Below are some sample conventions.

Id Convention

Apply’s a naming convention to Id columns. Id’s will take the form type name + “Id”, for example, the Person class will have the id PersonId.

mapper.BeforeMapClass += (mi, t, map) => map.Id(
	x => {
		x.Column(t.Name + "Id");
		x.Generator(Generators.Identity);
	});

A Many to One Convention

The following convention dictates that the foreign key property on a many to one relationship will take the form reference type property + “Id”. For example if the InvoiceItem table refers to the Invoice table, the key column name will be InvoiceId.

mapper.BeforeMapManyToOne += (modelInspector, propertyPath, map) =>
   map.Column(propertyPath.LocalMember.GetPropertyOrFieldType().Name + "Id");

Written by Rich

February 10th, 2012 at 4:45 pm

Posted in NHibernate

Reading and Listing Embedded Files

without comments

When writing unit tests I occasionally find the need to include embedded resources (mostly files – e.g. XML). This enables the tests to run anywhere without relying on a specific file structure. Each time I do this I seem to have to re-create the same test utility for managing these files so I thought I’d pop the code on my blog:

Here is some sample code:

public class EmbededResourceHelper
{
	public static string ReadEmbededResourceFile(string path)
	{
		var text = string.Empty;
		using (var stream = Assembly.GetExecutingAssembly()
                          .GetManifestResourceStream(path))
		using (var reader = new StreamReader(stream))
		{
			text = reader.ReadToEnd();
			reader.Close();
		}

		return text;
	}

	public static byte[] ReadEmbededResourceFileAsBytes(string path)
	{
		byte[] bytes;
		using (var stream = Assembly.GetExecutingAssembly()
                            .GetManifestResourceStream(path))
		{
			bytes = ReadFully(stream);
		}

		return bytes;
	}

	private static byte[] ReadFully(Stream input)
	{
		byte[] buffer = new byte[16 * 1024];
		using (var ms = new MemoryStream())
		{
			int read;
			while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
			{
				ms.Write(buffer, 0, read);
			}
			return ms.ToArray();
		}
	}

	public static void ListEmbededResources()
	{
		Assembly.GetExecutingAssembly()
                   .GetManifestResourceNames().ToList()
                      .ForEach(x => Debug.WriteLine(x));
	}
}

Written by Rich

February 8th, 2012 at 5:19 pm

Posted in Unit Testing

NHibernate – Set the Inverse on One To Many Relationships

without comments

Ayende has written an interesting blog on this here:

Ayendes NHProf blog

The salient point here is: Make sure that you specify inverse=’true’ on the <one-to-many> collection association otherwise NH will issue 2 SQL statements for a single Update/Insert.

Written by Rich

February 8th, 2012 at 4:50 pm

Posted in NHibernate

Windsor Inspector

without comments

Here is a useful utility class for inspecting the contents of the Windsor container:

public class WindsorContainerInspector
{
    private readonly IWindsorContainer _container;
    public WindsorContainerInspector(IWindsorContainer container)
    {
        _container = container;
    }

    public IList> ListDependencies()
    {
        var dependencies = new List>();

        foreach (var node in _container.Kernel.GraphNodes)
        {
            ComponentModel dependingNode = (ComponentModel) node;

            foreach (GraphNode depender in node.Dependents)
            {
                var dependerNode = (ComponentModel)depender;

                dependencies.Add(new KeyValuePair(
                        dependingNode,
                        dependerNode));
            }
        }

        return dependencies;
    }
}

Written by Rich

February 8th, 2012 at 3:50 pm

Posted in Windsor

NHibernate – Serializing Queries

without comments

It is not something that I would recommend doing in standard NH implementations, but occasionally it may be useful to serialize your NH queries. Fortunately the NH ICriteria is serializable and can be used to achieve just this.

The following code snippet demonstrates how to serialize / de serialize an NH query:

var query = QueryOver.Of().WhereRestrictionOn(e => e.LastName).IsLike("Smith");

var detatchedCriteria = query.DetachedCriteria;
var serializedCriteria = ObjectToByteArray(detatchedCriteria);
var desrializedCriteria = ByteArrayToObject(serializedCriteria) as DetachedCriteria;

// where session is and NH ISession
var people = desrializedCriteria.GetExecutableCriteria(session).List();

Just for reference the serialization code used here is as follows:

private byte[] ObjectToByteArray(object obj)
{
	if (obj == null)
		return null;
	var bf = new BinaryFormatter();
	var ms = new MemoryStream();
	bf.Serialize(ms, obj);
	return ms.ToArray();
}
// Convert a byte array to an Object
private object ByteArrayToObject(byte[] arrBytes)
{
	var memStream = new MemoryStream();
	var binForm = new BinaryFormatter();
	memStream.Write(arrBytes, 0, arrBytes.Length);
	memStream.Seek(0, SeekOrigin.Begin);
	var obj = binForm.Deserialize(memStream);
	return obj;
}

This technique allows you to send queries over the wire or persist for later use.

Written by Rich

February 8th, 2012 at 12:16 pm

Posted in NHibernate

NHibernate 3.2

without comments

Having worked with Nhibernate 3.1 and early versions I spent today implementing a NHibernate 3.2 solution for my current client. I have always been a big fan of Fluent Nhibernate in the past as I am not keen on lots of XML config and like as much compile time checking as possible.

Several things have changed in NH 3.2, especially around the Domain mapping and configuration. NH now has its own in code mapping “Mapping By Code” which provides an alternative to Fluent. Another great thing is that NH itself no longer has dependencies on the Core Castle dlls (Fluent does) so if you don’t use Fluent you have less chance of dlls version issues if you happen to be using these assemblies elsewhere.

As ever with NH its no pain no gain when it comes to finding the documentation that you need. After some hunting around I found some really useful code samples here:

NH 3.2 Samples

I also found the following blogs handy:

A good summary of mapping by code
NHibernate Docunentation
A Stack Overflow Article with some links
HunabKu
Felice Pollano
Mohamed Abed
Some Useful Examples
Some Useful Comparisons between Fluent NH Mappings and Mapping by Code
Stack Overflow – Some useful examples of conventions and custom Type
Another Stack Overflow entry with some mapping examples and Q and A’s
A sample solution with mapping by code
Applying conventions to Bags – e.g. BatchSize

Written by Rich

February 7th, 2012 at 5:17 pm

Posted in NHibernate