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 structured pretty much identical to Steve Bohlen's Summer of NHibernate videos.
I've noticed that I'm about to repeat my code a lot and I want to simplify my DataProvider
. For example I have two business classes called Instrument
and Broker
. The method to add an Instrument
in my DataProvider
is:
public int AddInstrument(Instrument instrument)
{
using (ITransaction tx = _session.BeginTransaction())
{
try
{
int newId = (int)_session.Save(instrument);
_session.Flush();
tx.Commit();
return newId;
}
catch (NHibernate.HibernateException)
{
tx.Rollback();
throw;
}
}
}
and the AddBroker
class looks remarkably similar (just find and replace). So I thought maybe I could use Generics to solve the problem. Something like:
public class DataProvider <TEntity>
{
public int AddEntity(TEntity entity)
{
using (ITransaction tx = _session.BeginTransaction())
{
try
{
int newId = (int)_session.Save(entity);
_session.Flush();
tx.Commit();
return newId;
}
catch (NHibernate.HibernateException)
{
tx.Rollback();
throw;
}
}
}
}
With this I can pass in a Broker
, an Instrument
or anything and I save myself a lot of repetitive code. The problem I'm having is that in my Test
class I create a new DataProvider
each time a test is run like this:
#region Fields
private DataProvider _provider;
private SessionManager _sessionManager;
private NHibernate.ISession _session;
#endregion
[SetUp]
public void Setup()
{
DatabaseSetUp();
_session = _sessionManager.GetSession();
_provider = new DataProvider(_session); // problem here
}
Using generics I have to pass in the object type to my DataProvider
. Can you think of a way to solve this? I am a novice programmer and I am wondering if I am going down the right path. Should I be doing something totally different?
UPDATE
I have tried to implement Groo's answer but am having some issues. Here's what I've done.
IRepo.cs
interface IRepo<T>
{
int Add<Entity>(Entity entity);
void Delete<Entity>(Entity entity);
void GetById<Entity>(int Id);
}
BaseRepo.cs
public abstract class BaseRepo <T> : IRepo <T>
{
private ISession _session;
#region SessionManagement
public BaseRepo(ISession session)
{
_session = session;
}
public ISession Session
{
set { _session = value; }
}
#endregion
public int Add<Entity>(Entity entity)
{
using (ITransaction tx = _session.BeginTransaction())
{
try
{
int newId = (int)_session.Save(entity);
_session.Flush();
tx.Commit();
return newId;
}
catch (NHibernate.HibernateException)
{
tx.Rollback();
throw;
}
}
}
// other methods omitted for brevity
}
IRepoFactory.cs
interface IRepoFactory
{
IInstrumentRepo CreateInstrumentRepo(ISession s);
}
RepoFactory.cs
public class RepoFactory : IRepoFactory
{
public IInstrumentRepo CreateInstrumentRepo(ISession s) // problem here
{
return new InstrumentRepo(s);
}
}
IInstrumentRepo.cs
interface IInstrumentRepo : IRepo<Instrument>
{
}
InstrumentRepo.cs
public class InstrumentRepo : BaseRepo<Instrument>, IInstrumentRepo
{
public InstrumentRepo(ISession s) : base(s) { }
}
In RepoFactory.cs I get this error:
Inconsistent accessibility: return type 'MooDB.Data.IInstrumentRepo' is less accessible than method 'MooDB.Data.RepoFactory.CreateInstrumentRepo(NHibernate.ISession)'
Any ideas what I'm missing?