0

Trying to figure out how to keep class methods clean, follow EF's guidance of short-lived DbContexts, and use DI in WPF. Issue I'm having is implementing transactions with DI. I'm trying to figure out what the best way of handling this:

public class Repository : IRepository
{
    public Repository(MyDbContext dataContext) { /* blah */ }

    public void Add(BLLEntity entity) { /* blah */ }

    public void GetById(int id) { /* return entity */ }
}

public class NonTransactionalAppService
{
    public AppService(IRepository repo) { /* blah */ }

    public AddNewAccount(Account account)  // Issue: Not transactional
    {
        // do some stuff....
        repo.Add(account);
    }
}

public class TransactionalAppService
{
    public TransactionalAppService(IRepositoryFactory repoFactory, DbContextFactory factory) { /* blah */ }

    public AddNewAccount(Account account)  // Issue: Transactional, but odd?? And requires me to create the repositories with every call.
    {
        using (var db = factory.Create()
        {
            IRepo repo = repoFactory.Create(db);
            repo.Add(account);
        }
    }
}

So how do I handle transactions, keep DI for better unit-testing, and inject only what's needed without injecting factories everywhere?

This is for a desktop WPF app and I do not want to use a DI framework.

EF has guidance to use one DbContext per form, but how would I handle that with the Composition Root? I would assume I would need some type of FormFactory that would create a form and inject all the required dependencies to include the DbContext.

9
  • Change Repository to take ContextFactory as dependency instead of DbContext, then repository will create context whenever it need and as much as required Commented Apr 11, 2018 at 2:36
  • Are you basically asking how to handle Unit of Work? It looks to me you need to abstract the context out and pass that around like what Fabio says. Not sure what you are asking exactly. Commented Apr 11, 2018 at 5:56
  • @Fabio, this doesn’t allow me to use transaction then. So I can’t do batch updates and rollbacks when multiple repositories are involved. For example let’s say a new account needs to be added. The could involved a row being added to multiple tables. Therefore multiple repositories are involved. If the transaction fails then I don’t want to leave any of the tables in an inconsistent state. I used to use a context factory in the repository and it worked okay, not the best. Commented Apr 11, 2018 at 10:58
  • @Sentinel, I don’t think abstracting away the Context into a UnitOfWork will necessarily solve my issue. I want to use DI with a new context per form or per transaction. The service layer (an application service) should be responsible to handle a transaction. But right now I’m having trouble handling transactions and injecting contexts into the repository using constructor injection. Commented Apr 11, 2018 at 11:00
  • Why you cannot gather all required data and pass it to one repository method, which will save data to multiply tables with one context and one call of SaveChanges()? Commented Apr 11, 2018 at 11:27

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.