English 中文(简体)
使用单一的命令和查询数据库,在清洁考古技术和 DDD 中填入复杂的查询
原标题:Where to imlement complex queries in Clean Architechture and DDD with a single database for commands and queries
I m trying to follow clean architecture principles, where I try to keep implementation details regarding persistence out of Application Core: The repository interfaces are in Application Core project The Application Core project does not reference any data access library (ORM) The Infrastracture project references ORM and implements the repositories (reference solution here) However, I struggle with db queries like: Give me open orders past due with customer details and total prices. because such queries contains some business logic (Order is considered Open when ....,. Past due is when....) often must be optimized for performance (e.g dont fetch order items, but sum of the order items price). I put OpenOrdersQuery dto in the Application Core layer, but where do I implement the handler for it? If I implement it in Infrastructure project I m putting some business logic there I can t implement it in Application Core, since there is no direct data access
问题回答
If I implement it in Infrastructure project I m putting some business logic there Not really. Your domain model is indeed responsible for Business Logic (from the command side) and if this leaks into Application / Infrastructure layers then that s a smell that should be addressed. However, you re now looking at the query side of CQRS. Ideally, you d have a database optimised for use-case handling (commands) and a database optimised for the read-side (query). But, in lieu of that, you can use the same database for write and reads. I often do this as first step and then migrate to a read-optimized warehouse when the performance demands it and/or I have the clarity of what queries might be executed to effectively design that read-side database. Even when using a single database for commands and queries, I will not use ORM for query execution. I will query the database directly with SQL. This avoids the problem you ve encountered where your repository method (designed for commands) are potentially retrieving related data that is not relevant to the query being executed. So, to summarise: Command Pipeline Client creates command Client sends command to command module, which finds the handler to execute the command Handler uses Domain Model (aka Command Model) to handle business logic for the command use case and may then add an entity using a repository interface. The infrastructure repository implementation will add the entity to the unit of work in the ORM. Query Pipeline Client creates a Query Client sends query to query module, which finds the handler to execute the query. Handler creates SQL statement , opens a connection to database and queries directly. (It does not use your Domain Model for this). Handler maps results to the required DTO for consumption by the client. Yes, from one perspective, knowing what an "Open" order is could be considered business logic when there is not a specific boolean value "OrderIsOpen", but it is not command business logic (which should remain in the Domain Model). At some stage, if you did set up a read database optimised for the queries that your client may execute, then during population of that database (following a command completion) you might consider using an "OrderIsOpen" field in the database to make queries more performant and remove the need for the query handler to know what other properties indicate that an Order is open.
contains some business logic (Order is considered Open when ....,. Past due is when....) Yes, in this case you can argue that some business logic can leak into DAL/Infrastructure layer. One thing you can do is to make the query more generic/abstract, i.e. provide parameters to query which are expressed not in business terms related but DAL terms (i.e. something like list of statuses, date filters, etc.). I would argue that this approach pairs nicely combined with the specification pattern. often must be optimized for performance (e.g dont fetch order items, but sum of the order items price). This, I would argue, should not be a problem at all - you are free to create special entities/DTOs for specific cases and it s up to the Infrastructure/DAL/CQRS layer to map them (in general I m a big proponent of using different types for ORM entities and Domain/Business Logic level entities so you can decouple better storage and your Domain).




相关问题
Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How do I compare two decimals to 10 decimal places?

I m using decimal type (.net), and I want to see if two numbers are equal. But I only want to be accurate to 10 decimal places. For example take these three numbers. I want them all to be equal. 0....

Exception practices when creating a SynchronizationContext?

I m creating an STA version of the SynchronizationContext for use in Windows Workflow 4.0. I m wondering what to do about exceptions when Post-ing callbacks. The SynchronizationContext can be used ...

Show running instance in single instance application

I am building an application with C#. I managed to turn this into a single instance application by checking if the same process is already running. Process[] pname = Process.GetProcessesByName("...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签