Riferimenti all'interfaccia dominio NHibernate?

1

Vedi la domanda qui, che ho chiesto ieri: Dominio guidato Progetta in un'architettura di cipolla

Come affermato, comprendo che DDD è un approccio che ha come target solo il livello del dominio e Onion è un'architettura per l'intero sistema, ovvero core, infrastruttura ecc.

Onion suggerisce che tutte le interfacce dell'applicazione debbano essere contenute nel livello dominio come descritto qui: link e anche descritto nella mia domanda di ieri.

Ora vedi l'interfaccia dell'Unità di lavoro qui: link . Ecco un estratto del codice:

 public ISession Session { get; private set; }

    public UnitOfWork(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
        Session = _sessionFactory.OpenSession();
    }

Quindi devo creare un'interfaccia UOW che abbia un riferimento a Session e un riferimento a SessionFactory. Pertanto devo installare NHibernate nel livello del dominio, che sembra essere un grande no no.

Che cosa posso fare in questo scenario? Si prega di non avvisarmi di non inserire l'interfaccia nel livello del dominio in quanto il livello del dominio contiene un servizio di dominio simile a questo: link (I servizi di dominio possono accedere al database tramite un repository in un servizio di dominio).

    
posta w0051977 20.10.2017 - 13:32
fonte

2 risposte

4

L'unità di lavoro è la transazione. La sfida è assicurarsi che le interfacce e le classi NHibernate non siano referenziate al di fuori del livello di accesso ai dati. L'interfaccia dell'unità di lavoro non dovrebbe avere riferimenti a NHibernate, ad esempio:

public interface IUnitOfWork : IDisposable
{
    void Begin();
    void Commit();
    void Rollback();
}

L'implementazione concreta di questa interfaccia potrebbe richiedere qualcosa da NHibernate, ad esempio:

public class UnitOfWork : IUnitOfWork
{
    private ISession session;
    private ITransaction transaction;

    public UnitOfWork(ISession session)
    {
        this.session = session ?? throw new ArgumentNullException(nameof(session));
    }

    public void Begin()
    {
        if (transaction != null)
            return;

        transaction = session.BeginTransaction();
    }

    public void Dispose()
    {
        Rollback();
    }

    public void Commit()
    {
        if (transaction == null)
            return;

        transaction.SaveChanges();
        transaction.Dispose();
        transaction = null;
    }

    public void Rollback()
    {
        if (transaction == null)
            return;

        transaction.DiscardChanges();
        transaction.Dispose();
        transaction = null;
    }
}

Gli unici riferimenti a NHibernate sono nel costruttore e nei campi privati. Un oggetto factory dovrà darti l'unità di lavoro, ma il tuo codice esterno non dovrebbe richiedere alcun riferimento a NHibernate.

using (IUnitOfWork uow = unitOfWorkFactory.Create())
{
    uow.Begin();
    // do stuff
    uow.Commit();
}

Nel codice sopra, nulla sta facendo riferimento a NHibernate.

Il modello Unità di lavoro ti dà il controllo della transazione mentre disaccoppia l'implementazione di quelle transazioni dal resto dell'applicazione.

    
risposta data 20.10.2017 - 18:00
fonte
2

Anche se hai detto di non farlo, ti dirò che il tuo uso di ISession è un dettaglio di implementazione e non dovrebbe essere esposto al livello del dominio.

Il dominio dovrebbe essere agnostico su come (o anche se) il tuo repository è fisicamente persistente. L'ISession, come dici tu, è un dettaglio dell'attrezzo specifico di NHibernate.

Quindi come risolvere? Bene, la tua interfaccia UoW dovrebbe solo esporre solo i metodi necessari per svolgere il suo lavoro, cose come Commit () e BeginTransaction (), a seconda della modalità che preferisci. Il modo in cui viene eseguito il commit potrebbe essere implementato da un ISession sotto il cofano, ma non esposto nell'interfaccia.

    
risposta data 20.10.2017 - 14:57
fonte

Leggi altre domande sui tag