CQRS
CQRS Example IN C#
CQRS, or Command Query Responsibility Segregation, is a design pattern that separates the responsibilities of reading data (queries) and writing data (commands). This separation allows for different models to be used for reading and writing, which can improve performance, scalability, and maintainability.
### Key Concepts
1. **Commands**: Actions that change the state of the application (e.g., creating, updating, or deleting data).
2. **Queries**: Actions that retrieve data without modifying it.
### Usage Scenarios
CQRS is particularly useful in scenarios where:
- The application has complex business logic.
- Read and write workloads are significantly different (e.g., high read loads).
- You want to optimize read and write models independently.
- The system needs to support eventual consistency.
### Example: Blog Website
Let's consider a simple blog website where users can create, read, and delete blog posts.
#### Commands
1. **CreatePostCommand**: Command to create a new blog post.
2. **DeletePostCommand**: Command to delete a blog post.
#### Queries
1. **GetPostQuery**: Query to retrieve a specific blog post.
2. **GetAllPostsQuery**: Query to retrieve all blog posts.
### Example Code
Here’s a simplified implementation in C#:
```csharp
// Models
public class BlogPost
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
// Commands
public class CreatePostCommand
{
public string Title { get; set; }
public string Content { get; set; }
}
public class DeletePostCommand
{
public Guid Id { get; set; }
}
// Command Handlers
public class BlogCommandHandler
{
private readonly List
public BlogCommandHandler(List
{
_posts = posts;
}
public void Handle(CreatePostCommand command)
{
var newPost = new BlogPost
{
Id = Guid.NewGuid(),
Title = command.Title,
Content = command.Content
};
_posts.Add(newPost);
}
public void Handle(DeletePostCommand command)
{
var post = _posts.FirstOrDefault(p => p.Id == command.Id);
if (post != null)
{
_posts.Remove(post);
}
}
}
// Queries
public class GetPostQuery
{
public Guid Id { get; set; }
}
public class GetAllPostsQuery { }
// Query Handlers
public class BlogQueryHandler
{
private readonly List
public BlogQueryHandler(List
{
_posts = posts;
}
public BlogPost Handle(GetPostQuery query)
{
return _posts.FirstOrDefault(p => p.Id == query.Id);
}
public List
{
return _posts.ToList();
}
}
// Usage
public class BlogService
{
private readonly BlogCommandHandler _commandHandler;
private readonly BlogQueryHandler _queryHandler;
public BlogService(BlogCommandHandler commandHandler, BlogQueryHandler queryHandler)
{
_commandHandler = commandHandler;
_queryHandler = queryHandler;
}
public void CreatePost(string title, string content)
{
var command = new CreatePostCommand { Title = title, Content = content };
_commandHandler.Handle(command);
}
public void DeletePost(Guid id)
{
var command = new DeletePostCommand { Id = id };
_commandHandler.Handle(command);
}
public BlogPost GetPost(Guid id)
{
var query = new GetPostQuery { Id = id };
return _queryHandler.Handle(query);
}
public List
{
return _queryHandler.Handle(new GetAllPostsQuery());
}
}
```
### Conclusion
CQRS can help in structuring applications with complex logic and varying read/write operations. By clearly separating commands and queries, it can lead to cleaner code and better scalability. This example provides a basic structure; in a real-world application, you might use a database, implement event sourcing, or integrate a messaging system for better decoupling.
Comments
Post a Comment