Archive for February, 2012
NHibernate – Calling Stored Procs
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();
SQL Script – Dropping Foreign Keys
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'))
Nhibernate – List, Set or Bag for collection mappings?
I found a useful snippet on StackOverflow that clears this up…
So, to quote:
NHibernate semantics:
- List: Ordered collection of entities, duplicate allowed. Use a .net IList in code. The index column will need to be mapped in NHibernate.
- 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.
- 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
NHibernate 3.2 and SqlCE
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:
- Add a reference to the System.Data.SqlServerCe assembly, then edit the properties and set Copy Local to true, see below:

- Add the SqlCE Dlls to your project ensuring that Copy to Output Directory is set to Copy if newer:

- 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; });
NHibernate 3.2 “Mapping By Code” Snippets
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");
Reading and Listing Embedded Files
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));
}
}
NHibernate – Set the Inverse on One To Many Relationships
Ayende has written an interesting blog on this here:
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.
Windsor Inspector
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;
}
}
NHibernate – Serializing Queries
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.
NHibernate 3.2
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:
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