I have product repository. And I want to use redis as cache. And I create cache repo.
When I want to get product. First I go cache repo if not exist I query main database . If product exists in There. I write to cache and return.
Option 1) I get cache repository in product repository via DI and use in there.
Option 2) I get cache repository in application layer in command handler with product repository and I use both separetly
It seems to me that you are driven by technical requirements (i.e usage of Redis) and not business requirement (i.e why do you need caching ? performance issue, latency ?).
But, to sum up a great post from another thread in SO: Which layer should I implement caching of lookup data from database in a DDD application?, you have the following options:
Manage the cache in the Application layer, directly in the Application Service. This way, you have full control whether you want to to use the cache or not for such query/command
Hide the cache in the repository. But here every clients of your repository will use the cache, and that is something maybe you want to have control over.
Either way, one of the most common approach is to use the pattern proxy, where the method call will be intercepted first by the proxy, whom role is to send data from the cache if it already have the data. Otherwise delegate the call to the original object.
Related
I am using the Azure API for FHIR service, and I would like to generate a resource with an Id I create on my side. Looking at the docs, it looks like you are supposed to be able to do a PUT request to /, but it doesn't seem to be working. If I do a POST to / and specify my Id, it gets ignored.
In the future, I want it to be able to generate the Ids, but for the "Importing Legacy Data" phase, I want to be able to specify my own Ids to make the linking side of things easier.
Any ideas?
Update
The problem I am trying to avoid is having to push all the data to the FHIR Endpoint and then go over everything again to create the links.
If the server allows an upsert, you would do the PUT to '/[ResourceType]/[id]', not to just '/'.
For example, if you have a Patient with technical id '123', you could do:
PUT [base]/Patient/123
Make sure the Patient resource has its 'id' field set to '123' inside the resource as well. It has to match the id you put on the url.
Another option would be to construct a transaction Bundle, where you can make entries for each resource you want to upsert. You would use the PUT verb and '[ResourceType]/[id]' again for the entry.request details. After constructing the Bundle, you can send it with a POST to the base, so the server knows to process this as a transaction.
Transaction Bundles are also very useful if you have a bunch of resources that are related and reference each other, since the server is required to update all references for new resources inside the Bundle. See http://hl7.org/fhir/http.html#trules for more information about that. Note that not all servers support transactions, just like not all servers allow upserts as Lloyd mentions in his answer.
Servers are not required to allow external systems to assign ids. Many servers won't support 'upsert' as it risks id collisions. Those that do will typically only enable it in certain circumstances. E.g. all ids are required to be UUIDs, so collisions aren't possible; there's only one source and it's synchronizing with the target system, so it 'owns' the id and there can't be collisions.
Some servers may have a configuration ability to turn on 'upsert' capability if it's been determined to be safe to do.
I've been reading a book Domain-Driven Design Quickly.
Now I've reached the Repository Pattern.
I am not sure what are they referring by mentioning the "Client"?
What does "Client" mean here?
Databases are part of the infrastructure. A poor solution is for
the client to be aware of the details needed to access a database.
For example, the client has to create SQL queries to retrieve the
desired data. The database query may return a set of records,
exposing even more of its internal details. When many clients
have to create objects directly from the database, it turns out that such code is scattered throughout the entire domain.
Client of a repository is a piece of code (another class), usually application layer in context of DDD/Onion Architecture. The rule of a thumb says: 1 repository per Aggregate Root. If your Aggregate Root is Order, which has a collection of OrderItem inside, you create only OrderRepository and return back the whole Order with ALL OrderItems, no Lazy Loading. Now, your client, (application layer code) should have no idea what is inside repository, (is it file based, sql based, http based) you treat it as inmemory collection: repository.GetById(orderId) where repository is IOrderRepository. That would mean you can easily change your repo from in Memory to sql and back anytime and your client code (application layer) or whatever class which uses repository will not be affected hence Liskov Substitution principle is preserved.
Need to add global variable in REDIS Cache.
For Ex:
Consider an student, employee and Staff related application.
Every role has a unique object. When student log in to the application we need to get student information from redis. Same for other roles log in too.
If we store all the details at time of application initialization, we no need to send request to get role related details. If we store it into session, that data will be checking by every users login. And also session id has been varied for every users.
Is it possible?
If yes, How can we store the values at the time of application initialization?
First of all, since Redis is a cache, you are storing objects that may be evicted with time. When Redis becomes full, it will start clearing objects according to your eviction policy configuration.
Probably caching everything upon initialization is not the best course of action, I'd go with caching the objects when they are first requested, if they don't exist on Redis, store them for future retrievals. This way, if your Redis instance clears that object, your application logic will always find it (from cache or from local storage). That's called a Cache-Aside Pattern.
Your initialization logic varies depending on which technology / platform are you using.
ASP.NET MVC 5 or lower has the Global.asax file, ASP.NET 5 MVC6 has the Startup.cs file.
I model a User as an aggregate root and a User is composed of an Identifier value object as well as an Email value object. Both value objects can uniquely identify a User, however the email is allowed to change and the identifier cannot.
In most examples of DDD I have seen, a repository for an aggregate root only fetches by identifier. Would it be correct to add another method that fetches by email to the repository? Am I modeling this poorly?
I would say yes, it is appropriate for a repository to have methods for retrieving aggregates by something other than the identity. However, there are some subtleties to be aware of.
The reason that many repository examples only retrieve by ID is based on the observation that repositories coupled with the structure of aggregates cannot fulfill all query requirements. For instance, if you have a query which calls for some fields from an aggregate as well as some fields for a referenced aggregate and some summary data, the corresponding aggregate classes cannot be used to represent this data. Instead, a dedicated read-model is needed. Therefore, querying responsibilities are decoupled from the repository. This have several advantages (queries can be served by a dedicated de-normalized store) and it is the principal paradigm of CQRS. In this type of architecture, domain classes are only retrieved by the repository when some behavior needs to execute. All read-only use cases are served by a read-models.
The reason that I think it appropriate for a repository to have a GetByEmail method is based on YAGNI and battling complexity. You an allow your application to evolve as requirements change and grow. You don't need to jump to CQRS and separate read/write stores right away. You can start with a repository that also happens to have a query method. The only thing to keep in mind is that you should try to retrieve entities by ID when you need to invoke some behavior on those entities.
I would put this functionality into a service / business layer that is specific to your User object. Not every object is going to have an Email identifier. This seems more like business logic than the responsibility of the repository. I am sure you already know this, but here is good explanation of what I am talking about.
I would not recommend this, but you could have a specific implementation of your repository for a User that exposes a GetByEmail(string emailAddress) method, but I still like the service idea.
I agree with what eulerfx has answered:
You need to ask yourself why you need to get the AR using something
other than the ID.
I think it would be rather obvious that you do not have the ID but you do have some other unique identifier such as the e-mail address.
If you go with CQRS you need to first determine whether the data is important to the domain or only to the query store. If you require the data to be 100% consistent then it changes things slightly. You would, for instance, need 100% consistency if you are checking whether an e-mail address exists in order to satisfy the unique constraint. If the queried data is at any time stale you will probably run into problems.
Remember that a repository represents a collection of sorts. So if you do not need to actually operate on the AR (command side) but you have decided that where you are using your domain is appropriate then you could always go for a ContainsEMailAddress on the repository; else you could have a query side for your domain data store also since your domain data store (OLTP type store) is 100% consistent whereas your query store (OLAP type store) may only be eventually consistent, as is typical of CQRS with a separate query store.
In most examples of DDD I have seen, a repository for an aggregate
root only fetches by identifier.
I'd be curious to know what examples you've looked at. According to the DDD definition, a Repository is
A mechanism for encapsulating storage, retrieval, and search behavior
which emulates a collection of objects.
Search obviously includes getting a root or a collection of roots by all sorts of criteria, not only their ID's.
Repository is a perfect place for GetCustomerByEmail(), GetCustomersOver18(), GetCustomersByCountry(...) and so on.
Would it be correct to add another method that fetches by email to the repository? - I would not do that. In my opinion a repository should have only methods for getting by id, save and delete.
I'd rather ask why you don't have user id in the command handler in which you want to fetch the user and call a domain method on it. I don't know what exactly you are doing, but for the login/register scenario, I would do following. When a user logs in, he passes an email address and a password, and you do a query to authenticate the user - this would not use domain or repository (that is just for commands), but would use some query implementation which would return some UserDto which would contain user id, from this point you have the user id. Next scenario is registration. The command handler to create a new user would create a new user entity, then the user needs to log in.
I have a design question which I think Domain events will solve but I need to make sure I am going about it the correct way and that I understand Domain events correctly.
I have a change in one aggregate root which needs to make a change in the another aggregate root.
So when I make a change in my initiating aggregate root I will fire a domain event which will apply the change in the other aggregate root. If all goes well I have two database transactions which will be persisted.
Now if one fails (say the second), how do I resolve this or if the second goes through but my initiating change fails to persist?
I am assuming this is a single user system where everything happens synchronously so the second aggregate is committed before the first initiating aggregate.
JD
It depends on how you have organized Unit of Work management in your application. In web app Unit of Work should be created every request and in this case you usually have one transaction within http request, which will be committed or rolled back after end of request.
Of course you can create two separate transaction, but I do not recommend to do it inside your web app. In this case (if I would have such requirements) would rather use messaging architecture (take a look at http://www.nservicebus.com/ or http://masstransit-project.com/)