Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UnitOfWork Implementation

Ive been able to implement a little cool unit of work to work with entity framework.

I came up with ..

public class UnitOfWork : IUnitOfWork
    {
        private Database _database;
        private IDatabaseFactory _databaseFactory;

        private DbTransaction transaction;

        public UnitOfWork(IDatabaseFactory databaseFactory)
        {
            _databaseFactory = databaseFactory;
            _database = Database;

            transaction = _database.Database.Connection.BeginTransaction();
        }

        public Database Database
        {
            get { return _database ?? (_database = _databaseFactory.Get()); }
        }

        public void Dispose()
        {
            try
            {
                _database.SaveChanges();
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
            }
        }
    }

I am pretty sure everyone is jealous of this unit of work now. (Kidding)

But i have a little design problem in this service layer.

public class JournalService : IJournalService
    {
        IJournalRepository _journalRepository;

        public JournalService(IJournalRepository journalRepository)
        { 
            _journalRepository = journalRepository;
        }

        public void AjouterJournal(Journal j)
        {
           [B]using (IUnitOfWork uow = new UnitOfWork())[/B]
            {
                var journal = new Journal();
                journalRepository.AddJournal(journal);

            }
        }
    }

The problem is the unit of work need a database injection so i cant create an instance of it. I can't provide an unit of work directly in the service layer because it would make no sense since the unit of work need to be disposable.

And because i use repository to add my stuff there no need to access the unit of work directly, the saving will occur automaticly when it will be disposed anyway.

I could inject the IDatabaseFactory in my service layer but the idea is to not use it there. Actually the service layer shouldnt know about it.

How about an UnitOfWork factory ?

Any ideas or suggestion on how i can fix this?

Thanks.

like image 702
Rushino Avatar asked Feb 05 '11 15:02

Rushino


1 Answers

You should inject UnitOfWork into service if you want to use your current architecture. Your service will not have inner (hidden) dependency on UnitOfWork implementation and it will be better testable. It goes hand in hand with many principles of object oriented architecture.

Other thing is that this implementation is only usable for simple CRUD operations. In more complex services you will end up with composition of multiple operations (possibly from multipe services) which will each operate with UnitOfWork. Calling multiple SaveChanges (and transactions) in one business operation is probably not what you usually want - in such case you want to call SaveChanges only once from some top level service or from service's caller. Typical scenario is that single business operation has one unit of work with one transaction but you can do a lot of service's operations as part of this business operation.

Another implication is construction of your Repositories. They probably need access to Database, don't they? So you probably already inject UoW into repository constructor. If you do this you can avoid relation between UoW and basic services at all.

like image 127
Ladislav Mrnka Avatar answered Oct 12 '22 01:10

Ladislav Mrnka