How should I implement my Repository (DDD) in C# to handle multiple calls for the same Aggregate Root
Asked Answered
G

3

6

What class in my project should responsible for keeping track of which Aggregate Roots have already been created so as not to create two instances for the same Entity. Should my repository keep a list of all aggregates it has created? If yes, how do i do that? Do I use a singleton repository (doesn't sound right to me)? Would another options be to encapsulate this "caching" somewhere else is some other class? What would this class look like and in what pattern would it fit?

I'm not using an O/R mapper, so if there is a technology out there that handles it, i'd need to know how it does it (as in what pattern it uses) to be able to use it

Thanks!

Gristle answered 8/2, 2011 at 21:0 Comment(0)
C
3

I believe you are thinking about the Identity Map pattern, as described by Martin Fowler.

In his full description of the pattern (in his book), Fowler discusses implementation concerns for read/write entities (those that participate in transactions) and read-only (reference data, which ideally should be read only once and subsequently cached in memory).

I suggest obtaining his excellent book, but the excerpt describing this pattern is readable on Google Books (look for "fowler identity map").

Basically, an identity map is an object that stores, for example in a hashtable, the entity objects loaded from the database. The map itself is stored in the context of the current session (request), preferably in a Unit of Work (for read/write entities). For read-only entities, the map need not be tied to the session and may be stored in the context of the process (global state).

Cahan answered 8/2, 2011 at 23:54 Comment(1)
I do own that book. I'll have a look at Identity map to see if it fits. ThanksGristle
A
1

I consider caching to be something that happens at the Service level, rather than in a repository. Repositories should be "dumb" and just do basic CRUD operations. Services can be smart enough to work with caching as necessary (which is probably more of a business rule than a low-level data access rule).

To put it simply, I don't let any code use Repositories directly - only Services can do that. Then everything else consumes the relevant services as interfaces. That gives you a nice wrapper for putting in biz logic, caching, etc.

Adila answered 8/2, 2011 at 21:5 Comment(6)
So if two calls for the same Aggregate are made to the same instance of the repository, two seperate instances of the same Aggregate would be created and returned?Gristle
Yes, but those calls should be going through a Service that would cache the instance of the Aggregate if necessary. So in that case the Service would only call to the repository once, and just return from the cache on the second request.Adila
but also see this question - https://mcmap.net/q/350197/-repository-pattern-caching - some people have a different opinion. I like to treat caching as a form of business concern so that my repositories have very few dependencies, but not everyone views it that way.Adila
and this one too :) - #103413Adila
Thanks, i'm thinking about this idea. To me though, its not really caching (i suppose technically it is). It's more to make sure that there is only one instance of each aggregate root. I guess i never really thought about this as a caching responsibility but more of a reconstitution responsibility, which is why i thought of putting it in the RepositoryGristle
Sure - we actually use LINQ to SQL under the hood and it handles the only-one-instance issue for us in that regard. I suspect other ORMs do the same thing for you. If you want to avoid using an ORM and just replicate that pattern of persisting one instance, here's a high-level on what L2S does: msdn.microsoft.com/en-us/library/bb399376.aspx Basically, just keep a dictionary or similar lookup based on a primary key and check that before building an object from scratch. Is there a reason you can't use an ORM?Adila
R
0

I would say, if this "caching" managed anywhere other than the Repository then you are letting concerns leak out.

The repository is your collection of items. No code consuming the repository should have to decide whether to retrieve the object from the repository or from somewhere else.

Singleton sounds like the wrong lifetime; it likely should be per-request. This is easy to manage if you are using an IoC/DI container.

It seems like the fact that you even have consider multiple calls for the same aggregate evidences a architecture/design problem. I would be interested to hear an example of what those first and second calls might be, and why they require the same exact instance of your AR.

Raptorial answered 8/2, 2011 at 23:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.