‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۷:۰۰
بله. این روش طراحی خیلی خوبه؛ برنامه استفاده کننده از نحوه پیاده سازی  GetMemberInfo بی‌خبر است. حالا می‌خواهد NH باشد یا EF یا هر مورد دیگری.
ضمن اینکه این لایه میانی رو که عنوان کردید هم در برنامه‌های وب می‌تونه استفاده شود و هم ویندوزی.
‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۶:۴۲
همه این‌ها نیکو! ولی زمانیکه از یک ORM‌ استفاده می‌کنید، DAL همین ORM است. تعویض آن هم به سادگی میسر نیست. من با شناختی که مثلا از NH دارم عرض می‌کنم که کسی که از NH استفاده می‌کنه نمی‌تونه توانایی‌های توکار آن‌را با هیچ ORM ‌دیگری عوض کنه. سطح دوم کش، غیرفعال کردن سطح اول کش برای مباحث گزارشگیری. متدهای ویژه‌ای که در QueryOver آن پیش‌بینی شده. استفاده از HQL آن برای اعمالی که نه با LINQ میسر است و نه با QueryOver.
خلاصه از سطحی خیلی بالا اینطور به نظر میرسه که می‌شود یک لایه انتزاعی بر روی ORM درست کرد ولی در عمل اینطور نیست. این لایه قابل انتقال نیست مثلا به EF یا نمونه‌های مشابه.
‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۶:۲۳
- ORMهای با پشتیبانی از IQueryable ، پشتیبانی یکسانی از متدهای الحاقی تعریف شده ندارد. کد شما قابل انتقال نیست. برای مثال NH یک سری متد الحاقی خاص خودش را دارد. بنابراین اگر تصور می‌کنید که می‌توان این پیاده سازی را به ORM دیگری تغییر داد، در عمل ممکن نیست؛ مگر اینکه از توانایی‌های محدود و مشترکی استفاده کنید.
- یکی دیگر از اشتباهات طراحی الگوی Repository متدهای عمومی هستند که دارای خروجی IQueryable است. به این نوع طراحی، طراحی نشتی دار گفته می‌شود چون ابتدای کار مشخص است اما انتهای کار بازگذاشته شده است: (^)
- یک مثال دیگر: NH دارای متدی است به نام tofeautre که توانایی اجرای چندین و چند مثلا sum را بر روی بانک اطلاعاتی در یک رفت و برگشت دارد. لایه Repository شما نمی‌تواند این را مخفی کند و در صورت استفاده از آن قابل انتقال نخواهد بود. استفاده از آن هم ایرادی ندارد چون دلیل استفاده از یک ORM، استفاده از توانایی‌های پیشرفته آن‌ها است. از این نمونه مثال زیاد است.
حالا اینجا اگر شخصی از الگوی Repository استفاده کند، هم بی‌جهت خودش را محدود کرده و هم نهایتا به یک leaky abstraction رسیده.
- «چهارچوبی دارم که کاملاً از ORM مستقل هستند» این همان لایه سرویس است که از آن صحبت شد. نباید کدهای یک ORM (هر ORM ایی) داخل Code behind یا کنترلرهای MVC مشاهده شوند. این روش توصیه شده است.
- رمزنگاری را می‌شود با یک سری متدالحاقی در یک پروژه دیگری به نام Common پیاده سازی کرد. در لایه Service از آن استفاده کرد. بحث ما در اینجا در مورد Repository و عدم ضرورت استفاده از آن است. یا مباحث صفحه بندی هم به همین ترتیب. این‌ها یک سری متدالحاقی عمومی هستند؛ خارج از تعریف الگوی Repository قرار می‌گیرند.
‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۵:۰۲
این همان مورد «به این ترتیب به سادگی می‌توان ORM مورد استفاده را تغییر داد» است که در بالا توضیح دادم. نمی‌تونید به این سادگی وابستگی‌های ذاتی به ORM مورد استفاده را حذف کنید. تمام کار با ORM به Update و Delete ختم نمی‌شود. برای نوشتن یک لایه قابل انتقال نیاز خواهید داشت دست و پای ORM مورد استفاده را قطع کنید که مثال زدید ... استقلال از IQueryable . و سؤال اینجا است که تمام لطف EF همین IQueryable است؛ چرا باید از این مستقل شد. من از کار کردن مستقیم با آن لذت می‌برم! به همین دلیل EF را انتخاب کرده‌ام. فقط لایه سرویس مورد استفاده نباید IQueryable را بازگرداند.
‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۴:۴۴
- به همین دلیل در مورد عدم استفاده از Repository توضیح دادم. کار Repository همین warping عملکرد یک ORM است که نه تنها ضرورتی ندارد بلکه در یک پروژه واقعی به شدت جلوی آزادی عمل شما را خواهد گرفت و همچنین پیاده سازی شما هم قابل انتقال نخواهد بود. استفاده از ORMها وابستگی‌های زیادی را به همراه دارند که شاید تنها قسمتی از آن‌ها را بتوانید مخفی کنید. همچنین برای اینکار باید از قابلیت‌های پیشرفته آن‌ها که ممکن است در سایر ORMs موجود نباشد، صرف نظر کرد. آزمون‌های واحد مرتبط با بانک‌های اطلاعاتی نیاز به بانک اطلاعاتی واقعی دارند تا بتواند قیود را اعمال کند. کار با اشیاء درون حافظه در اینجا اصلا توصیه نمی‌شود.
- بهتره. ضرورتی نداره. در حد یک مدیریت پروژه بهتر است که با یک نگاه بتوان تشخیص داد ... حداقل یک پوشه Models در برنامه هست. تا این حد کفایت می‌کند.
‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۴:۲۷
یک مثال ساده: بجای اینکه در Code behind برنامه شروع کنید به وهله سازی از DbContext و بعد کوئری بنویسید و حاصل را مثلا در اختیار یک Grid قرار دهید، یک کلاسی ... جایی در یک پروژه Class library مجزا درست کنید که حاوی متد مشخصی است که فقط یک IList را برمی‌گرداند. این متد، محل کار با EF است نه Code behind یک فرم. در آنجا فقط باید از لیست نهایی تهیه شده استفاده شود.
‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۴:۲۳
- بله. چیزی شبیه به همین، البته وجود Interface هم در اینجا غیرضروری است. چون در مورد mocking صحبت کردم که در بانک‌های اطلاعاتی روش مناسبی نیست و بیشتر «توهم» صحیح کارکردن سیستم را به همراه خواهد داشت. توهم پاس شدن آزمون‌های واحدی که در عمل ممکن است تعداد زیادی از آن‌ها روی بانک اطلاعاتی واقعی اجرا نشوند. فرق است بین کار با اشیاء درون حافظه و بانک اطلاعاتی واقعی که بسیاری از قیود را اعمال می‌کند.
- بله. اسامی مهم نیست. یکی عنوان می‌کند BLL یکی Infrastructure یکی Service یکی...
- خروجی لایه سرویس فقط باید از نوع اشیاء معمولی، لیست یا IEnumerable باشد. اگر از IQueryable به عنوان خروجی متد استفاده کردید، به یک Abstraction دارای «نشتی» خواهید رسید. چون به سادگی خارج از منطقی که مدنظر بوده کاملا قابل تغییر است.
- God Class کلاسی است که اطلاعات زیادی را در اختیار سایرین قرار می‌دهد، نه کلاسی که جهت برآورده سازی منطق تجاری برنامه، از اطلاعات زیادی استفاده می‌کند. کلاسی که 1000 تا متد را در اختیار سایر کلاس‌ها قرار می‌دهد God class نام دارد. نه متدی که برای عملکرد صحیح خود نیاز به اطلاعات زیادی است.
‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۴:۱۴
1- بله.
 2- بله.
3- این هم خوبه ولی اگر بانک اطلاعاتی و برنامه وب شما مثلا در یک سرور قرار دارند ضرورتی به استفاده از WCF نیست و به کارآیی بیشتری حین استفاده مستقیم از بانک اطلاعاتی خواهید رسید. WCF برای معماری چند tier توصیه می‌شود (هر tier رو یک سرور در اینجا فرض کنید. یک سرور جدای وب، یک سرور جدای اس کیوال و الی آخر ....)
4- BLL همان لایه سرویسی‌است که عنوان کردم. جایی که از EF استفاده می‌شود.
5- بله.

این M در MVC مرتبط با ASP.NET MVC جای بحث زیاد دارد. بیشتر ViewModel است تا Model به معنای Domain Classes .
‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۴:۰۳
اولین StudentRepository را که نوشته، بله. در اینجا Unit of work را نقض کرده.
ولی درادامه ... خیر (زمانیکه UnitOfWork را ارائه داده). ولی کار اضافی انجام داده.
بینید در کلاس UnitOfWork کار وهله سازی Context انجام شده. بنابراین درست است. در همین کلاس هم Save قرار دارد بنابراین درست عمل شده و می‌شود با این سیستم یک تراکنش را انجام داد. ضمنا در این کلاس Uow کار معرفی Repository ها رو انجام داده.
ولی ... خود Context اصلی هم این موارد را دارد (خودش Uow است. کلاس مشتق شده از آن دارای DbSet‌ است). شما به چه نتیجه‌ای از این Abstraction بی‌مورد خواهید رسید؟ احتمالا دو مورد عنوان شده در بالا ... که توضیح دادم در عمل هیچ وقت رخ نخواهد داد.
‫۱۲ سال و ۵ ماه قبل، دوشنبه ۲۵ اردیبهشت ۱۳۹۱، ساعت ۱۳:۵۴
اون پیاده سازی هم اشتباه است! چون متد Save داخل خود Repository است.
ضمنا اون مطالب رو بر اساس اطلاعات آن روز نوشتم. الان هم پیاده سازی UOW و Repository کاملی رو از NH‌ دارم ولی ... هیچ وقت NH رو در پروژه‌ای که از آن استفاده کردم، تغییر ندادم یا از آن repository برای Unit testing استفاده نکردم.
وابستگی به ORM در عمل زیاد خواهد بود. بنابراین تعویض آن غیرممکن می‌شود.
استفاده از بانک اطلاعاتی واقعی بهتر است و به همین جهت دو کاربردی که برای آن در اکثر سایت‌ها ذکر شده، در عمل استفاده نمی‌شود.
بنابراین استفاده از Repository صرفا پیچیدگی بی‌موردی را به سیستم تحمیل می‌کند.