پیاده سازی گام به گام الگوی جنریک Repository در #C

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

دسترسی مستقیم به دیتابیس از طریق منطق تجاری برنامه (Business Logic) کار جالبی نیست. این کار توسعه و تست برنامه را مشکل خواهد کرد. دسترسی مستقیم به دیتابیس از طریق BL موجب بروز مشکلات زیر خواهد شد:

۱- آزمون واحد BL را پیچیده خواهد کرد.

۲- BL بدون وجود عناصر خارجی مانند دیتابیس قابل تست شدن نخواهد بود.

۳- بخش دسترسی به داده در سرتاسر BL تکرار خواهد شد.

بدون یک Repository یک برنامه به شکل زیر خواهد بود:

 

الگوی Repository منطق دستیابی به داده را جدا و آن را به موجودیت‌های داخل BL نگاشت می‌نماید. اینکار باعث می‌شود هم با موجودیت‌های دامنه کار کند و هم منطق دستیابی به داده را اجرا نماید. در الگوی Repository، موجودیت‌های دامنه، منطق دستیابی به داده و منطق تجاری برنامه (BL) با یکدیگر با استفاده از واسط‌(interface)ها ارتباط برقرار می‌کنند.

در این‌حالت جزئیات دستیابی به داده از BL مخفی می‌ماند. به عبارت دیگر BL می‌تواند بدون داشتن هرگونه دانشی از معماری دستیابی به داده مورد استفاده در برنامه به شی داده‌ دسترسی داشته باشد. به‌عنوان مثال در الگوی Repository، BL اطلاع ندارد که آیا برنامه از LINQ to SQL استفاده می‌کند یا ADO.NET Entity Model ORM. این کار یک مزیت مهم دارد:معماری یا منبع داده‌ای مورد استفاده می‌تواند بدون ایجاد کوچکترین تاثیری روی BL تغییر کند.

 

برخی از سایر فواید استفاده از الگوی Repository عبارت‌است از:

        • منطق تجاری(BL) برنامه می‌تواند بدون نیاز به یک منبع خارجی تست شود.

        • منطق دسترسی به دیتابیس (DAL) برنامه می‌تواند به‌طور جداگانه تست شود.

        • دیگر کد تکراری وجود نخواهد داشت.

        • استراتژی کش نمودن داده برای منبع داده‌ای می‌تواند متمرکز گردد.

        • توسعه دامنه‌محور(Domain Driven) آسان‌تر خواهد بود.

        • متمرکز شدن DAL ، بنابراین نگهداری کد آسان‌تر خواهد شد.

حالا وقت آن رسیده است که الگوی Repository را در#C پیاده کنیم. برای اینکار ما با ایجاد یک کلاس Entity، کار را شروع خواهیم کرد. این کلاس شامل یک متغیر سراسری Id خواهد بود که بیانگر ستون Identity موجودیت ما است.

public class IEntity
    {
        public string Id; 
    }

همچنین interface جنریک Repository نوع IEntity می‌تواند به شکل زیر باشد. همانطور که مشاهده می‌کنید عملیات CRUD بخشی از آن است. توجه کنید که درصورتی که یک Repository به‌خصوص نیازمند عملیات اضافی باشد، آن عملیات می‌تواند در واسط جنریک Repository تعبیه گردد.

public interface IRepository<T> where T: IEntity
    {

        IEnumerable<T> List { get; }
        void Add(T entity);
        void Delete(T entity);
        void Update(T entity);
        T FindById(int Id);
    }

فرض کنید می‌خواهیم با یک کلاس مولف(Author) کار کنیم. برای این‌کار یک کلاس موجودیت Author را ایجاد می‌کنیم. این کلاس باید از کلاس IEntity مشتق شود تا بتواند با الگوی جنریک Repository کار کند:

    [Table("Author")]
    public partial class Author : IEntity
    {
        public int Id { get; set; }

        [Required]
        public string authorname { get; set; }
    }

همانطور که ملاحظه می‌کنید کلاس به صفت Table آراسته شده است. در اینجا تفاوتی نمی‌کند که شما از این روش استفاده کنید یا از Fluent API.

برای ایجاد نمودن AuthorRepository یک کلاس ایجاد خواهیم کرد که اینترفیسRepository جنریک ،<IRepository<Author را پیاده سازی خواهد کرد. در این مثال ما عملیات CRUD را توسط Entity Framework انجام داده‌ایم. شما می‌توانید این عملیات را توسط LINQ to SQL، ADO.NET یا هر روش دلخواه دیگری انجام دهید.

در مورد انجام عملیات CRUD در کلاس AuthorRepository نکته‌ی خاصی وجود ندارد و این بخش شامل کدهای ساده LINQ to Entity برای اجرای عملیات CRUD‌ است.

کلاس AuthorRepository به شکل زیر است:

public class AuthorRepository : IRepository<Author>
    {

        MyModel _authorContext;

        public AuthorRepository()
        {
            _authorContext = new MyModel();

        }
        public IEnumerable<Author> List
        {
            get
            {
                return _authorContext.Authors;
            }
            
        }

        public void Add(Author entity)
        {
            _authorContext.Authors.Add(entity);
            _authorContext.SaveChanges();
        }

        public void Delete(Author entity)
        {
            _authorContext.Authors.Remove(entity);
            _authorContext.SaveChanges();
        }

        public void Update(Author entity)
        {
            _authorContext.Entry(entity).State = System.Data.Entity.EntityState.Modified;
            _authorContext.SaveChanges();
            
        }

        public Author FindById(int Id)
        {
            var result = (from r in _authorContext.Authors where r.Id == Id select r).FirstOrDefault();
            return result; 
        }

این تمام کاری است که باید برای پیاده‌سازی الگوی جنریک Repository انجام دهید. در هرنوع برنامه خواه MVC، خواه WPF یا یک Console Application ساده، نحوه استفاده از یک الگوی جنریک Repository به شکل زیر خواهد بود:

IRepository<Author> repository = new AuthorRepository();
            var result = repository.List;
            foreach (var r in result)
            {
                Console.WriteLine(r.authorname);

            }

در اینجا من مستقیما یک نمونه از کلاس AuthorRepository ایجاد کردم. برای تست‌پذیری بهتر و ایجاد Dependency زمان اجرا می‌توان از ابزارهای Dependency Injection‌ی مثل StructureMap و یا Unity برای ایجاد یک نمونه از شی AuthorRepository استفاده کنید.

 

  • Book.mark.hu
  • co.mments
  • De.lirio.us
  • del.icio.us
  • Digg
  • DotNetKicks
  • E-Mail
  • Facebook
  • feedmelinks
  • Google
  • LinkedIn
  • msdn Social
  • MyShare
  • Slashdot
  • StumbleUpon
  • TwitThis
  • Tumblr
  • Yahoo! Buzz
  • Yahoo! MyWeb
  • Print

نظرات (3) -

مهسا

مرسی خیلی جالب بود

admin

خواهش می‌کنم.
موفق باشید.

محمد

البته روش بهتری از این هم وجود دارد بدین صورت که  در معرفی کلاس میتوانیم از
public class GenericRepository<T> : IGenericRepository<T> where T:class
به جای
public class AuthorRepository : IRepository<Author>
استفاده کنیم در این حالت اگر چندین کلاس مثل Publisher یا Book  نیز داشته باشیم میتوانیم از یک کلاس واحد برای همه آنها استفاده کرد

امکان ارسال نظر برای این موضوع وجود ندارد