Utilisation correcte du pattern NHibernate Unit Of Work et Ninject
J'ai la suite de la mise en œuvre et aimerait que certains des commentaires si elle fait de l'utilisation correcte de NHibernate pour les sessions et les transactions.
public interface IUnitOfWork : IDisposable
{
ISession CurrentSession { get; }
void Commit();
void Rollback();
}
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
CurrentSession = _sessionFactory.OpenSession();
_transaction = CurrentSession.BeginTransaction();
}
public ISession CurrentSession { get; private set; }
public void Dispose()
{
CurrentSession.Close();
CurrentSession = null;
}
public void Commit()
{
_transaction.Commit();
}
public void Rollback()
{
if (_transaction.IsActive) _transaction.Rollback();
}
}
Ninject liaison
Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope();
Bind<ISessionFactory>().ToProvider<NHibernateSessionFactoryProvider>().InSingletonScope();
Bind<IRepository>().To<Repository>().InTransientScope();
Voici un exemple de l'utilisation:
public class Repository : IRepository
{
private readonly ISessionFactory _sessionFactory;
public Repository(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
public void Add(IObj obj)
{
using (var unitOfWork = new UnitOfWork(_sessionFactory))
{
unitOfWork.CurrentSession.Save(obj);
unitOfWork.Commit();
}
}
}
Dans mon précédent de mise en œuvre, je voudrais injecter IUnitOfWork dans mon référentiel constructeur comme
public Repository(IUnitOfWork unitOfWork)
{...
Mais la méthode dispose() ne serait pas exécuter provoquant un appel ultérieur à lever cette exception: "Impossible d'accéder à un objet supprimé. Nom de l'objet: 'AdoTransaction'."
source d'informationauteur Brian T
Vous devez vous connecter pour publier un commentaire.
Première observation: le référentiel ne faut pas commettre l'unité de travail. Cela va à l'encontre du point de l'ensemble de l'unité de travail modèle. Par immédiatement enregistrer vos modifications à l'intérieur du dépôt, vous êtes "micro-gestion" de la NHibernate Session.
L'unité de travail doit être référencé plus haut dans la pile, dans votre application/de la couche de service. Cela vous permet d'avoir le code de l'application qui effectue plusieurs actions, potentiellement sur des référentiels différents, et encore à la fin de commettre tout à la fois.
La UnitOfWork classe elle-même semble Ok, mais vous devriez vous demander si vous avez vraiment besoin. Dans NHibernate, le ISession EST votre unité de travail. Votre UnitOfWork classe ne semble pas ajouter beaucoup de valeur (surtout depuis que vous êtes exposant les CurrentSession propriété de toute façon)
Mais vous avez besoin de penser au sujet de sa vie. Je pense que vous avez tort sur ce point. Session de gestion de durée de vie dépend du type d'application que vous êtes en développement: dans une application web, il est généralement préférable de disposer d'une unité de travail, conformément à la demande (vous pouvez google sur "nhibernate session, conformément à la demande'). Dans une application de bureau, c'est légèrement plus compliqué, vous aurez la plupart du temps d'une séance par écran " ou "conversation par transaction".
J'ai surtout CRUD type d'application, et j'ai mis en place l'Unité De Travail avec un modèle de Référentiel, mais ne pouvait pas vraiment s'éloigner de la Session/l'Opération de scission. Des Sessions et les Transactions ont besoin de différentes durées de vie. Dans le monde de bureau, une Session est habituellement "par l'écran" et l'Opération est "par utilisateur-action".
Plus d'informations à ce excellent article.
Donc ce que j'ai fini avec:
IUnitOfWork
-> Enveloppements session, met en œuvreIDisposable
IAtomicUnitOfWork
-> Enveloppements transaction, met en œuvreIDisposable
IRepository
-> Fournit à Obtenir, Enregistrer, Supprimer, et de l'accès aux requêtesJ'ai fait en sorte que vous avez besoin d'un
IUnitOfWork
de construire unIAtomicUnitOfWork
et vous avez besoin d'unIAtomicUnitOfWork
de construire unIRepository
donc, qui assure la bonne gestion des transactions. C'est vraiment tout ce que j'ai acquise par la mise en œuvre de mes propres interfaces.Comme jeroenh dit, vous êtes presque tout aussi bien à une utilisation en
ISession
etITransaction
mais en fin de compte je me sentais un peu mieux écrit de tous mon code à l'encontre d'une interface que j'ai défini.Une partie importante de la réponse réside dans ce que vous voulez que vos tailles de transaction. En ce moment (comme jeroenh a indiqué), la transaction est par l'invocation de méthode sur votre dépôt. C'est très petit et n'est probablement pas nécessaire. J'ai créé une page ASP.L'application MVC et il utilise une taille de transaction, qui comprenait tout, à partir d'une seule requête http. Cela pourrait être de base de données multiples lectures/mises à jour. Je suis l'aide de la même unité de travail et de Ninject pour le CIO. Prendre un coup d'oeil, peut-être quelque chose qui va les aider avec vos questions:
http://bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/
http://bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://bobcravens.com/2010/09/the-repository-pattern-part-2/
http://bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/
Espère que cette aide.
Bob