2009-06-25 6 views
2

Я использую StructureMap как свой контейнер IoC и NHibernate как свой ORM. Я нашел пример в Интернете, в котором показано, как иметь StructureMap для сборки ISessionFactory и ISession, так что Factory является одноэлементным, а Session основан на HttpContext. Это отлично работает, но затем я начал использовать NH Profiler, который сказал мне, что я всегда должен явно использовать транзакции. Итак, подумал я, почему бы не позволить StructureMap обрабатывать это для меня тоже? Используя приведенный ниже код, я понял, что все работает нормально, кроме того, я не знаю, как/где совершать/откатывать транзакции.Управление IT-взаимодействием NHibernate с StructureMap?

Вот как я инициализировать StructureMap:

ObjectFactory.Initialize(x => 
    { 
     x.ForRequestedType<ISessionFactory>() 
      .CacheBy(InstanceScope.Singleton) 
      .TheDefault.Is.ConstructedBy(cfg.BuildSessionFactory); 

     x.ForRequestedType<ISession>() 
      .CacheBy(InstanceScope.Hybrid) 
      .TheDefault.Is.ConstructedBy(context => context.GetInstance<ISessionFactory>().OpenSession()); 

     x.ForRequestedType<ITransaction>() 
      .CacheBy(InstanceScope.Hybrid) 
      .TheDefault.Is.ConstructedBy(context => context.GetInstance<ISession>().BeginTransaction()); 

     x.Scan(y => 
     { 
      y.TheCallingAssembly(); 
      y.WithDefaultConventions(); 
     }); 
    }); 

Все мои хранилищами выглядеть следующим образом:

public UserRepository(ISession session, ITransaction transaction) 
    { 
     _session = session; 
     _transaction = transaction; 
    } 

И типичный метод внутри хранилища выглядит следующим образом:

public void Remove(int id) 
    { 
     Remove(_session.Get<User>(id)); 
    } 

То, что я пытаюсь сделать, это иметь все методы, которые я вызываю в одном HttpContext, Сессия и транзакция. Возможно ли это, или это совершенно неправильно, и я лаю неправильное дерево?

Заранее благодарен!

Дан

+0

Вы когда-нибудь принимали решение об этом или находили приемлемое решение? Мне интересно то же самое. – mxmissile

ответ

2

Этот вопрос был, почему я создал простой UnitOfWork, который сочетает в себе ISession и ITransaction.

В тестах, я хотел бы написать следующий код:

var product = new Product {Name = "Apple", Category = "Fruits"}; 
using (var session = _sessionFactory.OpenSession()) 
using (var transaction = _session.BeginTransaction()) 
{ 
    session.Save(product); 
    transaction.Commit(); 
} 

, когда я действительно хотел:

var product = new Product {Name = "Apple", Category = "Fruits"}; 
using (var unitOfWork = new UnitOfWork(_sessionFactory)) 
{ 
    unitOfWork.CurrentSession.Save(product); 
    unitOfWork.Commit(); 
} 

Вот моя единица выполнения работ,

using NHibernate; 

namespace NHibernateBootstrap.Core.Persistence 
{ 
    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(); 
     } 
    } 
} 

Что касается как когда вызывать Commit() (используя ITransaction или UnitOfWork), я считаю, что это должно быть сделано явно до конец вашего запроса. Если вы его не назовете, то UnitOfWork должен очиститься, но не зафиксировать. Кроме того, вы можете использовать HttpModule для фиксации в обработчике EndRequest.

Смежные вопросы