Thursday, 23 September 2010

Extension method for adding export hbm from fluent nhibernate when in a debug environment

Came up with a useful little extension method today. I wanted the fluent nhibernate configuration to export the hbm files when the site is being run in debug mode.

   1: /// <summary>
   2: /// Export hbm to path if debug environment
   3: /// </summary>
   4: /// <param name="fluentMappingsContainer">Container</param>
   5: /// <param name="path">Path</param>
   6: /// <returns>container</returns>
   7: public static FluentMappingsContainer ExportPathIfDebug(this FluentMappingsContainer fluentMappingsContainer, string path)
   8: {
   9:     #if DEBUG            
  10:     if (ConfigurationManager.AppSettings[path] != null)
  11:     {
  12:         if (!Directory.Exists(ConfigurationManager.AppSettings[path])) Directory.CreateDirectory(ConfigurationManager.AppSettings[path]);
  13:         fluentMappingsContainer.ExportTo(ConfigurationManager.AppSettings[path]);
  14:     }
  15:     #endif
  16:     return fluentMappingsContainer;
  17: }

Where the path refers to an application setting in the app.config.

Monday, 24 May 2010

Redirecting Assembly Bindings

Remembered a useful way to redirect assembly bindings to newer versions:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <runtime>
   4:      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
   5:       <dependentAssembly>
   6:         <assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" culture="neutral" />
   7:         <bindingRedirect oldVersion="1.1.0.0" newVersion="1.2.0.0" />
   8:       </dependentAssembly>
   9:     </assemblyBinding>
  10:   </runtime>
  11: </configuration>

Here I redirect an old version of Castle.Core to a newer one. Hopefully I’ll remember this next time :)

Tuesday, 4 May 2010

Creating a base repository class for Fluent NHibernate

For several of my projects I use a repository pattern for the data access layer which sits above Fluent NHibernate. Using generics I can then replicate the same features for all entity repositories.

An example of the base interface is shown below.

   1: /// <summary>
   2: /// Base repository for nhibernate 
   3: /// </summary>
   4: /// <typeparam name="T">Entity</typeparam>
   5: public interface INHibernateBaseRepository<T>
   6: {
   7:     /// <summary>
   8:     /// Gets the current session in the repository
   9:     /// </summary>
  10:     /// <returns>Current session</returns>
  11:     ISession GetCurrentSession();
  12:  
  13:     /// <summary>
  14:     /// Finds an entity by passed identifier
  15:     /// </summary>
  16:     /// <param name="id">Identifier</param>
  17:     /// <returns>Entity matching identifier</returns>
  18:     T FindById(long id);
  19:  
  20:     /// <summary>
  21:     /// Saves entity
  22:     /// </summary>
  23:     /// <param name="t">Entity to save</param>
  24:     void Save(T t);
  25:  
  26:     /// <summary>
  27:     /// Saves or updates entity
  28:     /// </summary>
  29:     /// <param name="t">Entity to save or update</param>
  30:     T SaveOrUpdate(T t);
  31:  
  32:     /// <summary>
  33:     /// Deletes entity
  34:     /// </summary>
  35:     /// <param name="t">Entity to delete</param>
  36:     void Delete(T t);
  37:  
  38:     /// <summary>
  39:     /// Finds all entities and passes back as a collection
  40:     /// </summary>
  41:     /// <returns>Collection of entities</returns>
  42:     IList<T> FindAll();
  43:  
  44:     /// <summary>
  45:     /// Finds all entities by passed order and passes back as a collection
  46:     /// </summary>
  47:     /// <param name="orders">Orders</param>
  48:     /// <returns>Collection of entities</returns>
  49:     IList<T> FindAll(params Order[] orders);
  50:  
  51:     /// <summary>
  52:     /// Finds all entities and passes back as a collection within the range specified
  53:     /// </summary>
  54:     /// <param name="firstResult">First result</param>
  55:     /// <param name="numberOfResults">Number of results to return</param>
  56:     /// <returns>Collection of entities</returns>
  57:     IList<T> FindAll(int firstResult, int numberOfResults);
  58:  
  59:     /// <summary>
  60:     /// Finds all entities and passes back as a collection within the range specified
  61:     /// </summary>
  62:     /// <param name="firstResult">First result</param>
  63:     /// <param name="numberOfResults">Number of results to return</param>
  64:     /// <param name="orders">Orders</param>
  65:     /// <returns>Collection of entities</returns>
  66:     IList<T> FindAll(int firstResult, int numberOfResults, params Order[] orders);
  67:  
  68:     /// <summary>
  69:     /// Finds all entities and passes back as a collection within the range specified
  70:     /// </summary>
  71:     /// <param name="firstResult">First result</param>
  72:     /// <param name="numberOfResults">Number of results</param>
  73:     /// <param name="sortFields">Sort order dictionary</param>
  74:     /// <returns>List of entities</returns>
  75:     IList<T> FindAll(int firstResult, int numberOfResults, IDictionary<string, bool> sortFields);
  76:  
  77:     /// <summary>
  78:     /// Finds entities by criteria
  79:     /// </summary>
  80:     /// <param name="dc">Detatched criteria</param>
  81:     /// <returns>Collection of entities that match the passed criteria</returns>
  82:     IList<T> FindByCriteria(DetachedCriteria dc);
  83:  
  84:     /// <summary>
  85:     /// Finds entities by criteria and paging
  86:     /// </summary>
  87:     /// <param name="dc">Detatched criteria</param>
  88:     /// <param name="firstResult">First result</param>
  89:     /// <param name="numberOfResults">Number of results to return</param>
  90:     /// <returns>Collection of entities that match the passed criteria</returns>
  91:     IList<T> FindByCriteria(DetachedCriteria dc, int firstResult, int numberOfResults);
  92:  
  93:     /// <summary>
  94:     /// Finds entities by criteria, paging and ordering
  95:     /// </summary>
  96:     /// <param name="dc">Detatched criteria</param>
  97:     /// <param name="firstResult">First result</param>
  98:     /// <param name="numberOfResults">Number of results to return</param>
  99:     /// <param name="orders">Orders</param>
 100:     /// <returns>Collection of entities that match the passed criteria</returns>
 101:     IList<T> FindByCriteria(DetachedCriteria dc, int firstResult, int numberOfResults, params Order[] orders);
 102:        
 103:     /// <summary>
 104:     /// Gets a list of entities by passed query
 105:     /// </summary>
 106:     /// <param name="queryString">Query to get entities</param>
 107:     /// <returns>Collection of entities</returns>
 108:     IList<T> FindByQuery(string queryString);
 109:  
 110:     /// <summary>
 111:     /// Gets a list of entities by passed query and parameters
 112:     /// </summary>
 113:     /// <param name="queryString">Query to get entities</param>
 114:     /// <param name="parameters">Parameters to set in query</param>
 115:     /// <returns>Collection of entities</returns>
 116:     IList<T> FindByQuery(string queryString, params object[] parameters);
 117:   
 118:     /// <summary>
 119:     /// Gets a list of entities by passed query
 120:     /// </summary>
 121:     /// <param name="queryString">Query to get entities</param>
 122:     /// <param name="firstResult">First result</param>
 123:     /// <param name="numberOfResults">Number of results to return</param>
 124:     /// <returns>Collection of entities</returns>
 125:     IList<T> FindByQuery(string queryString, int firstResult, int numberOfResults);
 126:    
 127:     /// <summary>
 128:     /// Gets a list of entities by passed query and parameters
 129:     /// </summary>
 130:     /// <param name="queryString">Query to get entities</param>
 131:     /// <param name="firstResult">First result</param>
 132:     /// <param name="numberOfResults">Number of results to return</param>
 133:     /// <param name="parameters">Parameters to set in query</param>
 134:     /// <returns>Collection of entities</returns>
 135:     IList<T> FindByQuery(string queryString, int firstResult, int numberOfResults, params object[] parameters);        
 136:  
 137:     /// <summary>
 138:     /// Finds one entity that matches criteria and throws exception otherwise
 139:     /// </summary>
 140:     /// <param name="criteria">Criteria</param>
 141:     /// <returns>Entity matching criteria</returns>
 142:     T FindOne(DetachedCriteria criteria);
 143:  
 144:     /// <summary>
 145:     /// Finds first entity in collection that matches criteria
 146:     /// </summary>
 147:     /// <param name="criteria">Criteria</param>
 148:     /// <returns>First entity</returns>
 149:     T FindFirst(DetachedCriteria criteria);
 150:  
 151:     /// <summary>
 152:     /// Finds first entity in collection that matches criteria and order params
 153:     /// </summary>
 154:     /// <param name="criteria">Criteria</param>
 155:     /// <param name="orders">Orders</param>
 156:     /// <returns>First entity</returns>
 157:     T FindFirst(DetachedCriteria criteria, params Order[] orders);
 158:  
 159:     /// <summary>
 160:     /// Get count of entities that match criteria
 161:     /// </summary>
 162:     /// <param name="criteria">Criteria</param>
 163:     /// <returns>Count of number of entities that match criteria</returns>
 164:     long Count(DetachedCriteria criteria);
 165:  
 166:     /// <summary>
 167:     /// Get count of entities
 168:     /// </summary>
 169:     /// <returns>Count of entities</returns>
 170:     long Count();
 171:  
 172:     /// <summary>
 173:     /// Determines if at least one entity exists that matches passed criteria
 174:     /// </summary>
 175:     /// <param name="criteria">Criteria</param>
 176:     /// <returns><c>true</c> if exists</returns>
 177:     bool Exists(DetachedCriteria criteria);
 178: }

Then a base class to implement this interface - as follows:

   1: #region Usings
   2:  
   3: using System;
   4: using System.Collections.Generic;
   5: using Castle.Facilities.NHibernateIntegration;
   6: using AimKai.Core.Interfaces;
   7: using AimKai.Core.Resources;
   8: using AimKai.Core.Util;
   9: using log4net;
  10: using NHibernate;
  11: using NHibernate.Criterion;
  12: using System.Linq;
  13:  
  14: #endregion Usings
  15:  
  16: /// <summary>
  17: /// Base nhibernate repository
  18: /// </summary>
  19: /// <typeparam name="T">Type</typeparam>
  20: public abstract class NHibernateBaseRepository<T> : INHibernateBaseRepository<T>
  21: {
  22:     #region Fields
  23:  
  24:     /// <summary>
  25:     /// Session manager
  26:     /// </summary>
  27:     protected readonly ISessionManager SessionManager;
  28:  
  29:     #endregion Fields
  30:  
  31:     #region Properties
  32:     
  33:     /// <summary>
  34:     /// Gets the current session
  35:     /// </summary>
  36:     public virtual ISession Session
  37:     {
  38:         get { return SessionManager.OpenSession(); }
  39:     }
  40:  
  41:     /// <summary>
  42:     /// Gets the base log here
  43:     /// </summary>
  44:     public ILog NHibernateBaseRepositoryLog = LogManager.GetLogger(typeof (NHibernateBaseRepository<T>));
  45:  
  46:     #endregion Properties
  47:  
  48:     #region Constructors
  49:  
  50:     /// <summary>
  51:     /// Set session manager via constructor
  52:     /// </summary>
  53:     /// <param name="sessionManager"></param>
  54:     protected NHibernateBaseRepository(ISessionManager sessionManager)
  55:     {
  56:         SessionManager = sessionManager;
  57:     }       
  58:  
  59:     #endregion Constructors
  60:  
  61:     #region Public Methods
  62:  
  63:     #region INHibernateBaseRespository<T> Members
  64:  
  65:     /// <summary>
  66:     /// Gets the current session in the repository
  67:     /// </summary>
  68:     /// <returns>Current session</returns>
  69:     public ISession GetCurrentSession()
  70:     {
  71:         return Session;
  72:     }
  73:  
  74:     /// <summary>
  75:     /// Finds an entity by passed identifier
  76:     /// </summary>
  77:     /// <param name="id">Identifier</param>
  78:     /// <returns>Entity matching identifier</returns>
  79:     public T FindById(long id)
  80:     {
  81:         return Session.Get<T>(id);
  82:     }
  83:  
  84:     /// <summary>
  85:     /// Loads an entity by passed identifier
  86:     /// </summary>
  87:     /// <param name="id">Identifier</param>
  88:     /// <returns>Entity matching identifier</returns>
  89:     public T Load(long id)
  90:     {
  91:         return Session.Load<T>(id);
  92:     }
  93:  
  94:     /// <summary>
  95:     /// Saves entity
  96:     /// </summary>
  97:     /// <param name="t">Entity to save</param>
  98:     public void Save(T t)
  99:     {
 100:         //Use transaction here
 101:         using (var tx = Session.BeginTransaction())
 102:         {
 103:             try
 104:             {
 105:                 //Check to see if we can validate
 106:                 var validateMethod = t.GetType().GetMethod("Validate");
 107:                 if (validateMethod != null)
 108:                     validateMethod.Invoke(t, null);
 109:  
 110:                 //Save here
 111:                 Session.Save(t);
 112:                 tx.Commit();
 113:             }
 114:             catch (Exception ex)
 115:             {
 116:                 tx.Rollback();
 117:  
 118:                 // throw not saved exception
 119:                 NHibernateBaseRepositoryLog.Error(ex);
 120:                 throw new CoreException("NHibernateBaseRepository_NotSaved", ExceptionMessages.NHibernateBaseRepository_NotSaved, ex,
 121:                     new object[] {"Save", ex.Message});
 122:             }
 123:         }
 124:     }
 125:  
 126:     /// <summary>
 127:     /// Saves or updates entity
 128:     /// </summary>
 129:     /// <param name="t">Entity to save or update</param>
 130:     public T SaveOrUpdate(T t)
 131:     {
 132:         //Use transaction here
 133:         using (var tx = Session.BeginTransaction())
 134:         {
 135:             try
 136:             {
 137:                 Session.SaveOrUpdate(t);
 138:                 tx.Commit();
 139:             }
 140:             catch (Exception ex)
 141:             {
 142:                 tx.Rollback();
 143:  
 144:                 // throw not saved exception
 145:                 NHibernateBaseRepositoryLog.Error(ex);
 146:                 throw new CoreException("NHibernateBaseRepository_NotSaved",
 147:                                         ExceptionMessages.NHibernateBaseRepository_NotSaved, ex,
 148:                                         new object[] {"Save or Update", ex.Message});
 149:             }
 150:         }
 151:         return t;
 152:     }
 153:  
 154:     /// <summary>
 155:     /// Deletes entity
 156:     /// </summary>
 157:     /// <param name="t">Entity to delete</param>
 158:     public void Delete(T t)
 159:     {
 160:         using (var tx = Session.BeginTransaction())
 161:         {
 162:             try
 163:             {
 164:                 Session.Delete(t);
 165:                 tx.Commit();
 166:             }
 167:             catch (Exception ex)
 168:             {
 169:                 tx.Rollback();
 170:  
 171:                 // throw not saved exception
 172:                 NHibernateBaseRepositoryLog.Error(ex);
 173:                 throw new CoreException("NHibernateBaseRepository_NotSaved",
 174:                                         ExceptionMessages.NHibernateBaseRepository_NotSaved, ex,
 175:                                         new object[] { "Delete", ex.Message });
 176:             }
 177:         }
 178:     }
 179:  
 180:     /// <summary>
 181:     /// Finds all entities and passes back as a collection
 182:     /// </summary>
 183:     /// <returns>Collection of entities</returns>
 184:     public IList<T> FindAll()
 185:     {
 186:         //Builds a criteria to pull back a collection of all items that match this type
 187:         return Session.CreateCriteria(typeof(T)).List<T>();
 188:     }
 189:  
 190:     /// <summary>
 191:     /// Finds all entities by passed order and passes back as a collection
 192:     /// </summary>
 193:     /// <param name="orders">Orders</param>
 194:     /// <returns>Collection of entities</returns>
 195:     public IList<T> FindAll(params Order[] orders)
 196:     {
 197:         return AddOrders(Session.CreateCriteria(typeof(T))).List<T>();
 198:     }
 199:  
 200:     /// <summary>
 201:     /// Finds all entities and passes back as a collection within the range specified
 202:     /// </summary>
 203:     /// <param name="firstResult">First result</param>
 204:     /// <param name="numberOfResults">Number of results to return</param>
 205:     /// <returns>Collection of entities</returns>
 206:     public IList<T> FindAll(int firstResult, int numberOfResults)
 207:     {
 208:         return Session.CreateCriteria(typeof(T))
 209:             .SetFirstResult(firstResult)
 210:             .SetMaxResults(numberOfResults)
 211:             .List<T>();
 212:     }
 213:  
 214:     /// <summary>
 215:     /// Finds all entities and passes back as a collection within the range specified
 216:     /// </summary>
 217:     /// <param name="firstResult">First result</param>
 218:     /// <param name="numberOfResults">Number of results to return</param>
 219:     /// <param name="orders">Orders</param>
 220:     /// <returns>Collection of entities</returns>
 221:     public IList<T> FindAll(int firstResult, int numberOfResults, params Order[] orders)
 222:     {
 223:         return AddOrders(Session.CreateCriteria(typeof(T)))
 224:             .SetMaxResults(numberOfResults)
 225:             .SetFirstResult(firstResult)
 226:             .List<T>();
 227:     }
 228:  
 229:     /// <summary>
 230:     /// Finds all entities and passes back as a collection within the range specified
 231:     /// </summary>
 232:     /// <param name="firstResult">First result</param>
 233:     /// <param name="numberOfResults">Number of results</param>
 234:     /// <param name="sortFields">Sort order dictionary</param>
 235:     /// <returns>Collection of entities</returns>
 236:     public IList<T> FindAll(int firstResult, int numberOfResults, IDictionary<string, bool> sortFields)
 237:     {
 238:         var orders = new List<Order>();
 239:         foreach (var item in sortFields)
 240:         {
 241:             var item1 = item;
 242:             if (typeof(T).GetProperties().Where(x => x.Name == item1.Key).Count() == 0)
 243:                 throw new CoreException("NHibernateBaseRepository_SortParameterNotValid",
 244:                                                ExceptionMessages.NHibernateBaseRepository_SortParameterNotValid,
 245:                                                new object[] { item1.Key });
 246:             orders.Add(new Order(item1.Key, item1.Value));
 247:         }
 248:         return AddOrders(Session.CreateCriteria(typeof(T)))
 249:             .SetMaxResults(numberOfResults)
 250:             .SetFirstResult(firstResult)
 251:             .List<T>();
 252:     }
 253:  
 254:     /// <summary>
 255:     /// Finds entities by criteria
 256:     /// </summary>
 257:     /// <param name="dc">Detatched criteria</param>
 258:     /// <returns>Collection of entities that match the passed criteria</returns>
 259:     public IList<T> FindByCriteria(DetachedCriteria dc)
 260:     {
 261:         return dc.GetExecutableCriteria(Session).List<T>();
 262:     }
 263:  
 264:     /// <summary>
 265:     /// Finds entities by criteria and paging
 266:     /// </summary>
 267:     /// <param name="dc">Detatched criteria</param>
 268:     /// <param name="firstResult">First result</param>
 269:     /// <param name="numberOfResults">Number of results to return</param>
 270:     /// <returns>Collection of entities that match the passed criteria</returns>
 271:     public IList<T> FindByCriteria(DetachedCriteria dc, int firstResult, int numberOfResults)
 272:     {
 273:         //Set paging
 274:         dc.SetFirstResult(firstResult).SetMaxResults(numberOfResults);
 275:  
 276:         //Execute criteria
 277:         return dc.GetExecutableCriteria(Session).List<T>();
 278:     }
 279:  
 280:     /// <summary>
 281:     /// Finds entities by criteria, paging and ordering
 282:     /// </summary>
 283:     /// <param name="dc">Detatched criteria</param>
 284:     /// <param name="firstResult">First result</param>
 285:     /// <param name="numberOfResults">Number of results to return</param>
 286:     /// <param name="orders">Orders</param>
 287:     /// <returns>Collection of entities that match the passed criteria</returns>
 288:     public IList<T> FindByCriteria(DetachedCriteria dc, int firstResult, int numberOfResults, params Order[] orders)
 289:     { 
 290:         return AddOrders(dc, orders).SetFirstResult(firstResult).SetMaxResults(numberOfResults)
 291:             .GetExecutableCriteria(Session).List<T>();
 292:     }
 293:   
 294:     /// <summary>
 295:     /// Gets a list of entities by passed query
 296:     /// </summary>
 297:     /// <param name="queryString">Query to get entities</param>
 298:     /// <returns>Collection of entities</returns>
 299:     public IList<T> FindByQuery(string queryString)
 300:     {
 301:         return Session.CreateQuery(queryString).List<T>();
 302:     }
 303:  
 304:     /// <summary>
 305:     /// Gets a list of entities by passed query and parameters
 306:     /// </summary>
 307:     /// <param name="queryString">Query to get entities</param>
 308:     /// <param name="parameters">Parameters to set in query</param>
 309:     /// <returns>Collection of entities</returns>
 310:     public IList<T> FindByQuery(string queryString, params object[] parameters)
 311:     {
 312:         var query = Session.CreateQuery(queryString);
 313:         if (parameters != null)
 314:         {
 315:             var count = 0;
 316:             foreach (var parameter in parameters)
 317:             {
 318:                 query.SetParameter(count, parameter);
 319:                 count++;
 320:             }
 321:         }
 322:         return query.List<T>();
 323:     }
 324:  
 325:     /// <summary>
 326:     /// Gets a list of entities by passed query
 327:     /// </summary>
 328:     /// <param name="queryString">Query to get entities</param>
 329:     /// <param name="firstResult">First result</param>
 330:     /// <param name="numberOfResults">Number of results to return</param>
 331:     /// <returns>Collection of entities</returns>
 332:     public IList<T> FindByQuery(string queryString, int firstResult, int numberOfResults)
 333:     {
 334:         return Session.CreateQuery(queryString)
 335:             .SetFirstResult(firstResult)
 336:             .SetMaxResults(numberOfResults)
 337:             .List<T>();
 338:     }
 339:  
 340:     /// <summary>
 341:     /// Gets a list of entities by passed query and parameters
 342:     /// </summary>
 343:     /// <param name="queryString">Query to get entities</param>
 344:     /// <param name="firstResult">First result</param>
 345:     /// <param name="numberOfResults">Number of results to return</param>
 346:     /// <param name="parameters">Parameters to set in query</param>
 347:     /// <returns>Collection of entities</returns>
 348:     public IList<T> FindByQuery(string queryString, int firstResult, int numberOfResults, params object[] parameters)
 349:     {
 350:         var query = Session.CreateQuery(queryString);
 351:         if (parameters != null)
 352:         {
 353:             var count = 0;
 354:             foreach (var parameter in parameters)
 355:             {
 356:                 query.SetParameter(count, parameter);
 357:                 count++;
 358:             }
 359:         }
 360:         return query.List<T>();
 361:     }
 362:  
 363:     /// <summary>
 364:     /// Finds one entity that matches criteria and throws exception otherwise
 365:     /// </summary>
 366:     /// <param name="criteria">Criteria</param>
 367:     /// <returns>Entity matching criteria</returns>
 368:     public T FindOne(DetachedCriteria criteria)
 369:     {
 370:         return criteria.GetExecutableCriteria(Session).UniqueResult<T>();
 371:     }
 372:  
 373:     /// <summary>
 374:     /// Finds first entity in collection that matches criteria
 375:     /// </summary>
 376:     /// <param name="criteria">Criteria</param>
 377:     /// <returns>First entity</returns>
 378:     public T FindFirst(DetachedCriteria criteria)
 379:     {
 380:         //Do we have any results?
 381:         var results = criteria.SetMaxResults(1)
 382:             .GetExecutableCriteria(Session).List<T>();
 383:  
 384:         return (results.Count > 0) ? results[0] : default(T);
 385:     }
 386:  
 387:     /// <summary>
 388:     /// Finds first entity in collection that matches criteria and order params
 389:     /// <remarks>Can be used to get last in a collection</remarks>
 390:     /// </summary>
 391:     /// <param name="criteria">Criteria</param>
 392:     /// <param name="orders">Orders</param>
 393:     /// <returns>First entity</returns>
 394:     public T FindFirst(DetachedCriteria criteria, params Order[] orders)
 395:     {
 396:         var results = AddOrders(criteria, orders).SetMaxResults(1)
 397:             .GetExecutableCriteria(Session).List<T>();
 398:  
 399:         return (results.Count > 0) ? results[0] : default(T);
 400:     }
 401:  
 402:     /// <summary>
 403:     /// Get count of entities that match criteria
 404:     /// </summary>
 405:     /// <param name="criteria">Criteria</param>
 406:     /// <returns>Count of number of entities that match criteria</returns>
 407:     public long Count(DetachedCriteria criteria)
 408:     {
 409:         return Convert.ToInt64(criteria.GetExecutableCriteria(Session)
 410:                         .SetProjection(Projections.RowCountInt64()).UniqueResult());
 411:     }
 412:  
 413:     /// <summary>
 414:     /// Get count of entities
 415:     /// </summary>
 416:     /// <returns>Count of entities</returns>
 417:     public long Count()
 418:     {
 419:         return Convert.ToInt64(Session.CreateCriteria(typeof(T)).SetProjection(Projections.RowCountInt64()).UniqueResult());
 420:     }
 421:  
 422:     /// <summary>
 423:     /// Determines if at least one entity exists that matches passed criteria
 424:     /// </summary>
 425:     /// <param name="criteria">Criteria</param>
 426:     /// <returns><c>true</c> if exists</returns>
 427:     public bool Exists(DetachedCriteria criteria)
 428:     {
 429:         return Count(criteria) > 0;
 430:     }
 431:  
 432:     #endregion INHibernateBaseRespository<T> Members
 433:  
 434:     #endregion Public Methods
 435:  
 436:     #region Private Methods
 437:  
 438:     /// <summary>
 439:     /// Adds orders to detached criteria
 440:     /// </summary>
 441:     /// <param name="dc">Detached criteria</param>
 442:     /// <param name="orders">Orders</param>
 443:     /// <returns>Criteria with orders</returns>
 444:     private static DetachedCriteria AddOrders(DetachedCriteria dc, params Order[] orders)
 445:     {
 446:         //Build orders
 447:         if (orders != null)
 448:             foreach (var order in orders)
 449:                 dc.AddOrder(order);
 450:  
 451:         return dc;
 452:     }
 453:  
 454:     /// <summary>
 455:     /// Adds orders to detached criteria
 456:     /// </summary>
 457:     /// <param name="dc">criteria</param>
 458:     /// <param name="orders">Orders</param>
 459:     /// <returns>Criteria with orders</returns>
 460:     private static ICriteria AddOrders(ICriteria dc, params Order[] orders)
 461:     {
 462:         //Build orders
 463:         if (orders != null)
 464:             foreach (var order in orders)
 465:                 dc.AddOrder(order);
 466:  
 467:         return dc;
 468:     }
 469:  
 470:     #endregion Private Methods
 471: }

Then say if I have an entity called 'Mountain' I would name a repository 'MountainRepository' which implements the interface IMountainRepository:

   1: /// <summary>
   2: /// Provides Mountain repository functionality
   3: /// </summary>
   4: public interface IMountainRepository : INHibernateBaseRepository<Mountain>
   5: {
   6:     /// <summary>
   7:     /// Get mountains by height
   8:     /// </summary>
   9:     /// <param name="height">Height of mountain</param>
  10:     IList<Mountain> GetMountainsByHeight(double height);
  11: }

and concrete implementation:

   1: /// <summary>
   2: /// Provides user group repository functionality
   3: /// </summary>
   4: public class MountainRepository: NHibernateBaseRepository<Mountain>, IMountainRepository 
   5: {
   6:     #region Constructors
   7:  
   8:     /// <summary>
   9:     /// Constructor for the suv user group restriction repository
  10:     /// </summary>
  11:     /// <param name="sessionManager">Session manager</param>
  12:     public SuvUserGroupRepository(ISessionManager sessionManager)
  13:         : base(sessionManager)
  14:     {
  15:     }
  16:  
  17:     #endregion Constructors
  18:  
  19:     #region Public Methods
  20:  
  21:     #region IMountainRepository Members
  22:  
  23:     /// <summary>
  24:     /// Get mountains by height
  25:     /// </summary>
  26:     /// <param name="height">Height of mountain</param>
  27:     public IList<Mountain> GetMountainsByHeight(double height)
  28:     {
  29:         return FindAll(DetachedCriteria.For<Mountain>().Add<Mountain>(x => x.Height == height));
  30:     }
  31:  
  32:     #endregion IMountainRepository Members
  33:  
  34:     #endregion Public Methods
  35: }

So the repository classes are all simpler and I have still access to the 20 odd base methods which have all the basic NHibernate functionality required.