2

In our company we have a relatively long history of database backed applications, but have only just begun experimenting with dependency injection. I am looking for advice about how to convert our existing data access pattern into one more suited for dependency injection.

Some specific questions:

Do you create one access object per table (Given that a table represents an entity collection)? One interface per table? All of these would need the low level Data Access object to be injected, right?
What about if there are dozens of tables, wouldn't that make the composition root into a nightmare?

Would you instead have a single interface that defines things like GetCustomer(), GetOrder(), etc?

If I took the example of EntityFramework, then I would have one Container that exposes an object for each table, but that container doesn't conform to any interface itself, so doesn't seem like it's compatible with DI.

What we do now, in case it helps:

The way we normally manage data access is through a generic data layer which exposes CRUD/Transaction capabilities and has provider specific subclasses which handle the creation of IDbConnection, IDbCommand, etc.

Actual table access uses Table classes that perform the CRUD operations associated with a particular table and accept/return domain objects that the rest of the system deals with. These table classes expose only static methods, and utilise a static DataAccess singleton instantiated from a config file.

5
  • 3
    What is your goal for using DI? Do you want to create automatic tests for your business logic, decoupled from your database? And does your business logic live an a BL? If that's the case, you have to use DI for your BL, not for you data objects. So maybe its best to start using DI with the repository pattern (martinfowler.com/eaaCatalog/repository.html)?
    – Doc Brown
    Apr 8, 2014 at 13:14
  • You're right in that we are mostly taking advantage of DI for its effect on the business layer, and we already have a fairly stable interface between the two. At the moment, though, there is conflict between the BL which is all instance based, and the data layer, which is all static. The mixture between DI and what is essentially a service locator seems messy.
    – IanAWP
    Apr 9, 2014 at 7:09
  • 1
    I have still trouble to understand what your problem is - currently its seems you have a solution ("DI") and you are now looking for the problem to solve with that solution. But what is the actual problem you want to solve? Can you give a more specific example? The question how to apply DI (or if DI is really the best solution for your problem) can only be answered if we know what you want to achieve.
    – Doc Brown
    Apr 9, 2014 at 7:31
  • Maybe you're right. We currently create wrapper class(es) for the DL which implement an interface, and which can be injected into the BL. The problem I see is that Consumers of the wrapper have to know to set up the underlying static classes before using the wrapper and this is causing problems. Also, when integrating other code we have found that multiple regions of code set the static properties to different values, which causes problems. Moving to an instance based Data access layer seems like a solution to that problem, but even when it's instance based it doesn't have to be DI.
    – IanAWP
    Apr 9, 2014 at 9:08
  • Thanks, that's much clearer now. I think what you should read is the unit-of-work pattern (martinfowler.com/eaaCatalog/unitOfWork.html) and the repository pattern (link above). You define repositories for separate parts of your BL and inject them using a repository interface. Your repository will do the data access, using whatever kind of DL you want to encapsulate. Initialization can be part of the ctor of your repository, but there is no need to create "one interface per table" - the granularity of your repo should fit to the requirements of your BL objects.
    – Doc Brown
    Apr 9, 2014 at 11:17

1 Answer 1

1

I typically prefer to see interfaces (and injections) that describe actions that can be performed on the domain rather than just raw access into data. For example, I'd rather see a Customer interface that gives access to customer data without revealing the underlying data structure instead of just providing CRUD operations.

But then again, it depends on what level of abstraction you're at. At some point, you do need to access the lower-level CRUD operations. And yes, you may want to be able to inject the actual objects that interact with the database.

When I used Entity Framework 4 for a previous project, we had some test limitations so we moved all the code for the actual database queries into "thin" classes that had no conditional logic. So we ended up relying on the EF contract objects directly and didn't inject them. Instead we injected an abstraction which worked on those objects.

So... for your scenario, you might try creating some "wrapper" classes which provide the interface you want to expose via injection. Or it's also possible to edit the EF code generation to do this for you (though I've forgotten how to do it...)

2
  • I think part of my problem here is not knowing how to evaluate what a good DI implementation looks like. Are large projects pretty much guaranteed to have complicated composition roots, and unwieldy constructors?
    – IanAWP
    Apr 8, 2014 at 6:27
  • Good point. And it reminds me that we have to separate the concept of DI and IoC from implementations (such as Unity for .NET, Spring for Java, etc.). Martin Fowler has a really good article that covers the basic concepts. So I'd say: no, it doesn't have to be complicated... but inasmuch as keeping software clean is hard it will take some effort.
    – Allan
    Apr 9, 2014 at 14:47

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.