Condivisione del repository principale e della logica di mappatura degli oggetti tra i metodi dell'unità di lavoro

0

Mi chiedo se c'è un modo migliore per farlo o se sto facendo un po 'di anti-pattern qui. Come ho detto nell'argomento, sto cercando di condividere le chiamate al repository e la logica di mappatura degli oggetti tra i metodi dell'Unità di lavoro.

Ad esempio, vedi il mio metodo GetEnvelopeBody() utilizzato più di una volta.

public class EnvelopeService
{
    private EnvelopeRepository envelopeRepository;
    private RecipientRepository recipientRepository;
    private RecipientTabRepository recipientTabRepository;

    public Envelope GetEnvelope(int id)
    {
        using (var uow = UnitOfWorkFactory.Create())
        {
            envelopeRepository = new EnvelopeRepository(uow);
            recipientRepository = new RecipientRepository(uow);
            recipientTabRepository = new RecipientTabRepository(uow);

            // I'm extracting the repository calls and mapping 
            // code into this GetEnvelopeBody() so other methods 
            // that have their own Unit of Work can use it.
            // This is to avoid multiple Unit of Work sessions? 
            // from colliding.
            var envelope = GetEnvelopeBody(id);

            uow.SaveChanges();

            return envelope;
        }
    }

    private Envelope GetEnvelopeBody(int id)
    {
        // repository calls and object mapping code goes here
    }

    public void SaveEnvelope(Envelope envelope)
    {
        using (var uow = UnitOfWorkFactory.Create())
        {
            envelopeRepository = new EnvelopeRepository(uow);
            recipientRepository = new RecipientRepository(uow);
            recipientTabRepository = new RecipientTabRepository(uow);

            SaveEnvelopeBody(envelope);

            uow.SaveChanges();
        }
    }

    private void SaveEnvelopeBody(Envelope envelope)
    {
        CleanEnvelope(envelope);

        // repository calls and object mapping code goes here
    }

    private void CleanEnvelope(Envelope newEnvelope)
    {
        var oldEnvelope = this.GetEnvelopeBody(newEnvelope.Id);
        // Do other fancy stuff ...
    }
}
    
posta programmer 29.04.2015 - 22:23
fonte

1 risposta

1

Il problema principale che vedo è che la tua classe EnvelopeService non è threadsafe.

Immagina due thread usando una singola istanza di EnvelopeService . Il thread 1 chiama GetEnvelope che crea un UnitOfWork . Allo stesso tempo Thread 2 chiama SaveEnvelope che crea un secondo UnitOfWork . Non è garantito se queste due operazioni vengano eseguite utilizzando il UnitOfWork appropriato.

Questo perché stai effettivamente memorizzando il tuo UnitOfWork a livello di classe (nelle tue 3 istanze del repository) e quindi utilizzandolo nelle chiamate di metodo helper successive. Questo è uno stato condiviso ed è pericoloso.

Un approccio più sicuro sarebbe rimuovere lo stato condiviso:

public class EnvelopeService
{
        public Envelope GetEnvelope(int id)
        {
                using (var uow = UnitOfWorkFactory.Create())
                {
                        var envelopeRepository = new EnvelopeRepository(uow);
                        var recipientRepository = new RecipientRepository(uow);
                        var recipientTabRepository = new RecipientTabRepository(uow);

                        var envelope = GetEnvelopeBody(id, envelopeRepository, recipientRepository, recipientTabRepository);

                        uow.SaveChanges();

                        return envelope;
                }
        }

        private Envelope GetEnvelopeBody(
            int id,
            EnvelopeRepository envelopeRepository,
            RecipientRepository recipientRepository,
            RecipientTabRepository recipientTabRepository)
        {
                // repository calls and object mapping code goes here
        }

        public void SaveEnvelope(Envelope envelope)
        {
                using (var uow = UnitOfWorkFactory.Create())
                {
                        var envelopeRepository = new EnvelopeRepository(uow);
                        var recipientRepository = new RecipientRepository(uow);
                        var recipientTabRepository = new RecipientTabRepository(uow);

                        SaveEnvelopeBody(envelope, envelopeRepository, recipientRepository, recipientTabRepository);

                        uow.SaveChanges();
                }
        }

        private void SaveEnvelopeBody(
            Envelope envelope,
            EnvelopeRepository envelopeRepository,
            RecipientRepository recipientRepository,
            RecipientTabRepository recipientTabRepository)
        {
                CleanEnvelope(envelope, envelopeRepository, recipientRepository, recipientTabRepository);

                // repository calls and object mapping code goes here
        }

        private void CleanEnvelope(
            Envelope newEnvelope,
            EnvelopeRepository envelopeRepository,
            RecipientRepository recipientRepository,
            RecipientTabRepository recipientTabRepository)
        {
                var oldEnvelope = this.GetEnvelopeBody(newEnvelope.Id, envelopeRepository, recipientRepository, recipientTabRepository);
                // Do other fancy stuff ...
        }
}

Tieni presente che i repository che contengono il tuo UnitOfWork vengono ora passati ai tuoi metodi di supporto come dipendenze.

Il fatto che tu debba essere new dei tuoi repository è un altro potenziale motivo di preoccupazione. Potrebbe rendere difficile il test della classe EnvelopeService . Prendi in considerazione l'utilizzo di Factory per ottenere invece le istanze del repository. Poi di nuovo, potrebbe essere eccessivo. Dipende davvero dalla tua situazione.

    
risposta data 30.04.2015 - 13:03
fonte

Leggi altre domande sui tag