برنامه نویسی

الگوی مخزن در C# با اصول محکم

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

– چرا از الگوی مخزن استفاده می کنیم؟

مزایا

تفکیک – مخزن پایگاه داده را از منطق تجارت جدا می کند.
جایگزینی آسان – اگر می خواهیم از چارچوب موجودیت به Dapper یا ORM دیگر تغییر کنیم ، می توانیم بدون تغییر کل برنامه ، این کار را انجام دهیم.
تست های واحد για را مسخره می کند – ما به راحتی می توانیم با بهبود آزمایش ، مخازن را تهیه کنیم.
مدیریت داده بهتر – یک رویکرد اصلی برای دسترسی به داده ها فراهم می کند.

– اصول جامد و الگوی مخزن

هنگام استفاده از الگوی مخزن ، پیروی از اصول جامد برای تمیز نگه داشتن کد و قابل ارتقاء مهم است.

1⃣ اصل مسئولیت واحد (SRP) – هر مخزن باید یک مسئولیت داشته باشد: دسترسی به داده های یک نهاد خاص.
2 اصل بسته (OCP) – ما باید بدون تغییر کد موجود بتوانیم مخازن یا نمایش داده های جدید را اضافه کنیم.
3⃣ اصل تعویض لیسکوف (LSP) – هر مخزن را می توان با دیگری جایگزین کرد بدون اینکه مشکلی ایجاد کند.
4⃣ اصل تفکیک رابط (ISP) – به جای مخزن با روش های مختلف ، بهتر است رابط های تخصصی داشته باشید.
5⃣ اصل وارونگی وابستگی (DIP) – مخزن نباید مستقیماً به ORM (به عنوان مثال چارچوب موجودیت) بستگی داشته باشد ، بلکه به انتزاع است.

مخزن مثال در C# با اصول محکم

1⃣ نهاد (نهاد)

فرض کنید ما یک برنامه با آن داریم مشتریان

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

2 ایجاد مخزن عمومی (مخزن عمومی)

بوها مخزن عمومی (مخزن عمومی) به ما اجازه می دهد تا داشته باشیم کد قابل استفاده مجدد

public interface IRepository where T : class
{
    Task GetByIdAsync(int id);
    Task> GetAllAsync();
    Task AddAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(int id);
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

3⃣ اجرای مخزن عمومی با چارچوب موجودیت

در هسته EF برای دسترسی به پایگاه داده استفاده می شود.

public class Repository : IRepository where T : class
{
    protected readonly AppDbContext _context;
    protected readonly DbSet _dbSet;

    public Repository(AppDbContext context)
    {
        _context = context;
        _dbSet = context.Set();
    }

    public async Task GetByIdAsync(int id) => await _dbSet.FindAsync(id);

    public async Task> GetAllAsync() => await _dbSet.ToListAsync();

    public async Task AddAsync(T entity)
    {
        await _dbSet.AddAsync(entity);
        await _context.SaveChangesAsync();
    }

    public async Task UpdateAsync(T entity)
    {
        _dbSet.Update(entity);
        await _context.SaveChangesAsync();
    }

    public async Task DeleteAsync(int id)
    {
        var entity = await _dbSet.FindAsync(id);
        if (entity != null)
        {
            _dbSet.Remove(entity);
            await _context.SaveChangesAsync();
        }
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

4⃣ ایجاد مخزن تخصصی برای مشتریان (مخزن مشتری)

به جای اضافه کردن تمام روشهای موجود در یک مخزن، ما ایجاد می کنیم مخازن تخصصی.

4.1 ما یک رابط تخصصی را تعریف می کنیم

public interface ICustomerRepository : IRepository
{
    Task GetByEmailAsync(string email);
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

4.2 اجرای مخزن مشتری

public class CustomerRepository : Repository, ICustomerRepository
{
    public CustomerRepository(AppDbContext context) : base(context) { }

    public async Task GetByEmailAsync(string email)
    {
        return await _context.Customers.FirstOrDefaultAsync(c => c.Email == email);
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

آیا خوب است که مخازن زیادی داشته باشید یا یک روش بزرگ با روش های زیادی؟

👉 بهترین روش داشتن مخازن کوچک و تخصصی است.

🔹 مشکل با یک مخزن عظیم:

  • حفظ آن دشوار می شود.
  • این اصل تفکیک رابط (ISP) را نقض می کند.
  • اگر برنامه رشد کند ، مخزن چند برابر می شود.

🔹 راه حل:

  • بوها مخزن عمومی برای توابع اساسی (CRUD).
  • مخازن تخصصی برای پرس و جوهای پیچیده یا منطق کسب و کار (به عنوان مثال icustomerrepository).

🔹 چگونه می توانیم بدون نیاز به اجرای آن ، یک رابط را به ارث ببریم؟

اگر یک کلاس باشد یک رابط را به ارث می برد، باید تمام روش های او را پیاده سازی کند. اما راهی برای جلوگیری از اجرای اجباری وجود دارد!

👉 راه حل: ما استفاده می کنیم یک کلاس متوسط (کلاس انتزاعی ή کلاس پایه).

نمونه

فرض کنید ما یک ICUSTOMERREPORITORE رابط داریم و می خواهیم یک پایه ایجاد کنیم که نیازی به اجرای همه روش ها نداشته باشد.

public abstract class BaseRepository : IRepository where T : class
{
    public virtual Task GetByIdAsync(int id) => throw new NotImplementedException();
    public virtual Task> GetAllAsync() => throw new NotImplementedException();
    public virtual Task AddAsync(T entity) => throw new NotImplementedException();
    public virtual Task UpdateAsync(T entity) => throw new NotImplementedException();
    public virtual Task DeleteAsync(int id) => throw new NotImplementedException();
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

اکنون ، هر ارث مخزن το پایه گذاری*، اگر به آنها احتیاج ندارید ، لازم نیست تمام روشهای CRUD را پیاده سازی کنم!*

📌 پایان
✔ الگوی مخزن ساختار کد را بهبود می بخشد.
✔ ترجیح داده می شود مخازن تخصصی به جای یک عظیم
✔ اگر می خواهیم بدون اجرای یک رابط به ارث ببریم ، استفاده می کنیم کلاسهای انتزاعی.

همچنین ببینید: دسته بندی عملکردهای بادوام و زمان استفاده از آنها

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا