Thursday 22 September 2011

Mapping by Code - Part 1

Over the next few weeks I am going to put together a sample application showing how you would build a project using Mapping by code. Why do this? Well firstly there are not too many examples on the web yet about NHibernate 3.2 and mapping by code and secondly I am running out of Blog ideas :)

The domain I shall use will based on events, that is events that people pay to book on to. I have vastly simplified the domain so that it looks like this:-


Event

This is where events are held, a typical event would be "Developers Forum" or "How to get ahead in business" etc. The event has a name and a time it starts and finishes.

Event Package

This table holds the different packages that a visitor can book. For example a package could be:-
"Gold" - you get a better seat and a cup of tea
"Silver" - you get a seat but no tea
"Bronze" - you are forced to stand

Event Visitor

As you can see this table holds the people who are attending. A visitor can book more than one ticket so I have decided to use a hierarchical structure, that is the person who books has a ParentId of NULL and the additional people he/she books on will get a Id in ParentId.

Event Payment

This table just keeps track of who has paid. Notice that I have denormalised this table a bit and have created a column called NoTickets sold.

Please note that this domain is for demonstration purposes as I just wanted to show how hierarchical structures can be used in NHibernate.

Next post will be how we create a C# project to map this domain

Thursday 15 September 2011

Queryover, eager loading parent and children with a filter

Sometimes we want to use eager loading as:-

1. The dataset returned is small
2. We don't care about the cartesain product.
3. We want to load the parents
4. We want to load the children
5. We want to filter the results based on a where clause on the children

So how do we go about this, the domain model for this example looks like this:-
public class Movie : Entity
{
  public virtual string Director { get; set; }
  public virtual IList<Actor> ActorList { get; set; }
}

public class Actor : Entity
{
  public virtual string Name { get; set; }
  public virtual string Role { get; set; }
}
When using NHibernate and QueryOver we would specify eager loading by using:-
Actor actor = null;

return Session.QueryOver<Movie>()
  .Fetch(f => f.ActorList).Eager
  .Left.JoinAlias(f => f.ActorList, () => actor)
  .Where(() => actor.Name.Like("m%"))
  .List();
Lets look at the SQL output that gets generated:-

Excellent this is exactly what I require, one sql statement is sent to the database and both parents and children are hydrated at the same time.

However, there is one caveat here, look closely at my c# code and you will see that I am specifying a left join.
Now for me this is where the some confusion crops up. If I take out the .left out of my code so that it is:-
return Session.QueryOver<Movie>()
  .Fetch(f => f.ActorList).Eager
  .JoinAlias(f => f.ActorList, () => actor)
  .Where(() => actor.Name.Like("m%"))
  .List();
and rerun my example the sql that gets generated is:-
As you can see we have resorted back to lazy loading, this is quite strange and I am not 100% sure if this is a bug or the intended behaviour.

So it looks like if you want to take advantage of eager loading and queryover then you always need to specify a .left join in your code!

Monday 12 September 2011

NHibernate QueryOver and NewId or Rand

Returning a random record using NHibernate is quite simple to achieve. If you do not have the whole collection in memory then you ought to consider using NEWID() (for MSSQL) or RAND() (for MySql)

The following MSSQL query will return 5 random Testimonials:-
select TOP 5 * from Testimonials order by newid()
So how would you do this using NHibernate? The following ICriteria example shows how you would register the MySql function RAND(). If you are using MSSQL then you just need to replace the word RAND with NewId.
public class RandomOrder : Order {
  public RandomOrder() : base("", true) { }
  public override SqlString ToSqlString(
      ICriteria criteria, ICriteriaQuery criteriaQuery) {
    return new SqlString("RAND()");
  }
}
The following code based on ICritrtia returns a random list of Testimonials:-
public IList<CmsTestimonial> GetRandomTestimonials(int count) {
  ICriteria criteria = Session
    .CreateCriteria(typeof(CmsTestimonial))
    .AddOrder(new RandomOrder())
    .SetMaxResults(count);
    return criteria.List<CmsTestimonial>();
}
The following code returns a single random Testimonial:-
public CmsTestimonial GetRandomTestimonial() {
  ICriteria criteria = Session
    .CreateCriteria(typeof(CmsTestimonial))
    .AddOrder(new RandomOrder())
    .SetMaxResults(1);
    return criteria.UniqueResult<CmsTestimonial>();
}

Can I do this using QueryOver?

Ok all good so far but what about if we want to use QueryOver rather than ICriteria?

Make sure you keep the RandomOrder class and then create this extension method:-
public static class NHibernateExtensions {
  public static IQueryOver<TRoot, TSubType> 
      OrderByRandom<TRoot, TSubType>(
        this IQueryOver<TRoot, TSubType> query) {
    query.UnderlyingCriteria.AddOrder(new RandomOrder());
    return query;
  }
}
and change your ICriteria query to the following QueryOver query
public IList<CmsTestimonial> GetRandomTestimonials(int count) {
  return Session
    .QueryOver<CmsTestimonial>()
    .OrderByRandom()
    .Take(count)
    .List();
}
NHibernate has so many extensible points and really mostly makes life easy us developers! This is a real sweet spot.

Wednesday 7 September 2011

RequireHttps attribute in MVC3

I came across this gem of an attribute when looking to secure one of my controllers in a asp.net MVC 3 project.
[RequireHttps(Order = 1)]
public class PayController : Controller {
   ...
}
This will automatically redirect and any url:-

from: http://www.mydomain.com/pay/membership

to: https://www.mydomain.com/pay/membership

However this comes with one small glitch, after the user has finished with the pay controller and then navigates to say the home controller then the browser still shows https:// in the address bar. So is there a elegant solution to make all your other controllers http only?

One way is to create a base controller that overrides the OnAuthorization method
public class BaseController : Controller {
  protected override void OnAuthorization(
        AuthorizationContext filterContext) {

    //Only check if we are already on a secure connectuion and 
    // we don't have a [RequireHttpsAttribute] defined
    if (Request.IsSecureConnection) {
      var requireHttps = filterContext.ActionDescriptor
                  .GetCustomAttributes(
                     typeof(RequireHttpsAttribute), false)
                  .Count() >= 1;

      //If we don't need SSL and we are not on a child action
      if (!requireHttps && !filterContext.IsChildAction) {
        var uriBuilder = new UriBuilder(Request.Url) {
                                 Scheme = "http", 
                                 Port = 80
                                };
        filterContext.Result = 
             this.Redirect(uriBuilder.Uri.AbsoluteUri);
      }
    }
    base.OnAuthorization(filterContext);
  }
}
And then make all our non secure controllers inherit from this base controller:
public class CmsHomeController : BaseController {
  ...
}
Lovely!

Tuesday 6 September 2011

Update NHibernate 3.2 and Medium Trust Environments

NOTE: This is an update from a previous post - Nhibernate 3.2 and Medium Trust

Another NOTE: NHibernate 3.3 does not have this problem. See this post for more info.
A few weeks ago I asked the community if somebody could help me figure out how to get NHibernate working in a Medium Trust environment. Well a person by the name of Randy Lee @ranzlee came to the rescue. Basically Randy downloaded the NHibernate source and got to work. He used PEVerify a tool on MSDN that:-
The PEVerify tool helps developers who generate Microsoft intermediate language (MSIL) (such as compiler writers, script engine developers, and so on) to determine whether their MSIL code and associated metadata meet type safety requirements. Some compilers generate verifiably type-safe code only if you avoid using certain language constructs. If, as a developer, you are using such a compiler, you may want to verify that you have not compromised the type safety of your code. In this situation, you can run the PEVerify tool on your files to check the MSIL and metadata.
Thankfully the results of PEVerify showed one error:
[IL]: Error: [c:\Users\Randy\generatedassembly.dll : CatProxy::.ctor][mdToken=0x6000001][offset 0x00000001][found ref ('this' ptr) 'CatProxy'] Call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj.
Randy figured out that he needed to fixed the proxy factory to emit call the "real" base type constructor, but this would have the side-effect of preventing constructor DI in entities. He then added a new provider and contract (DefaultEntityInjector and IEntityInjector) so that DI is supported out-of-box by providing an implementation. The implementation simply needs to provide the constructor arguments for NH's call to Activator.CreateInstance.

You can download Randy's version of NHibernate.DependencyInjection from Nuget.

Basically all you need to get up and running is to initialise the ByteCode Provider and you are up and running...
protected void Application_Start() {
  Initializer.RegisterBytecodeProvider();
  ...
  Rest of configuration code here
}
Also please note that if you think that NHibernate 3.2 should support Medium Trust environments out of the box then please visit the NHibernate Jira and vote the issue up, the more votes the more chance we have of getting this bug fixed.

Thanks

Monday 5 September 2011

Upcoming NHibernate presentations

Following on from my successful presentations at Birmingham, Manchester and Southampton I can now confirm that I am now presenting in two other regions.

Firstly I will be visiting NxtGenUg at Oxford on September 20th.

Secondly I will be visiting GL.NET at Gloucester on the 5th October.

The presentation covers:-

PART 1: Models and mappings - Shows how to model components, inheritance and collections using hbm XMLmappings

PART 2: Mapping by code - Shows how to model the same model in part 1 using the new sexy mapping by code syntax new to NHibernate 3.2. A simple console application showed how to retrieve some data.

PART 3: Sessions and transactions - Shows how NHibernate can be configured into a MVC 3 application, how a unit of work can implemented and how we can use NHProf.

PART 4: Queries - Shows how we break up a MVC 3 application into layers comprising of a Domain.Model, a service layer, a repository layer and the MVC 3 layer. The application uses Unity to achieve a loosely coupled design. NHProf is used extensively to show how we can optimise the queries. This part also covers eager loading versus lazy loading and how you should be aware of unwanted side effects.

So if anyone is interested in seeing what NHibernate 3.2 is all about including the sexy mapping by code then please book a place, see you there.