1

i am using Entity Framework and repository with unit of work design pattern.

Sometimes with my unit of work, I am making other calls to a different service.

This service in turn is making its own unit of work instance, for example:

ISettingsService settingsService = UnityContainer.Resolve<ISettingService>();
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.CreateUnitOfWork())
{
    List<Company> companies = unitOfWork.CompaniesRepository.GetAll();
    foreach(Company company in companies)
    {
        settingsService.SaveSettings(company, "value to set");
        company.Processed = DateTime.UtcNow();
    }
    unitOfWork.Save();
}

// ISettingsService.SaveSettings code in another module...
ISettingsService.SaveSettings(Company company, string value)
{
    using (IUnitOfWork unitOfWork = UnitOfWorkFactory.CreateUnitOfWork())
    {
        Setting setting = new Setting();
        setting.CompanyID = company.CompanyID;
        setting.SettingValue = value;
        unitOfWork.Insert(setting);
        unitOfWork.Save();
    }
}

The above code does work, but i have to reference ID's explicitly rather than attaching the company object (it would throw an error as it is already being tracked by the other unit-of-work in the other service).

As far as I can tell I see 3 ways of this happening:

1) Use the code as-is with service layers creating their own unit-of-work instances, any other references to other entity's are done on a primary key basis (procedures to set values should be passed by primary key object value, i.e. int customerID).

The bad side to this is potentially more hits to the database, and if the entity primary key type changed, i would need to change all service layer references for the ID field. __

2) Have service layers accept entity objects as references. This would be nice as i could pass objects around.

The bad side to this is that entities must not be referenced from any other context and must be attached to context to where it will be used. In a loop, the entity will most probably already be attached. __

3) Pass in unit-of-work instantiations to other service layers to they can use the existing unit-of-work instead of instantiating their own.

Not sure there is a downside to this other than having to pass around a unit-of-work reference, the upside would be the ability to reference objects without having to attach them or worry if they are already attached. __

In summary, I need to standardize on one access design, and would appreciate recommendations on what one i should choose.

In addition is there anything with transactions that i need to be concerned about or is EntityFramework with the unit-of-work design pattern implementing a form of transactional processing implicitly as changed are only committed on context.Save(), or am i mistaken?

Thanks,

Chris

morleyc
  • 2,169
  • 10
  • 48
  • 108

1 Answers1

1

You have a few options amongst them:

  1. Have different services pass out dettached entities (its entities), perhaps even DTOs that are not entities, then have each service translate them to its entities (or use primary keys).

    Each service can create its own content and use its own EDMX or a shared EMDX (or even several EDMXs).

  2. If the services are using the same EDMX, then inject the same context into them (you can wrap it behind and interface so that they don't expose EF).

  3. If the services don't use the same EDMX, either:

    3.1. Go with option 1, using different entities for different services (or DTOs).

    You can "share" tables between the EDMXs using different entities or use views to "tables from external domains" to reflect a read-only version of tables to other domains.

    3.2. Create a master EDMX by merging the EDMXs into one big one (see this question for details)

Changes are applied only when calling context.AcceptChanges(), so you can save changes to multiple contexts, then accept changes in each after all the saves have completed.

Community
  • 1
  • 1
Danny Varod
  • 17,324
  • 5
  • 69
  • 111
  • Hi thanks for reply. Yes I am using code first so this is the same schema and same instance across all services.I am using unity, injecting a related unit of work would be perfect, but I am unsure how to do this as dependencies are injected in each service layer constructor- is it possible to inject an object when resolving an interface? – morleyc Jun 05 '12 at 20:07
  • 1
    I am not familiar enough with Unity to answer that. Try asking another question with a [tag:Unity] tag. I suspect, however, that all dependency injection frameworks can do anything if configured enough. – Danny Varod Jun 05 '12 at 21:03