CQRS and Event sourcing in ASP.NET [Explained]

0
1571
CQRS-and-Event-sourcing

This post was last Updated on June 5, 2023 by Himanshu Tyagi to reflect the accuracy and up-to-date information on the page.

CQRS (Command-Query Responsibility Segregation) is commonly used with event sourcing pattern—command-query responsibility segregation-based system to use the data model to read and write.

Implementing, Command-query responsibility segregation (CQRS) can maximize your application’s performance, scalability, and security—event-sourcing stores data models with an action taken on data instead of storing the current data state.

Also ReadHow to create ASP.NET Registration Form Using C# and SQL Server Database

What is CQRS (Command-Query Responsibility Segregation)?

Command-Query Responsibility Segregation (CQRS) is a design pattern that has enormous consequences for any system design. CQRS states that command and query are entirely different and executed against different data models (Read and write).

The Command-Query Responsibility Segregation pattern divides into two categories:

Queries (Return Data): Get data/information from the database and never modify anything within the model.

Commands (Perform Action): Command performs actions that can be written, updated, or deleted (along with business logic).

common flow of application
1.1 The typical flow of Application

The standard data model reads and updates a database in traditional architectures and performs CRUD operations.  The application performs different queries in complex applications on the read side, and object mapping can become complex.

For the write-side, the model implements complicated validation and business logic for the application.

Also ReadHow To Create ASP.net Login Page Using C# with SQL Database [Download]

Challenges without CQRS

  • There may be a mismatch between the read and write representations of the data because additional columns or properties must be updated correctly, even though they aren’t required as part of an operation.
  • The traditional approach can hurt performance because of the load on the data store and access layer, and the complex queries are used to retrieve information.
  • The traditional approach uses a common entity for reading and writing operations, so managing security and permissions can be complex.

Also Read15 Best App Review Sites 2023

Solution

CQRS uses a separate read and writes model, Command is used to update data, and Queries is used to read data.

  • The command should not base on data. It should be task-based.
  • The command should be placed in an asynchronous queue rather than processed synchronously.
  • Query can’t modify the database and return DTO (Data transfer object).
cqrs work flow
1.2 CQRS WorkFlow

Benefits of CQRS

The benefits of CQRS are as follows:

  • Independent scaling: CQRS allows the read and writes workloads to scale independently.
  • Optimized data schemas: Schema is used by the read side to optimize the query, and Schema is used by the write side to optimize updates.
  • Separating read and write sides: Separating the read and write sides can result in maintainable and flexible models. Write models contain complex business logic, and the read model can be simple.
  • More straightforward queries: The application can avoid complex joins when querying using a materialized view in the read database.
  • Performance: CQRS increases performance because the event is stored in serialized JSON, and re-run JSON is fast.

What is Event sourcing?

In a “normal” database, data is stored with its value and relation as it currently exists. In the Event Sourcing data store, data is a store with its changes in the form of an event. These events can be re-run later to re-create the current state of data.

In Event sourcing, you have data stored at the current time and can re-create the data stored at any time. Event sourcing can improve an application’s performance, scalability, and responsiveness.

Command-Query Responsibility Segregation and Event sourcing fit together well because event sourcing becomes a written model of CQRS while the read model’s design is irrelevant.

CQRS and ES systems work well together, and the CQRS/ES system label is just a CQRS system.

CQRS/ES system is challenging to set up.

Why use Command-Query Responsibility Segregation/Event sourcing?

Use CQRS if:

  • CQRS/ES is used when your application’s performance is a significant concern.
  • If your application requires all the data at any point in time.

When to use this pattern?

Consider the following scenarios for CQRS:

  • When a collaborative domain is used, CQRS allows you to minimize merge conflicts at the domain level.
  • When the Task-based interface is used in your application to guide the user through a complex process as a step or with a complex model, the write model has full-command processing on business logic and validation. The read model has no business logic and uses in the view model.
  • When read data is tuned with the performance of write data and when several reads are more significant than the number of writes.
  • When one team can focus on a complex domain, which is part of the write model, and the other team, focus on the reading model and user interface.
  • When the system must evolve and contain multiple versions of the model, business rules change regularly.
  • When integrated with other systems like event sourcing, one system’s failure should not affect others.

This pattern is not recommended in the following scenario:

  • When the domain and business rule of application is simple.
  • When simple CRUD operation and data access operation are sufficient for your application.

Consider the following points when the CQRS pattern is used with Event-sourcing.

  • When systems based on this pattern are consistent and use separate read and write models.
  • There will be a delay between event generation and event updates.
  • The pattern adds complexity because code must be created to initiate and handle the event, update the view or object required by queries, or read the model. When CQRS is used with events, sourcing requires a different system design approach. Event sourcing makes it easier to rebuild the view because it preserves changes.
  • The materialized view is generated for a reading model or data projection by replying event.

Example

The following code shows the read model:

// Query interface
namespace ReadModel
{
  public interface StudentsDao
  {
    StudentDisplay FindById(int studentId);
    ICollection<StudentDisplay> FindByName(string name);
    ICollection<StudentDisplay> FindStudentResult(int studentId);
  }
  public class StudentDisplay
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email{ get; set; }
    public string RollNumber{ get; set; }
    public string Result{ get; set; }
  }
}

The following code shows the command handler:

public interface ICommand
{
  Guid Id { get; }
}
public class GenerateResult: ICommand
{
  public GenerateResult()
  {
    this.Id = Guid.NewGuid();
  }
  public Guid Id { get; set; }
  public int StudentId{ get; set; }
  public int Result{ get; set; }
}

Conclusion

In this blog, we have discussed the Command-Query Responsibility Segregation and the problem without Command-Query Responsibility Segregation, and the solution to those issues. We have also discussed a few benefits and Event sourcing with a simple example of the reading model and Command.