





















































Download the latest release of the Common Service Locator from http://commonservicelocator.codeplex.com, and extract Microsoft.Practices.ServiceLocation.dll to your solution's libs folder.
Complete the previous recipe, Setting up an NHibernate repository.
Following the Fast testing with SQLite in-memory database recipe in the previous article, create a new NHibernate test project named Eg.Core.Data.Impl.Test.
Include the Eg.Core.Data.Impl assembly as an additional mapping assembly in your test project's App.Config with the following xml:
<mapping assembly="Eg.Core.Data.Impl"/>
public interface IQuery
{
}
public interface IQuery<TResult> : IQuery
{
TResult Execute();
}
{
TQuery CreateQuery<TQuery>() where TQuery :IQuery;
}
public interface IRepository<T>
: IEnumerable<T>, IQueryFactory
where T : Entity
{
void Add(T item);
bool Contains(T item);
int Count { get; }
bool Remove(T item);
}
private readonly IQueryFactory _queryFactory;
public NHibernateRepository(ISessionFactory sessionFactory,
IQueryFactory queryFactory)
: base(sessionFactory)
{
_queryFactory = queryFactory;
}
public TQuery CreateQuery<TQuery>() where TQuery : IQuery
{
return _queryFactory.CreateQuery<TQuery>();
}
public class QueryFactory : IQueryFactory
{
private readonly IServiceLocator _serviceLocator;
public QueryFactory(IServiceLocator serviceLocator)
{
_serviceLocator = serviceLocator;
}
public TQuery CreateQuery<TQuery>() where TQuery : IQuery
{
return _serviceLocator.GetInstance<TQuery>();
}
}
public abstract class NHibernateQueryBase<TResult>
: NHibernateBase, IQuery<TResult>
{
protected NHibernateQueryBase(
ISessionFactory sessionFactory)
: base(sessionFactory) { }
public abstract TResult Execute();
}
public interface INamedQuery
{
string QueryName { get; }
}
public abstract class NamedQueryBase<TResult>
: NHibernateQueryBase<TResult>, INamedQuery
{
protected NamedQueryBase(ISessionFactory sessionFactory)
: base(sessionFactory) { }
public override TResult Execute()
{
var nhQuery = GetNamedQuery();
return Transact(() => Execute(nhQuery));
}
protected abstract TResult Execute(IQuery query);
protected virtual IQuery GetNamedQuery()
{
var nhQuery = session.GetNamedQuery(
((INamedQuery) this).QueryName);
SetParameters(nhQuery);
return nhQuery;
}
protected abstract void SetParameters(IQuery nhQuery);
public virtual string QueryName
{
get { return GetType().Name; }
}
}
[Test]
public void NamedQueryCheck()
{
var errors = new StringBuilder();
var queryObjectTypes = GetNamedQueryObjectTypes();
var mappedQueries = GetNamedQueryNames();
foreach (var queryType in queryObjectTypes)
{
var query = GetQuery(queryType);
if (!mappedQueries.Contains(query.QueryName))
{
errors.AppendFormat(
"Query object {0} references non-existent " +
"named query {1}.",
queryType, query.QueryName);
errors.AppendLine();
}
}
if (errors.Length != 0)
Assert.Fail(errors.ToString());
}
private IEnumerable<Type> GetNamedQueryObjectTypes()
{
var namedQueryType = typeof(INamedQuery);
var queryImplAssembly = typeof(BookWithISBN).Assembly;
var types = from t in queryImplAssembly.GetTypes()
where namedQueryType.IsAssignableFrom(t)
&& t.IsClass
&& !t.IsAbstract
select t;
return types;
}
private IEnumerable<string> GetNamedQueryNames()
{
var nhCfg = NHConfigurator.Configuration;
var mappedQueries = nhCfg.NamedQueries.Keys
.Union(nhCfg.NamedSQLQueries.Keys);
return mappedQueries;
}
private INamedQuery GetQuery(Type queryType)
{
return (INamedQuery) Activator
.CreateInstance(queryType,
new object[] { SessionFactory });
}
public interface IBookWithISBN : IQuery<Book>
{
string ISBN { get; set; }
}
public class BookWithISBN :
NamedQueryBase<Book>, IBookWithISBN
{
public BookWithISBN(ISessionFactory sessionFactory)
: base(sessionFactory) { }
public string ISBN { get; set; }
protected override void SetParameters(
NHibernate.IQuery nhQuery)
{
nhQuery.SetParameter("isbn", ISBN);
}
protected override Book Execute(NHibernate.IQuery query)
{
return query.UniqueResult<Book>();
}
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping >
<query name="BookWithISBN">
<![CDATA[
from Book b where b.ISBN = :isbn
]]>
</query>
</hibernate-mapping>