پرشین تم مقالات 🧩 CQRS چیست؟

🧩 CQRS چیست؟

image profile پرشین تم - 24 شهریور 1404 - 18:19 دانلود مقاله

هرCQRS یک الگوی طراحی نرم‌افزار است که عملیات خواندن (پرس‌وجوها) را از عملیات نوشتن (دستورات) جدا می‌کند. به جای استفاده از یک مدل برای مدیریت دو، آنها را به دو مدل مجزا تقسیم می‌کنید:

🧩 CQRS چیست؟

- دستورات: وضعیت سیستم را تغییر می‌دهند (مثلاً ایجاد، به‌روزرسانی، حذف).

- پرس‌وجوها: داده‌ها را بدون تغییر آن بازیابی می‌کنند.

این جداسازی به هر طرف اجازه می‌دهد تا به طور مستقل برای عملکرد، مقیاس‌پذیری و امنیت بهینه شود.

 

🏗️ چرا از CQRS استفاده کنیم؟

سیستم‌های CRUD سنتی از یک مدل برای همه چیز استفاده می‌کنند که می‌تواند منجر به موارد زیر شود:

  • گلوگاه‌های عملکرد هنگام رقابت عملیات خواندن و نوشتن.
  • مدل‌های داده پیچیده که سعی در برآورده کردن نیازهای متناقض دارند.
  • خطرات امنیتی ناشی از همپوشانی الگوهای دسترسی.

CQRS این مشکل را با فراهم کردن موارد زیر حل می‌کند:

  • مقیاس‌بندی خواندن و نوشتن به صورت مستقل.
  • استفاده از پایگاه‌های داده یا ساختارهای داده مختلف برای هر کدام.
  • ساده‌سازی منطق کسب‌وکار با هماهنگ‌سازی دستورات با اقدامات دنیای واقعی

 

🔧 اجزای اصلی

  • Command: نشان‌دهنده‌ی قصد تغییر وضعیت است (مثلاً CreateOrder)
  • Command Handler: دستور را پردازش کرده و تغییرات را اعمال می‌کند.
  • Query: داده‌ها را بازیابی می‌کند (مثلاً GetOrderDetails)
  • Query Handler: دستور را اجرا کرده و نتایج را برمی‌گرداند.
  • Event: پس از پردازش یک دستور منتشر می‌شود (در Event Sourcing استفاده می‌شود).

 

🚀 چه زمانی از CQRS استفاده کنیم

CQRS در سناریوهایی مانند موارد زیر می‌درخشد:

  • منطق تجاری پیچیده که در آن خواندن و نوشتن تفاوت قابل توجهی دارند.
  • سیستم‌های با کارایی بالا با ترافیک خواندن سنگین.
  • معماری‌های رویداد محور یا سیستم‌هایی که از Event Sourcing استفاده می‌کنند.

اما مراقب باشید - این پیچیدگی را افزایش می‌دهد. برای برنامه‌های ساده CRUD، ممکن است بیش از حد باشد.

 

مثال عملی 

در ادامه یک مثال عملی از پیاده سازی CQRS را ارائه می دهیم.

🧱 نمای کلی ساختار پروژه

/Domain
  Product.cs
/Application
  /Commands
    CreateProductCommand.cs
    CreateProductHandler.cs
  /Queries
    GetProductByIdQuery.cs
    GetProductByIdHandler.cs
/Core
  ICommand.cs
  IQuery.cs
  ICommandHandler.cs
  IQueryHandler.cs
  Dispatcher.cs
/Infrastructure
  ProductDbContext.cs
  ProductRepository.cs

 

1️⃣ تعریف اینترفیس های اصلی

// Core/ICommand.cs
public interface ICommand { }

// Core/IQuery<TResult>.cs
public interface IQuery<TResult> { }

// Core/ICommandHandler.cs
public interface ICommandHandler<TCommand>
    where TCommand : ICommand {
    Task HandleAsync(TCommand command);
}

// Core/IQueryHandler.cs
public interface IQueryHandler<TQuery, TResult>
    where TQuery : IQuery<TResult> {
    Task<TResult> HandleAsync(TQuery query);
}

 

2️⃣ ایجاد یک Dispatcher

// Core/Dispatcher.cs
public class Dispatcher {
    private readonly IServiceProvider _provider;
    public Dispatcher(IServiceProvider provider) {
        _provider = provider;
    }

    public Task SendAsync<TCommand>(TCommand command) where TCommand : ICommand {
        var handler = _provider.GetRequiredService<ICommandHandler<TCommand>>();
        return handler.HandleAsync(command);
    }

    public Task<TResult> QueryAsync<TQuery, TResult>(TQuery query) where TQuery : IQuery<TResult> {
        var handler = _provider.GetRequiredService<IQueryHandler<TQuery, TResult>>();
        return handler.HandleAsync(query);
    }
}

 

3️⃣ Domain Model

// Domain/Product.cs
public class Product {
    public Guid Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
}

 

4️⃣ Command & Handler

// Application/Commands/CreateProductCommand.cs
public class CreateProductCommand : ICommand {
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
}

// Application/Commands/CreateProductHandler.cs
public class CreateProductHandler : ICommandHandler<CreateProductCommand> {
    private readonly ProductDbContext _context;
    public CreateProductHandler(ProductDbContext context) {
        _context = context;
    }

    public async Task HandleAsync(CreateProductCommand command) {
        var product = new Product {
            Id = Guid.NewGuid(),
            Name = command.Name,
            Price = command.Price
        };

        _context.Products.Add(product);
        await _context.SaveChangesAsync();
    }
}

 

5️⃣ Query & Handler

// Application/Queries/GetProductByIdQuery.cs
public class GetProductByIdQuery : IQuery<Product?> {
    public Guid Id { get; set; }
}

// Application/Queries/GetProductByIdHandler.cs
public class GetProductByIdHandler : IQueryHandler<GetProductByIdQuery, Product?> {
    private readonly ProductDbContext _context;

    public GetProductByIdHandler(ProductDbContext context) {
        _context = context;
    }

    public async Task<Product?> HandleAsync(GetProductByIdQuery query) {
        return await _context.Products.FindAsync(query.Id);
    }
}

 

6️⃣ Register Services

// Program.cs
builder.Services.AddDbContext<ProductDbContext>(opt =>
    opt.UseInMemoryDatabase("ProductDb"));

builder.Services.AddScoped<Dispatcher>();
builder.Services.AddScoped<ICommandHandler<CreateProductCommand>, CreateProductHandler>();
builder.Services.AddScoped<IQueryHandler<GetProductByIdQuery, Product?>, GetProductByIdHandler>();

 

7️⃣ Controller Example

// Controllers/ProductController.cs
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase {
    private readonly Dispatcher _dispatcher;
    public ProductController(Dispatcher dispatcher) {
        _dispatcher = dispatcher;
    }

    [HttpPost]
    public async Task<IActionResult> Create(CreateProductCommand command) {
        await _dispatcher.SendAsync(command);
        return Ok();
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetById(Guid id) {
        var product = await _dispatcher.QueryAsync<GetProductByIdQuery, Product?>(new GetProductByIdQuery { Id = id });
        return product is null ? NotFound() : Ok(product);
    }
}
با خرید اشتراک می توانید تا چندین برابر مبلغ خرید اشتراک خود قالب های HTML ، سورس کدهای آماده و یا مقالات دانلود کنید
شما می توانید تنها فقط با مبلغ 3,000,000 میلیون تومان وب سایت سفارسی برای خود داشته باشید
محبوب ترین مقالات
تفاوت بین CSS و SCSS چیست؟ تفاوت بین CSS و SCSS چیست؟
category برنامه نویسی 07 اسفند 1402
تفاوت بین RDBMS و DBMS تفاوت بین RDBMS و DBMS
category برنامه نویسی 02 فروردین 1403
کلمات کلیدی در SQL کلمات کلیدی در SQL
category برنامه نویسی 01 خرداد 1403
کاوش در معماری GPT-3 کاوش در معماری GPT-3
category هوش مصنوعی 12 اسفند 1402
تفاوت بین CSS، SASS و SCSS چیست؟ تفاوت بین CSS، SASS و SCSS چیست؟
category برنامه نویسی 13 اسفند 1402
انواع Join در SQL انواع Join در SQL
category برنامه نویسی 02 فروردین 1403
ChatGPT چیست؟ ChatGPT چیست؟
category هوش مصنوعی 12 اسفند 1402
آخرین مقالات
آموزش معماری Bloc در فلاتر آموزش معماری Bloc در فلاتر معماری BLoC (مخفف Business Logic Component) یکی از محبوب‌ترین معماری‌ها در فلاتر برای مدیریت وضعیت (state management) ...
category برنامه نویسی 09 مهر 1404
میکروسرویس چیست؟ مثال عملی در Asp Core میکروسرویس چیست؟ مثال عملی در Asp Core میکروسرویس‌ها (Microservices) یک سبک معماری نرم‌افزاری هستند که در آن سیستم بزرگ به مجموعه‌ای از سرویس‌های کوچک، مستقل...
category برنامه نویسی 09 مهر 1404
Redis چیست؟ آموزش استفاده از آن در asp core Redis چیست؟ آموزش استفاده از آن در asp core Redis یک مخزن داده با عملکرد بالا و کلید-مقدار در حافظه است که اغلب برای ذخیره‌سازی موقت (caching)، مدیریت جلسه (sessi...
category برنامه نویسی 27 شهریور 1404