I have the project layout per illustration above. enter image description here

I would like to write a "SesisonManager" with an interface ISessionManager, wire it up using my container and inject it into my service layer. The UI and Infrastructure layers are the outermost layers and only have core as a dependency at this point, which from what I am reading is the correct approach.

My SessionManager looks something like this.

 public interface ISessionManager:IDisposable
{
    ISession GetSession();

}

public class SessionManager : ISessionManager
{
    private readonly ISessionFactory _sessionFactory;
    private readonly ILogger _logger;
    private ITransaction _transaction;
    private ISession _session;
    public SessionManager(ISessionFactory sessionFactory,ILogger logger)
    {
        _sessionFactory = sessionFactory;
        _logger = logger;
    }

    public void Dispose()
    {
        try
        {
            if (_session == null) return;
            if (_transaction == null || !_transaction.IsActive) return;
            _transaction.Commit();
            _transaction.Dispose();
        }
        catch (Exception exception)
        {
            if (_transaction != null)
            {
                _transaction.Rollback();
                _transaction.Dispose();
            }

            _logger.Error("Something bad just happend");
        }
        finally
        {
            if (_session != null) _session.Dispose();
        }
    }

    public ISession GetSession()
    {
        if (CurrentSessionContext.HasBind(_sessionFactory))
        {
            _session = CurrentSessionContext.Unbind(_sessionFactory);
        }
        else
        {
            _session = _sessionFactory.OpenSession();
            CurrentSessionContext.Bind(_session);
        }

        // Let's make sure we have a transaction 
        _transaction = _session.BeginTransaction(IsolationLevel.ReadCommitted);
        return _session;
    }
}

This will be injected into the service via constructor and when I need an ISession I simply call GetSession. When the SessionManager Is disposed the transaction will be commited or rolledback depending on what happens.

This all works except I have no idea where to stash the interface and the implementation for this. It should not stay in Infrastructure because the services layer depends on it and it is a layer above. (This is bad according to Onion Standards).

I can't put the interface in Core because I would need to have a dependency on Nhibernate.. So not sure what the hell to do here. I was thinking of making a common / shared layer and have it act as a middleman, not sure that is the correct way to go about things though.

Any help would be greatly appreciated.

有帮助吗?

解决方案

In Onion Architecture, outer layers implement interfaces.

My advice: design your Domain Service interfaces so that they are convenient to use from your application. Use your ISessionManager inside your domain service implementations. Since your implementations are at the outer layer, your dependency on ISessionManager (and consequently NHibernate) is also at your outer layer.

For my part, I tend to use a generic repository over NHibernate, but that decision is still an implementation detail of my Domain Services.

If my domain service interface looks like:

IWidgetService.MakeWidget(MakeWidgetParameters)

My implementation will open an ISession and do the work of making and persisting the changes I want to the Db. In this way, ISession will not leak into the outer layers.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top