ابتدا، ما تعریف الگوی Repository را از این کتاب با هم مرور خواهیم کرد:
Mediates between the domain and data mapping layers, acting like an in-memory collection of domain objects.
این تعریف بیان میکند که Repositor در واقع collection ازEntities است که به عنوان واسطی بین Data Mappers عمل میکند.
گفتیم که Repository مجموعهای از Entities است، بنابراین باید متدهایی که یک مجموعه دارد را نیز شامل شود، متدهایی مانند:
اولین نکتهای که باید به آن توجه کنیم این است که ما در حال صحبت درباره یک collection هستیم، بنابراین متدهایی مانند save (ذخیره) یا update (بهروزرسانی) نداریم.
خب! اگر متدهای ذخیره و بهروزرسانی نداریم، چطور میتوانیم یک record جدید ایجاد کنیم یا آن را بهروزرسانی کنیم؟ پاسخ این سوال را زمانی که به الگوی واحد کار (Unit of Work) اشاره کنیم، خواهیم داد.
گفتیم که هر Repository نمایانگر یک Entity است و مانند یک collection از آن Entity در حافظه عمل میکند. همچنین گفتیم که هر Repository به دلیل ویژگی collection بودن، دارای متدهایی مانند add ، remove ، get و find است. حالا، از آنجا که همه Repository ها باید این متدها را داشته باشند، برای جلوگیری از تکرار کد، یک کلاس پایه ایجاد میکنیم که این متدهای اساسی را دارد و سایر کلاسها از آن ارثبری میکنند.
حالا اجازه دهید به یکی از مزایای Repository Pattern اشاره کنیم:
در برنامههایی که منطق کسبوکار به طور مستقیم به دادهها دسترسی دارد، ممکن است با مشکلات زیر مواجه شوید:
مخازن یا Repository ها کلاسهایی هستند که منطق لازم برای ذخیره یا بازیابی دادهها را پنهان میکنند. بنابراین، برنامه ما اهمیتی نمیدهد که از چه نوع ORM استفاده میکنیم، زیرا همه چیز مرتبط با ORM در لایه مخزن مدیریت میشود. Repository ها کلاسها یا اجزایی هستند که منطق مورد نیاز برای دسترسی به منابع داده را در خود دارند. آنها عملکردهای عمومی دسترسی به دادهها را متمرکز کرده و باعث بهبود قابلیت نگهداری میشوند و همچنین زیرساخت یا فناوری مورد استفاده برای دسترسی به پایگاه دادهها را از لایه Domain Model جدا میکنند.
از آنجایی که Domain نباید به فناوری وابسته باشد!درنتیجه نباید به لایه دسترسی به دادهها یا EF Core یا... ارجاع داشته باشد. دامنه فقط مجموعهای از اینترفیسها را تعریف میکند که بعداً به عنوان لایه Data Access شناخته میشوند و این اینترفیسها باید پیادهسازی شوند!
معماری باید از فریمورکها مستقل باشد. (رابرت سیسیل مارتین)
ممکن است مواردی پیش بیاید که نیاز به استفاده از چندین ORM در یک راهحل داشته باشید. احتمالاً از Dapper برای خواندن داده و از EFCore برای نوشتن داده استفاده کنید. این کار صرفاً برای بهینهسازی عملکرد است.
الگوی Repository به ما کمک میکند با ایجاد یک لایه انتزاعی در بالای لایه دسترسی به دادهها به این هدف برسیم. اکنون دیگر نیازی نیست که برنامه شما به EFCore یا هر ORM دیگری وابسته باشد. به جای اینکه EFCore تنها گزینه شما برای دسترسی به دادهها باشد، تبدیل به یکی از گزینههایتان میشود.
حال که لایه EFCore خود را پیکربندی کردهایم، بیایید کمی درباره روش سنتی دریافت دادهها از این لایه صحبت کنیم. بهطور سنتی، شما مستقیماً از شیء dbContext برای خواندن و نوشتن دادهها استفاده میکنید. این روش خوب است، اما آیا برای بلندمدت واقعاً ایدهآل است؟ وقتی مستقیماً از dbContext استفاده میکنید، در واقع Entity Framework Core را به شدت با برنامه خود وابسته میکنید. بنابراین، در آینده زمانی که فناوری جدیدتر و بهتری از EFCore منتشر شود یا نیاز باشد، تغییرات لازم برای پیادهسازی این فناوری جدید بسیار آزاردهنده خواهد بود، درست است؟
از یک طرف، حامیان الگوی Repository معتقدند که تمام کدهای دسترسی به پایگاه داده باید در Repository قرار گیرد، و از طرف دیگر، کسانی که با DbSet و EF کار میکنند، اعتراف میکنند که DbSet خود یک Repository است، بنابراین نیازی به ایجاد یک Repository دیگر نیست.
هر دو نوع تفکر تا حدی صحیح هستند. الگوی Repository و ایده پشت آن برای کار با پایگاه دادهها مفید است، اما این الگو مدتها قبل از معرفی ORMهایی مانند EF شکل گرفته است و امروزه، با وجود ORMهای قدرتمندی مثل EF، ممکن است استفاده از این الگو چندان مفید نباشد.
مهمترین دلایلی که ممکن است بخواهید این کار را انجام دهید (اضافه کردن یک لایه انتزاعی در بالای DbContext):