Using nHibernate and the repository pattern, need some direction - nhibernate

Ok so I 'm just getting into nhibernate (using fluent).
One thing that I love about it is that I can use the Repository pattern (read about it from the nhibernate rhino blog).
Basically using generics, I can create methods that will work accross ALL my database tables.
public interface IRepository<T>
{
T GetById(int id);
ICollection<T> FindAll();
void Add(T entity);
void Remove(T entity);
}
public class Repository<T> : IRepository<T>
{
public ISession Session
{
get
{
return SessionProvider.GetSession();
}
}
public T GetById(int id)
{
return Session.Get<T>(id);
}
public ICollection<T> FindAll()
{
return Session.CreateCriteria(typeof(T)).List<T>();
}
public void Add(T t)
{
Session.Save(t);
}
public void Remove(T t)
{
Session.Delete(t);
}
}
I then inherit the Repository class and I can then add methods that are specific to that entity.
When trying to add an Update method, someone mentioned that the Repository pattern is suppose to act on collections? Am I looking at things incorrectly here? Why can't I create an update method?
I tried adding a update method, but I'm confused as to how I will handle the session and update the database?
I want a single place for all my database access for each entity, so UserRepository will have all basic CRUD and then maybe some other methods like GetUserByEmail() etc.

Don't use the repository pattern - use the UnitOfWork pattern instead, and pass defined query ICriteria to the ISession. Essentially the Repo pattern is wrapping something that doesn't need to be wrapped with NH.
see http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx for more info

Perhaps you misheard or someone mispoke - the Repository pattern is supposed to expose collection like behavior, not operate on collections. Just like you can add, remove and search for items in a collection, your repository offers save, delete and search operations that work against your database.
I suggest you download the code for S#arp Architecture. It includes a repository implementation that you can reuse quite easily. If you don't want to take the dependency, at the very least you can spend some time studying their implementation to give you a better idea of how to approach it yourself.

Related

Ninject NHibernate on plugin oriented architecture

According COMPOSITION ROOT pattern, I must to construct all dependencies graph as close as possible to the application's entry point.
My architecture is plugin oriented. So, if someone wants to extend my base system he can.
For example, in my base system I have this structure:
View Layer
Services Layer
Data Access Layer
Model Layer
In DAL, I expose some classes like:
IRepository
NHibernateRepository
ProductRepository
So, I'd like if a plugin wants to extend my base Product class to ExtendedProduct, and then create ExtendedProductRepository that inherits from NHibernateRepository.
The question is:
How can instantiate from my base system an instance of NHibernateRepository using NInject?
So, I know the first thing to do is to construct the graph dependencies:
using (var kernel = new StandardKernel())
{
kernel.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom<IRepository>()
.BindAllInterfaces());
}
However, I'm figuring out that when I execute something like:
kernel.GetAll<IRepository>()
It's going to return me a ProductRepository instance, and another ProductExtendedRepository under two IRepository objects.
So, how I can save a ProductExtended object from my base system...?
Another question, would be, how could I inject a object instance in my plugins, or, how can plugins autoinject some instance of base system assembly?
Thanks for all.
I'll appreciate a lot some help.
I use this pattern for my NHibernate based projects:
public interface IRepository<T> : IQueryable<T>
{
T Get(int id);
void Save(T item);
void Delete(T item);
}
public class NHibernateRepository<ModelType> : IRepository<ModelType>
where ModelType : class
{
// implementation
}
then...
public interface IProductRepository : IRepository<Product>
{
// product specific data access methods
}
public class ProductRepository : NHibernateRepository<Product>, IProductRepository
{
// implementation
}
... and in Ninject Module:
Bind(typeof(IRepository<>)).To(typeof(NHibernateRepository<>));
Bind<IProductRepository>().To<ProductRepository>();
then you can either request the base functionality like:
public Constructor(IRepository<Product> repo) { ... }
or specific product repository functionality:
public Constructor(IProductRepository repo) { ... }
your plugins can either get the base functionality and won't have to register anything:
public PluginConstructor(IRepository<ProductExtended> repo { ... }
or create their own repositories and register them in a Ninject module.
Thanks dave.
It's perfect. I'll try it.
However, how could I save or get or update (whichever IRepository methods)... an ExtendedProduct instance from my base system?
Think the follow out:
public interface BasePlugin<T> {...}
In another assembly:
public class PluginExtendedProduct : BasePlugin<ExtendedProduct>
{
public PluginExtendedProduct (IRepository<ExtendedProduct> repo { ... }
}
My headache is how to create an instance of (so, ExtendedProduct) in my base system in order to call methods PluginExtendedProduct that uses an IRepository.
I don't know if I'm explaining myself well...
Thanks for all.

Repository OO Design - Multiple Specifications

I have a pretty standard repository interface:
public interface IRepository<TDomainEntity>
where TDomainEntity : DomainEntity, IAggregateRoot
{
TDomainEntity Find(Guid id);
void Add(TDomainEntity entity);
void Update(TDomainEntity entity);
}
We can use various infrastructure implementations in order to provide default functionality (e.g. Entity Framework, DocumentDb, Table Storage, etc). This is what the Entity Framework implementation looks like (without any actual EF code, for simplicity sake):
public abstract class EntityFrameworkRepository<TDomainEntity, TDataEntity> : IRepository<TDomainEntity>
where TDomainEntity : DomainEntity, IAggregateRoot
where TDataEntity : class, IDataEntity
{
protected IEntityMapper<TDomainEntity, TDataEntity> EntityMapper { get; private set; }
public TDomainEntity Find(Guid id)
{
// Find, map and return entity using Entity Framework
}
public void Add(TDomainEntity item)
{
var entity = EntityMapper.CreateFrom(item);
// Insert entity using Entity Framework
}
public void Update(TDomainEntity item)
{
var entity = EntityMapper.CreateFrom(item);
// Update entity using Entity Framework
}
}
There is a mapping between the TDomainEntity domain entity (aggregate) and the TDataEntity Entity Framework data entity (database table). I will not go into detail as to why there are separate domain and data entities. This is a philosophy of Domain Driven Design (read about aggregates). What's important to understand here is that the repository will only ever expose the domain entity.
To make a new repository for, let's say, "users", I could define the interface like this:
public interface IUserRepository : IRepository<User>
{
// I can add more methods over and above those in IRepository
}
And then use the Entity Framework implementation to provide the basic Find, Add and Update functionality for the aggregate:
public class UserRepository : EntityFrameworkRepository<Stop, StopEntity>, IUserRepository
{
// I can implement more methods over and above those in IUserRepository
}
The above solution has worked great. But now we want to implement deletion functionality. I have proposed the following interface (which is an IRepository):
public interface IDeleteableRepository<TDomainEntity>
: IRepository<TDomainEntity>
{
void Delete(TDomainEntity item);
}
The Entity Framework implementation class would now look something like this:
public abstract class EntityFrameworkRepository<TDomainEntity, TDataEntity> : IDeleteableRepository<TDomainEntity>
where TDomainEntity : DomainEntity, IAggregateRoot
where TDataEntity : class, IDataEntity, IDeleteableDataEntity
{
protected IEntityMapper<TDomainEntity, TDataEntity> EntityMapper { get; private set; }
// Find(), Add() and Update() ...
public void Delete(TDomainEntity item)
{
var entity = EntityMapper.CreateFrom(item);
entity.IsDeleted = true;
entity.DeletedDate = DateTime.UtcNow;
// Update entity using Entity Framework
// ...
}
}
As defined in the class above, the TDataEntity generic now also needs to be of type IDeleteableDataEntity, which requires the following properties:
public interface IDeleteableDataEntity
{
bool IsDeleted { get; set; }
DateTime DeletedDate { get; set; }
}
These properties are set accordingly in the Delete() implementation.
This means that, IF required, I can define IUserRepository with "deletion" capabilities which would inherently be taken care of by the relevant implementation:
public interface IUserRepository : IDeleteableRepository<User>
{
}
Provided that the relevant Entity Framework data entity is an IDeleteableDataEntity, this would not be an issue.
The great thing about this design is that I can start granualising the repository model even further (IUpdateableRepository, IFindableRepository, IDeleteableRepository, IInsertableRepository) and aggregate repositories can now expose only the relevant functionality as per our specification (perhaps you should be allowed to insert into a UserRepository but NOT into a ClientRepository). Further to this, it specifies a standarised way in which certain repository actions are done (i.e. the updating of IsDeleted and DeletedDate columns will be universal and are not at the hand of the developer).
PROBLEM
A problem with the above design arises when I want to create a repository for some aggregate WITHOUT deletion capabilities, e.g:
public interface IClientRepository : IRepository<Client>
{
}
The EntityFrameworkRepository implementation still requires TDataEntity to be of type IDeleteableDataEntity.
I can ensure that the client data entity model does implement IDeleteableDataEntity, but this is misleading and incorrect. There will be additional fields that are never updated.
The only solution I can think of is to remove the IDeleteableDataEntity generic condition from TDataEntity and then cast to the relevant type in the Delete() method:
public abstract class EntityFrameworkRepository<TDomainEntity, TDataEntity> : IDeleteableRepository<TDomainEntity>
where TDomainEntity : DomainEntity, IAggregateRoot
where TDataEntity : class, IDataEntity
{
protected IEntityMapper<TDomainEntity, TDataEntity> EntityMapper { get; private set; }
// Find() and Update() ...
public void Delete(TDomainEntity item)
{
var entity = EntityMapper.CreateFrom(item);
var deleteableEntity = entity as IDeleteableEntity;
if(deleteableEntity != null)
{
deleteableEntity.IsDeleted = true;
deleteableEntity.DeletedDate = DateTime.UtcNow;
entity = deleteableEntity;
}
// Update entity using Entity Framework
// ...
}
}
Because ClientRepository does not implement IDeleteableRepository, there will be no Delete() method exposed, which is good.
QUESTION
Can anyone advise of a better architecture which leverages the C# typing system and does not involve the hacky cast?
Interestly enough, I could do this if C# supported multiple inheritance (with separate concrete implementation for finding, adding, deleting, updating).
I do think that you're complicating things a bit too much trying to get the most generic solution of them all, however I think there's a pretty easy solution to your current problem.
TDataEntity is a persistence data structure, it has no Domain value and it's not known outside the persistence layer. So it can have fields it won't ever use, the repository is the only one knowing that, it'a persistence detail . You can afford to be 'sloppy' here, things aren't that important at this level.
Even the 'hacky' cast is a good solution because it's in one place and a private detail.
It's good to have clean and maintainable code everywhere, however we can't afford to waste time coming up with 'perfect' solutions at every layer. Personally, for view and persistence models I prefer the quickest and simplest solutions even if they're a bit smelly.
P.S: As a thumb rule, generic repository interfaces are good, generic abstract repositories not so much (you need to be careful) unless you're serializing things or using a doc db.

Multiple UnitOfWorks, ISession and repositories

Do you know a good example somewhere for this?
What I would like is the following:
using(IUnitOfWork uow = UnitOfWork.Start())
{
repositoryA.Add(insanceOfA);
repositoryB.Add(instanceOfB);
uow.Commit();
}
But this case is too ideal, because what I also want is multiple UnitOfWorks (per presenter in most cases, and this is not for a web app). In that case, how will repositories know which UnitOfWork to use if I don't give them that explicitly like
repository.UnitOfWork = uow;
My goal is to have every UnitOfWork contain a ISession behind, so one UOW per presenter, one ISession per presenter. Note: I know that ISession is esentially UOW, but I must proceed this way...
Any advices are appreciated
What I do, is pass the unitOfWork that should be used to the Repository.
To achieve this, you can make sure that you have to pass the UnitOfWork instance that must be used by the repository in the repository's constructor.
In order to make it all a bit more user-friendly, you can create extension methods on your UnitOfWork that are specific for your project (supposing that your UnitOfWork is generic and used in multiple projects) that look like this:
public static class UnitOfWorkExtensions
{
public static IRepositoryA GetRepositoryA( this UnitOfWork uow )
{
return new RepositoryA(uow);
}
public static IRepositoryB GetRepositoryB( this UnitOfWork uow )
{
return new RepositoryB(uow);
}
}
Then, it enables you to do this:
using(IUnitOfWork uow = UnitOfWork.Start())
{
var repositoryA = uow.GetRepositoryA();
var repositoryB = uow.GetRepositoryB();
repositoryA.Add(insanceOfA);
repositoryB.Add(instanceOfB);
uow.Commit();
}

NHibernate - why is this static method legal in this domain class?

I have read in Chapter 4 of the NHibernate docs that all of a persistent classes public methods, properties and events must be declared as virtual.
However, whilst a runtime error is generated for any Properties that are not marked as virtual, I have found that static methods are allowed and do not generate a runtime error . As they are static they are of course not marked virtual which seems to break the rule in point 4.1.4 of the documentation (see above). I have checked the resulting sql and it also implements lazy loading correctly when I run a test against the method so is it therefore ok to use static methods?
Here's the basic details of the persistant class:
public class CmsPage
{
public virtual int? Id { get; set; }
public virtual string Title { get; set; }
public virtual void Update()
{
using (ISession session = NHibernateHelper.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Update(this);
transaction.Commit();
}
}
}
// Note: static and non-virtual and yet it will not cause a problem for Nhibernate
public static IEnumerable<CmsPage> GetList()
{
IList<CmsPage> pageList;
using (ISession session = NHibernateHelper.OpenSession())
{
string hql = "from CmsPage p";
pageList = session.CreateQuery(hql)
.List<CmsPage>();
}
return pageList;
}
}
So my question is why is it ok to use a static method in the persistent domain class when the documentation seems to say it's not?
Please answer from NHibernate's point of view not an OO design point of view; I don't want to get into an OOD/OOP debate if it can be avoided please.
The documentation says: "NHibernate works best if these classes follow some simple rules, ..." It doesn't say it won't work (clearly it does work).
So, really, the discussion boils down to an OO issue.
Actually this applies only to properties. Methods are not persisted, so proxies and lazy-loading does not apply. Ideally you should separate data access (the static methods in your case) from the domain object. But you are correct to point this out, maybe the documentation should have been clearer.
In conclusion your class is perfectly fine but it could be even better if you separated the concerns.
NHibernate needs all your properties to be virtual because it carries out its lazy-loading magic by making proxies of your objects that override everything. So when you write this code:
class Foo {
public virtual Foo[] Neighbors { get; set; }
}
NHibernate secretly generates classes like:
class NHProxy03450843275 : Foo {
public virtual Foo[] Neighbors { /* Godawful lazy-loading magic goes here */ }
}
Actually it's worse than that, but this gives you the idea. Anyway, static methods aren't bound to particular instances of a class, so NH doesn't need proxies to deal with them. Thus they can be non-virtual.

NHibernate ITransaction and pure domain model

I'm trying to write my Domain Model as persistence-ignorant as possible. The only thing I'm doing right now is marking every property and method virtual, as NHibernate requires that for lazy-loading.
In my domain model assembly I define some repository interfaces:
public interface IRepository<TEntity> where TEntity : EntityBase {
TEntity Get(int id);
/* ... */
}
public interface IProductRepository : IRepository<Product> { ... }
Then I have a data assembly. This one will reference NHibernate, it knows about its existence. This is the assembly that implements those repository interfaces:
public abstract class Repository<TEntity> : IRepository<TEntity> {
public TEntity Get(ind id) { ... }
/* ... */
}
public class ProductRepository : Repository<Product>, IProductRepository {
/* ... */
}
and so on.
Now I wanted to implement a transaction functionality to my repositories. To do so, I would add a BeginTransaction method on my IRepository interface. However, I cannot define its return type as NHibernate.ITransaction, since I want to keep the domain model persistence-ignorant, and not be forced to reference NHibernate's assembly from my domain model assembly.
What would you do?
Would you simply implement a void BeginTransaction(), a void Commit(), and a void RollBack() methods on the interface, and let the repository implementation manage the ITransaction object internally?
Or would you find a way to expose the ITransaction object to let the client manage the transaction directly with it, instead of using repository's methods?
Thanks!
You can take a look at the Sharp Architecture which has already implemented everything you talk about, including generic repositories with transactions support. The solution there is that IRepository has DbContext property which encapsulates transactions (it's actually an interface).
This is the first of the options that you described (custom transactions interface which hides NHibernate). And it works well.
I guess you can even re-use S#arp code regardless if you intend to use the full framework.
IMO Transactions should always start and end in business logic, in other words the transaction should start in the service layer not the repository layer and the repository should enlist it's self in the transaction, ideally this would be done implicitly.
Now if you're using NH then if your service and repositories share the same 'session' (which they should) then you can call 'BeginTransaction' in the service layer and commit or roll back as required:
Eg, imagine this a method on a service:
public void RegisterCustomer(Customer customer)
{
try
{
using(var transaction = _session.BeginTransaction())
{
_customerRepository.Save(customer);
_customerSurveyRepository.Save(customerSurvey);
// DO What ever else you want...
transaction.Commit();
}
}
catch (Exception exn)
{
throw new AMException(FAILED_REGISTRATION, exn);
}
}
How the repositories obtain a reference to the same Session can be solved by injecting in the constructors or by using a the SessionFactory to obtain the current session...