Search And Destroy

Look out honey, ’cause I’m using technology!

Archive for the ‘NHibernate’ Category

NHibernate Integration Testing Helpers

Posted by kilfour on September 8, 2011

What I want to test :

[Test]
public void MapperShouldNotCauseExtraQueries()
{
    using(0.Queries())
    {
        Mapper.Map(entityResultFromQuery);
    }
}

The plumbing :
public class QuerySpy : IDisposable
{
    private readonly int expectedNumber;
    private readonly NHibernateSqlLogSpy spy;

    public QuerySpy(int expectedNumber)
    {
        this.expectedNumber = expectedNumber;
        spy = new NHibernateSqlLogSpy();
    }

    public void Dispose()
    {
        Assert.AreEqual(expectedNumber, spy.Appender.GetEvents().Count());
    }
}

public static class NumberOfQueriesUsedExtension
{
    public static QuerySpy Queries(this int expectedNumber)
    {
        return new QuerySpy(expectedNumber);
    }
}

public class NHibernateSqlLogSpy : LogSpy
{
    public NHibernateSqlLogSpy() : base("NHibernate.SQL") { }
}

public class LogSpy : IDisposable
{
    static LogSpy()
    {
        XmlConfigurator.Configure();
    }

    private readonly MemoryAppender appender;
    private readonly Logger logger;
    private readonly Level prevLogLevel;

    public LogSpy(string loggerName)
    {
        logger = LogManager.GetLogger(loggerName) as Logger;
        if (logger == null)
            throw new NullReferenceException();
        prevLogLevel = logger.Level;
        logger.Level = Level.Debug;
        appender = new MemoryAppender();
        logger.AddAppender(appender);
    }

    public MemoryAppender Appender { get { return appender; } }

    public virtual void Dispose()
    {
        logger.Level = prevLogLevel;
        logger.RemoveAppender(appender);
    }
}

Posted in C# Musings, NHibernate | Leave a Comment »

Yet Another NHibernate Query Object Implementation

Posted by kilfour on March 17, 2011

The plumbing :

public interface IProjectionsDefinition { }

public interface IQuery<in TParameter>
{
    TResult UniqueResult<TResult>(TParameter parameter);
    IList<TResult> List<TResult>(TParameter parameter);
}

public abstract class Query<TProjections, TParameter> : IQuery<TParameter> 
    where TProjections : IProjectionsDefinition, new()
{
    private readonly TProjections projectionsDefinition = new TProjections();
    private readonly ISession session;

    protected Query(ISession session)
    {
        this.session = session;
    }

    public TResult UniqueResult<TResult>(TParameter parameter)
    {
        return GetQuery<TResult>(parameter).UniqueResult<TResult>();
    }

    public IList<TResult> List<TResult>(TParameter parameter)
    {
        return GetQuery<TResult>(parameter).List<TResult>();
    }

    protected abstract DetachedCriteria GetCriteria(TParameter parameter);

    private ProjectionList BuildProjectionList<TResult>()
    {
        var projectionList = Projections.ProjectionList();
        foreach (var propertyInfo in typeof(TResult).GetProperties())
        {
            var projectionPropertyInfo = typeof (TProjections).GetProperty(propertyInfo.Name);
            var projection = (IProjection) projectionPropertyInfo.GetValue(projectionsDefinition, null);
            projectionList.Add(projection, propertyInfo.Name);
        }
        return projectionList;
    }

    private ICriteria GetQuery<TResult>(TParameter parameter)
    {
        return
            GetCriteria(parameter)
                .GetExecutableCriteria(session)
                .SetProjection(BuildProjectionList<TResult>())
                .SetResultTransformer(new AliasToBeanResultTransformer(typeof(TResult)));
    }
}

Query example :
public interface ISearchAdresByStraatQuery : IQuery<string> { }

public class SearchAdresByStraatQuery : Query<SearchAdresByStraatQueryProjections, string>, ISearchAdresByStraatQuery
{
    public SearchAdresByStraatQuery(ISession session) 
        : base(session) { }

    protected override DetachedCriteria GetCriteria(string straat)
    {
        return 
            DetachedCriteria.For<Adres>("a")
                .CreateAlias("Straat", "s")
                .CreateAlias("Gemeente", "g")
                .CreateAlias("Postcode", "p")
                .Add(Restrictions.Like("s.Naam", straat));
    }
}

public class SearchAdresByStraatQueryProjections : IProjectionsDefinition
{
    public IProjection Id
    {
        get { return Projections.Cast(NHibernateUtil.String, Projections.Property("a.Id")); }
    }

    public IProjection HuisNummer
    {
        get { return Projections.Property("a.HuisNummer"); }
    }

    public IProjection BusNummer
    {
        get { return Projections.Property("a.BusNummer"); }
    }

    public IProjection Gemeente
    {
        get { return Projections.Property("g.Naam"); }
    }

    public IProjection Postcode
    {
        get { return Projections.Property("p.Waarde"); }
    }

    public IProjection StraatNaam
    {
        get { return Projections.Property("s.Naam"); }
    }

    public IProjection AantalRecords
    {
        get { return Projections.Count("Id"); }
    }
}

Usage :
This :
public class AdresResult
{
    public string Id { get; set; }
    public string Postcode { get; set; }
    public string Gemeente { get; set; }
    public string StraatNaam { get; set; }
    public string HuisNummer { get; set; }
    public string BusNummer { get; set; }
}
...
query.List<AdresResult>("filter");

Results in :
SELECT cast( this_.Id as NVARCHAR(255)) as y0_, this_.BusNummer as y1_, g2_.Naam as y2_, this_.HuisNummer as y3_, p3_.Postcode as y4_, s1_.Naam as y5_ FROM ...

And this :
public class CountDto
{
    public int AantalRecords { get; set; }
}
...
query.UniqueResult<CountDto>("filter");

Results in :
SELECT count(this_.Id) as y0_ FROM ...

Posted in C# Musings, NHibernate | Leave a Comment »

 
Follow

Get every new post delivered to your Inbox.