0

I have an entity A which has three children entities X, Y and Z.

I have also a generic repository one of those floating around the web...

In my Service method AXYZ()

I do multiple repositories calls: (pseudo code)

repoA.Update(objectA);
repoY.Delete(objectA.PK_Id);

foreach:
  objectX.FK_ID = objectA.PK_ID;
  repoX.Add(objectX);

foreach:
  objectY.FK_ID = objectA.PK_ID;
  repoY.Add(objectY);

foreach:
  objectZ.FK_ID = objectA.PK_ID;
  repoZ.Add(objectZ);

  _unitOfWork.Commit();

Now I asked myself, should it not be enough or better to do all foreach.Add operations not on the repoXXX just instead do the Add operation on the children collections?:

repoA.Update(objectA);
repoY.Delete(objectA.Id);

foreach:
  objectA.CollectionX.Add(objectX);
  objectA.CollectionY.Add(objectY);
  objectA.CollectionZ.Add(objectZ);

  _unitOfWork.Commit();

A sidenote:

The Delete operation on repoY could not be done inmemory as the objects_Y are not loaded into the context.

What do you think?

I tagged this question also with domain driven design maybe this scenario has something to do with it?

Elisabeth
  • 20,496
  • 52
  • 200
  • 321

1 Answers1

0

If you're actually approaching this from a DDD perspective, then it's concerning to me that you have repositories for all the child entities and not just for the aggregate root, A. Obviously, every project is different, and DDD is a set of guidelines that usually make sense. However, I would expect that repoA handles loading and persisting all four entities, unless X, Y, and Z have roles to play as aggregate roots. RepositoryA could handle loading and persisting X, Y, and Z objects from various sources if they aren't all stored in one record, but I wouldn't expect separate repositories.

Aside from canonical DDD correctness, I encourage you to consider how these relationships work in your domain layer. The foreach approach implies using setters, whereas the collection addition implies business objects establishing relationships in a way that can be expressed in the Ubiquitous Language.

I think your latter approach is more "correct", but I would alter it slightly:

repoA.Update(objectA);
repoY.Delete(objectA.Id);

foreach:
  objectA.addX(objectX);
  objectA.addY(objectY);
  objectA.addZ(objectZ);

  _unitOfWork.Commit();

Operations that alter child entities are typically exposed on the aggregate root itself, since it knows how to maintain the invariants it requires.

Hopefully that helps. However, I don't know your entire situation. It would help to understand a little more about what AXYZ() is doing.

Steven Hood
  • 678
  • 5
  • 18
  • The AXYZ() method has no own logic except that it is grouping repository calls within a business transaction. I agree with most of your comments. But one problem/concern I see. When I would follow strictly the DDD approach then my objectA should have a objectA.DeleteY(ObjectY). The CollectionOfObjectY is fetched via a FetchById method of my GenericRepository. The below DeleteY method is then also called in a foreach like the addXXX methods. What do you think? – Elisabeth Apr 02 '13 at 18:54