3

I'm pretty new to the concept. What I'm trying to do is create a factory that will return an object that is used for repository functions. No problems there. So I create the instance of a concrete factory in main() and store it in a static property of App but my entities are in a separate dll. Does it make sense to pass the repository to each entity class in the constructor? This doesn't feel right. My question is: how is the best make my entities aware of which repository they should be using?

My App partial class looks like

public partial class App : Application
{
 private static ICalDataAccess _daqFactory;

 public static ICalDataAccess DataAccessFactory
 {
   set { _daqFactory = value; }
   get { return _daqFactory; }
 }
}

Maybe a little more code is in order.

public class Widget
{
    public string Description { get; set; }
    public int ID { get; set; }

    private IWidgetRepository _widgetRepository;
    public Widget(IWidgetRepository WidgetRepository)
    {
        _widgetRepository = WidgetRepository;
    }

    public void Save()
    {
        _widgetRepository.Save(this);
    }
}

Am I doing anything egregious here?

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
cdaq
  • 167
  • 1
  • 9
  • 2
    Why would you want to make your entities aware of your repository? Shouldnt it be the other way around? – Euphoric Mar 30 '11 at 19:31
  • Same question. Normally you would want to solve this through a better design. – Adi Mar 30 '11 at 19:35
  • Well, so that I can do something like _widget.Save(). Seems simpler and cleaner than Factory.WidgetRepository.Save(_widget). The problem is that widget would need a concrete instance if IWidgetRepository in it's constructor. Am I way off base here? – cdaq Mar 30 '11 at 19:49
  • Related: http://stackoverflow.com/questions/4835046/why-not-use-an-ioc-container-to-resolve-dependencies-for-entities-business-object – Mark Seemann Mar 30 '11 at 21:06
  • Wanted to pose another question: How can you cleanly implement lazy loading (assuming we're NOT going to use DDD) without passing the repository to the entity? Example: A team contains a list of players that contain their own composite data. If the entity were not aware of the repository, you would end up with an awkwardly verbose repository. ie TeamRepository.GetPlayers(aTeam); And worse, the client would need to know the intricacies of this system. – cdaq Apr 06 '11 at 19:07

2 Answers2

3

I think the general recommendation is to keep your entities free from persistence concerns. That is, you have some code that retrieves the entities and uses them to perform whatever work needs to be done, resulting in new, deleted or modified entities, which the calling code then submits to the appropriate repository (or asks to be saved if you have something which tracks or detects modified entities, like EF or NHibernate).

That way your entities do not need to know about repositories at all.

I usually create a UnitOfWork helper class which exposes all of my repositories through a "public RepositoryFactory Repositories { get; }" property, so that simply by supplying an instance of the UnitOfWork class I have access to all of my data sources. UnitOfWork can then be injected via IoC to whatever class needs to have data access.

Some recommended reading on this topic:

Morten Mertner
  • 9,414
  • 4
  • 39
  • 56
  • "I think the general recommendation is to keep your entities free from persistence concerns." Why? can't the entity saves itself via an interface? – cdaq Mar 30 '11 at 19:51
  • 3
    They could, in theory. It works fine for really simple scenarios, but quickly becomes hard to manage when what you need to do modifies several entities. Suddenly you need multiple repositories inside a single class or references to other entities. This orchestration is usually much easier to manage from outside the entities, which results in a cleaner domain model that is easier to maintain. – Morten Mertner Mar 30 '11 at 20:03
  • hmmm, can you give me an example? I can't imagine a single entity needing to modify lots of other entities. If it does, this would certainly be handled by another class. In the system I'm working on now, the repositories really only perform crud operations on the domain objects. – cdaq Mar 30 '11 at 20:15
  • 1
    Say you add an Address to a Customer, but that you also have Companies with Addresses. Do you save the address independently of the owning entity or provide both customers and companies with access to the AddressRepository? Who validates that the address is valid, if for instance Customers may only use addresses that belong to a specific set of companies? Who controls transaction boundaries when you need to save multiple entities? When every entity simply saves itself, it has no knowledge of whether it is part of something bigger. All these "cross-entity concerns" are problematic. – Morten Mertner Mar 30 '11 at 20:34
  • I hope I'm not coming off as argumentative, I'm really trying to learn. I would think the customer would validate that it's address is valid or pass itself to some other business rule class, and then pass itself to the save method of the repository. The save method would probably flatten the object and then call a sproc to actually perform the save. – cdaq Mar 30 '11 at 20:44
  • Thank you for the links, looks like just what I need – cdaq Mar 30 '11 at 20:49
0

Your description sounds more like the service locator pattern than dependency injection. Dependency injection typically looks like any object that needs some service object (such as data access) to do its work receives that service as parameter to its constructor.

Jim Bolla
  • 8,265
  • 36
  • 54
  • I think this is what I'm proposing. An object needs to update itself, so it receives a data access object in its constructor that facilitates the functionality. – cdaq Mar 30 '11 at 19:54