I\'m new to NHibernate and not very good at C#, but I\'m learning. I have a DataProvider
class which provides data for my application using NHibernate 3. It\'s stru
First of all, to address your Test Setup question: the term Repository might suggest that it should be a long lived, persistent object, but Repositories used in DAL operations should actually be lightweight stateless objects with short lifetimes: you instantiate one when you need it, and throw it away as soon as you're done. When you think about this is terms of performance, you can easily instantiate millions of them per second.
Combined with NHibernate's short lived Session
instances, this is how your code is meant to look like when everything is in place:
using (var session = SessionManager.OpenSession())
{
// create an instrument repo
IInstrumentRepo instruments = DAL.RepoFactory.CreateInstrumentRepo(session);
var guitar = instruments.Find(i => i.Type == "Guitar");
// create a customer repo
ICustomerRepo customers = DAL.RepoFactory.CreateCustomerRepo(session);
var cust = customers.Find(c => c.Name == "Mark")
// do something -> changes will be persisted by NH when session is disposed
cust.Instruments.Add(guitar);
}
That's the general idea. Now, let me explain it in more detail:
You may have noticed that each repo has its own interface, and is created through a repo factory. Using a factory to create repositories means you can easily create mock repo factories, which will create any custom implementation of a repository for testing.
Each repo interface inherits from the base interface generic interface, IRepo
. This allows you to use a generic repository in 99% of cases, but still leave room to implement a custom query method specific to, say, Customer
entities only:
public interface IInstrumentRepo : IRepo
{
// nothing to do here
}
public interface ICustomerRepo : IRepo
{
// but we'll need a custom method here
void FindByAddress(string address);
}
public interface IRepo
{
T GetById(object id);
T Save(T item);
}
This means that your repo implementations will, in most cases, simply inherit from the base abstract class (I named it BaseRepo
, but it's essentially what your DataProvider
class does right now):
class InstrumentRepo : BaseRepo, IInstrumentRepo
{
// no need to implement anything here except pass the session downwards
public InstrumentRepo(ISession s) : base(s) { }
}
Your factory will simply need to instantiate the proper repository when asked:
public class RepoFactory : IRepoFactory
{
public IInstrumentRepo CreateInstrumentRepo(ISession s)
{
return new InstumentRepo(s);
}
}
And you will need to use the Singleton pattern in a, say, DAL
class to hold the factory (there are slightly better ways to do this, using DI, but for now this will do just fine):
public static class DAL
{
// repo factory is pretty lightweight, so no need for fancy
// singleton patterns
private static readonly IRepoFactory _repoFactory = new RepoFactory();
public static IRepoFactory RepoFactory
{
get { return _repoFactory; }
}
}