مطالب
مجوز WTFPL

در بین مجوز‌های سورس باز، یکی از اون‌ها که اتفاقا مورد پذیرش FSF هم هست، عنوان جالبی داره که ترجمه‌اش به فارسی می‌شود: "برو هر غلطی که دلت می‌خواد باهاش بکن!" یا WTFPL = Do What The F.u.c.k You Want To Public License
نگارش یک این مجوز توسط Banlu Kemiyatorn نویسنده برنامه Window maker در سال 2000 ارائه شده و در سال 2007 توسط مدیر پروژه تیم Debian نگارش دوم آن ارائه گردیده است!
این مجوز به شما اجازه هر نوع تغییر یا هر روش توزیعی را در مورد برنامه‌ی مورد نظر می‌دهد.
ترجمه این مجوز هم به زبان فارسی به صورت زیر است:

"
مجوز برو هر غلطی که دلت می‌خواد بکن!
نگارش 2، دسامبر 2004

هر کسی مجاز است این مستند را کپی یا توزیع کند با این شرط که اگر تغییری در اصل آن داده شد، نامش را تغییر دهد.
شروط اصلی این مجوز به شرح ذیل اعلام می‌گردد:
0- فقط برو هر غلطی که دلت می‌خواد باهاش بکن

"

البته شاید این سؤال پیش بیاد که این موارد به چه دلیلی اضافه شده؟ احتمالا شاید شنیده باشید که عده‌ای GPL‌ رو یک نوع سرطان می‌دونند؛ از این لحاظ که اگر طرف اون رفتید باید کل برنامه خودتون رو سورس باز ارائه بدید. به همین جهت کسانی که کار تجاری انجام می‌دهند از طرف سورس‌های پروژه‌های مبتنی بر GPL رد هم نمی‌شوند. در مقابل آن مجوزهایی مانند BSD یا MIT ملاحظات GPL را ندارند (+). در کل GPL تا به امروز لینوکس را زنده نگه داشته است.

مطالب
سیستم‌های توزیع شده در NET. - بخش پنجم - اهداف
در بخشهای قبل، دلایل بوجود آمدن سیستمهای توزیع شده بررسی شد و تاکید کردیم که نیازمندی‌ها، باعث تغییر و تکامل سیستمهای ما می‌شوند و بر همین اساس بررسی کردیم که چه نیازمندی‌هایی باعث می‌شوند که دیگر سیستم‌های متمرکز به تنهایی پاسخگوی نیازهای ما نباشند و عاملی شوند برای رفتن به سمت سیستمهای توزیع شده. گفتیم که اتخاذ تصمیمات نادرست چه عواقبی را برای سیستمهای ما بوجود می‌آورد و بر همین اساس مهمترین فاکتورها را در انتخاب سیستم‌های توزیع شده، به شما معرفی کردیم. تعاریف مختلفی از این نوع سیستم‌ها را در اختیار شما قرار دادیم؛ خصوصیات، مزایا و معایب سیستمهای توزیع شده را به شما معرفی کردیم، تا با دید باز، یک انتخاب درست را با کمترین میزان ریسک انجام دهیم.
در این بخش ما 4 هدف اصلی را که باید در سیستم‌های توزیع شده برآورده شوند، بر اساس ارزش آنها مورد بررسی قرار می‌دهیم. یک سیستم توزیع شده باید اولا منابع را به آسانی در دسترس کاربران قرار دهد. دوما شفاف باشد و تمام پیچیدگی‌های یک سیستم توزیع شده را از دید کاربر، مخفی کند. سوما باز و قابل گسترش باشد؛ بصورتیکه به آسانی و با شفافیت کامل بتوانیم اجزای جدیدی را به آن اضافه کنیم. چهارما مقیاس پذیر باشد؛ بصورتیکه بدون اینکه مشکلی برای سیستم بوجود بیاید، بتوانیم منابع موجود سیستم را افزایش دهیم. در این بخش جزئیات هر یک از این اهداف را مورد بررسی قرار می‌دهیم.


اهداف سیستم‌های توزیع شده

1- Connecting resources and users: مشخص‌ترین و اصلی‌ترین هدف سیستم‌های توزیع شده، اتصال کاربران به منابع و اشتراک منابع بصورت کنترل شده با کارآیی بالا برای کاربران است. به‌صورتیکه کاربران  به آسانی به منابع دسترسی داشته باشند. منظور از منابع، هرچیزی در سیستمهای توزیع شده می‌تواند باشد. منابعی مانند داده‌ها، سخت‌افزارها، فایلها، Componentها، زیرسیستمها و هر چیز دیگری که کاربران می‌توانند بصورت مستقیم و غیر مستقیم به آنها دسترسی داشته باشند. یکی از مهمترین دلایل دسترسی به این هدف، مسائل اقتصادی است. بطور مثال ممکن است ما سیستم خودمان را طوری طراحی کنیم که پردازش‌های بسیار مهم و پیچیده در تعدادی از سخت افزار‌های بسیار پر هزینه انجام شوند. به این صورت ما این سخت افزارها را برای سایر قسمت‌های سیستم، به اشتراک میگزاریم و از طریق دیگر قسمتهای سیستم، دسترسی آن را به کاربران می‌دهیم. در این حالت دیگر نیازی نیست هر قسمت جداگانه در سیستم، سخت افزاری بسیار قوی را برای خودش نیاز داشته باشد. یا زمانیکه ما یک زیرسیستم را یکبار پیاده سازی می‌کنیم و دسترسی آن را به سایر قسمت‌ها میدهیم، سایر سیستمها، دیگر نیازی نیست آن زیرسیستم را برای خودشان پیاده سازی کنند و تنها از زیرسیستم موجود استفاده می‌کنند. دسترسی به این هدف باعث می‌شود تا کاربران به راحتی به تمام منابع موجود در سیستم‌های توزیع شده دسترسی داشته باشند.

2- Distribution transparency: بدلیل پیچیدگی‌های بسیار زیاد در سیستم‌های توزیع شده، شفافیت، کمک بسیار بزرگی به سادگی نحوه تعامل کاربر با سیستم‌های توزیع شده می‌کند. شفافیت در سیستم‌های توزیع شده بدین معنا است که سیستم باید تمام پیچیدگی‌های خود را از دید کاربر مخفی کند و پیاده سازی سیستم بصورت توزیع شده نباید هیچ پیچیدگی را در نحوه تعامل کاربر با سیستم بوجود بیاورد.
درواقع در سیستمهای توزیع شده، درخواست دریافت شده، در بین منابع سیستم توزیع می‌شود. تمام منابع با همکاری که با یکدیگر انجام می‌دهند، درخواست مورد نظر را پردازش کرده و پاسخ لازم را به کاربر ارائه می‌دهند. در این بین ممکن است منابع موجود در سیستم، رفتارهای متفاوتی را داشته باشند؛ مثلا هر زیرسیستم در سخت افزار و سیستم عامل جداگانه‌ای اجرا شود که باعث می‌شود حتی نحوه دستیابی به فایل‌ها یا داده‌های هر زیرسیستم نیز با سایر زیرسیستمها متفاوت باشد. شفافیت در سیستمهای توزیع شده بدین معنا است که یک سیستم توزیع شده باید خود را به‌صورت یک سیستم واحد که در یک سخت افزار ارائه می‌شود، ارائه دهد تا کاربران هیچ نگرانی در نحوه تعامل با سیستم نداشته باشند. شفافیت در سیستمهای توزیع شده جنبه‌های مختلفی دارد که در این قسمت آنها را بررسی می‌کنیم.


جنبه‌های مختلف شفافیت در سیستم‌های توزیع شده

1- Access Transparency: شفافیت در دسترسی به منابع یا مخفی کردن پیچیدگی‌ها و روشهای مختلف دسترسی به منابع. زیر سیستم‌های متفاوت ممکن است در سیستم عامل‌های متفاوتی نیز اجرا شوند و همانطور که می‌دانید هر سیستم عامل ممکن است نحوه دسترسی به منابعش با سایر سیستم عامل‌ها متفاوت باشد. در اینجا ما باید زیر سیستم‌های خود را طوری طراحی کنیم تا این تفاوت‌های در نحوه دسترسی به منابع را از دید کاربر مخفی کنند و این حس را به کاربر بدهد که سیستم، یک روش واحدی را برای دسترسی به منابع دارد.

2- Location Transparency: شفافیت در مکان منابع و مخفی کردن اینکه منابع در سطح شبکه توزیع شده‌اند. این جنبه بیان می‌کند که کاربران نمی‌توانند بگویند که منابع بصورت فیزیکی در سخت افزار‌های متفاوتی توزیع شده‌اند.کاربران هیچ درکی از اینکه ممکن است منابع حتی بصورت جغرافیایی در مکان‌های بسیار دوری از یکدیگر قرار گرفته‌اند، ندارند.

3- Migration Transparency: مخفی کردن اینکه ممکن است مکان منابع تغییر یابند. در یک سیستم توزیع شده ممکن است به هر دلیلی، مکان منابع تغییر کند. بطور مثال ممکن است با افزایش داده‌ها نیاز به افزودن Node جدیدی به سیستم باشد تا قسمتی از داده‌های سیستم از این پس از طریق این Node در دسترس باشند. این جابجایی منابع نباید هیچ تاثیری در نحوه‌ی تعامل کاربر داشته باشد.

4- Relocation Transparency: مخفی کردن اینکه منابع ممکن است در زمان استفاده، تغییر مکان دهند. در این حالت دقیقا در زمانیکه شخص در حال استفاده از منابع است ممکن است منابع جابجا شوند که این جابجایی در زمان استفاده از منابع نباید هیچ تاثیری در نحوه تعامل کاربر با سیستم داشته باشد. بطور مثال زمانیکه دو کاربر از طریق تلفن همراه در حال ارسال اطلاعات برای یکدیگر هستند، جابجایی هر یک از این دو کاربر، نباید تاثیری در جریان ارتباطی آنها داشته باشد.

5- Replication Transparency: مخفی کردن اینکه منابع در چند جا کپی شده‌اند. در یک سیستم توزیع شده برای بهبود کارآیی و دسترسی ممکن است منابع در چند جای مختلف کپی شوند و شفافیت در Replication می‌گوید ما باید این واقعیت را که ممکن است منابع ما در سخت افزارهای مختلفی کپی شده باشند، از دید کاربر مخفی کنیم.

6- Concurrency Transparency: مخفی کردن اینکه ممکن است منابع، بین چند کاربر مشترک باشند. بدلیل بالا بودن تعداد کاربران در سیستمهای توزیع شده، همزمانی در دسترسی به منابع مشترک، بسیار بیشتر اتفاق می‌افتد و این مهم است که هیچ یک از کاربران ندانند که کاربر دیگری بصورت همزمان در حال استفاده از آن داده است.

7- Failure Transparency: مخفی کردن خرابی و بازیابی منابع یک سیستم توزیع شده، از کاربر. در یک سیستم توزیع شده ممکن است منابع به هر دلیلی از دسترس خارج شوند. در این صورت نباید از دسترس خارج شدن منابع و بازیابی آنها هیچ تاثیری در جریان تعامل کاربر با سیستم داشته باشد.


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



3- Openness: باز بودن یا قابل گسترش بودن سیستم‌های توزیع شده یکی دیگر از اهداف بسیار مهم این سیستمها می‌باشد. به این صورت که یک سیستم در حال اجرا باید توانایی اضافه کردن منابع جدید را داشته باشد. بطور مثال با افزوده شدن نیازمندی‌های جدید، نیاز می‌شود که یک زیر سیستم جدید یا Component جدید را پیاده سازی کنیم. قسمت جدید به راحتی و بدون تاثیر در جریان تعامل کاربر باید بتواند به سیستم اضافه شود. در اکثر موارد این هدف با استفاده از یکسری قراردادهای مشخص که تمامی زیر سیستم‌ها آنها را می‌شناسند و رعایت می‌کنند، محقق می‌شود.

4- Scalability: مقیاس پذیری سیستم‌های توزیع شده بدین معنی است که با رشد مواردی مانند تعداد پردازش و درخواست یا موقعیت جغرافیایی کاربران، سیستم قادر باشد بدون تاثیر بر جریان تعامل کاربر با سیستم، آنها را پوشش دهد. یعنی بطور مثال زمانیکه تعداد درخواست‌های کاربران سیستم افزایش می‌یابد، با Replicate قسمتهای موجود سیستم در سخت افزار‌های جدید می‌توانیم بار پردازشی را بین تعداد بیشتری از Node‌ها تقسیم کنیم. به این صورت سیستم می‌تواند بدون از دسترس خارج شدن، تعداد بیشتری از درخواستهای کاربران را پوشش دهد. یا زمانیکه قرار است موقعیت‌های جدید جغرافیایی را سیستم پوشش دهد، با اضافه کردن منابع مورد نیاز، در آن موقعیت جغرافیایی، سیستم قادر است نیاز کاربران آن مکان جغرافیایی را برآورده کند.


 تا به این قسمت از سری مقالات سیستم‌های توزیع شده، هدف من این بوده که با چرایی وجود این نوع از سیستم‌ها و نحوه‌ی انتخاب آنها و اهداف سیستم‌های توزیع شده آشنا شوید. در بخش‌های بعد، روشهای مختلف طراحی و پیاده سازی سیستم‌های توزیع شده را مورد بررسی قرار می‌دهیم و می‌بینیم که چه ابزارهایی برای پیاده سازی سیستم‌های توزیع شده در NET. وجود دارند و با توجه به نوع کارآیی هر یک از این ابزارها، آنها را بصورت جداگانه مورد استفاده قرار می‌دهیم تا با مزایا و معایب هریک آشنا شویم. البته این را نیز ذکر کنم که با توجه به تعاریف سیستم‌های توزیع شده، انواع مختلفی از سیستم‌های توزیع شده وجود دارند که ما از قبل با برخی از آنها آشنا هستیم؛ معماری‌هایی مانند Client/Server یا N-Tier  نمونه‌هایی از سیستم‌های توزیع شده هستند که در آنها وظایف، در سخت افزارهای متفاوتی تقسیم شده و ارتباط هر قسمت از طریق سرویس‌هایی که ما پیاده سازی می‌کنیم، صورت می‌پذیرد و به دلیل اینکه مطمئنا همه شما با نحوه طراحی و پیاده سازی آنها و نحوه ارتباط قسمتهای مختلف آنها آشنا هستید، در سری مقالات سیستمهای توزیع شده در NET.، دیگر نیازی به توضیحی در مورد آنها نمی‌باشد. هدف من از قسمت‌های مرتبط با پیاده سازی سیستم‌های توزیع شده، چگونگی تکامل معماری‌هایی مانند N-Tier بوسیله ابزارهایی است که با هدف دستیابی به خصوصیات و اهداف سیستم‌های توزیع شده بوجود آمده‌اند.  
نظرات مطالب
راحت بگویید نه!

در مورد «ما بیکار ننشسته ایم» واقعیت این است که کارهای برنامه نویسی یک سیستم بعد از یک مدت به پایان می‌رسند و مابقی آن نگهداری است. این فاز نگهداری آنچنان هیجان انگیز نیست. هر روز کار نداره. شاید هفته‌ای یکی دو تغییر اگر ارجاع شوند. اینطوری مدیر شرکت فکر می‌کنه داره زیادی حقوق می‌ده. چون شما که به ظاهر کاری نمی‌کنی. یا به همین دلیل (من دارم بهت حقوق می‌دم ...) اینقدر تغییرات بی‌ربط رو به سیستم تحمیل می‌کنه که دست آخر شیرازه سیستم از هم می‌پاشه. نمونه دیگرش بحث شبکه هست. کار شبکه که تموم شد، مگر مابقی آن چقدر کار دارد؟ حداکثر این است که یک نفر را بگذارند یوزر تعریف کند، دسترسی بدهد. همین. اینجا است که کار کارمندی با رویه کار IT آنچنان جور درنمیاد. ولی همین نگهداری سیستم هم کار هر کسی نیست. این رو هم خیلی‌ها نمی‌تونند درک کنند.

در کل به نظر من برنامه نویس‌ها نباید خودشون رو درگیر کار کارمندی کنند تا بخواهند با این نوع مسایل سر و کله بزنند و اثبات کنند که وجودشان واقعا ضروری است و اگر در مورد آن‌ها هزینه‌ای انجام می‌شود، دور ریخته نشده.

You’re a Developer, So Why Do You Work For Someone Else  

مطالب
شروع به کار با DNTFrameworkCore - قسمت 1 - معرفی و نحوه استفاده از آن

پروژه DNTFrameworkCore  که قصد پشتیبانی از آن را دارم، یک زیرساخت سبک وزن و توسعه پذیر با پشتیبانی از طراحی چند مستاجری، با تمرکز بر کاهش زمان و افزایش کیفیت توسعه سیستم‌های تحت وب مبتنی بر ASP.NET Core، توسعه داده شده است. 


اهدافی که این زیرساخت دنبال می‌کند

  • ارائه ساختارهای مشترک بین پروژه‌های مختلف از جمله Cross-Cutting Concern‌ها و ...
  • دنبال کردن اصل DRY به منظور متمرکز شدن صرف برروی منطق تجاری سیستم نه انجام و حل یکسری مسائل تکراری
  • کاهش زمان توسعه و اختصاص زمان بیشتر برای نوشتن آزمون‌های واحد منطق تجاری
  • کاهش باگ و جلوگیری از پخش شدن باگ‌های پیاده سازی در سراسر سیستم
  • کاهش زمان آموزش نیروهای جدید برای ملحق شدن به تیم تولید شما با حداقل دانش طراحی و برنامه نویسی شیء گرا
  • ارائه راهکاری یکپارچه برای توسعه پذیر بودن منطق تجاری پیاده سازی شده از طریق در معرض دید قرار دادن یکسری «Extensibility Point» با استفاده از رویکرد Event-Driven


امکانات این زیرساخت در زمان نگارش مطلب جاری


نحوه استفاده از بسته‌های نیوگت مرتبط

PM> Install-Package DNTFrameworkCore -Version 1.0.0
 services.AddDNTFramework()
     .AddDataAnnotationValidation()
     .AddModelValidation()
     .AddValidationOptions(options =>
     {
         /*options.IgnoredTypes.Add(typeof());*/
     })
     .AddMemoryCache()
     .AddAuditingOptions(options =>
     {
         // options.Enabled = true;
         // options.EnabledForAnonymousUsers = false;
         // options.IgnoredTypes.Add(typeof());
         // options.Selectors.Add(new NamedTypeSelector("SelectorName", type => type == typeof()));
     }).AddTransactionOptions(options =>
     {
         // options.Timeout=TimeSpan.FromMinutes(3);
         //options.IsolationLevel=IsolationLevel.ReadCommitted;
     });

متدهای الحاقی بالا برای ثبت سرویس‌ها و تنظیمات مرتبط با مکانیزم‌های اعتبارسنجی خودکار، مدیریت تراکنش‌ها، لاگ آماری، Eventing و سایر امکانات ذکر شده، در IoC Container  توکار ASP.NET Core استفاده خواهند شد.

PM> Install-Package DNTFrameworkCore.EntityFramework -Version 1.0.0
services.AddDNTUnitOfWork<ProjectDbContext>();

‎بسته نیوگت بالا شامل پیاده سازی مبتنی بر EF Core برای واسط‌های تعریف شده در بسته نیوگت DNTFrameworkCore، می‌باشد؛ از جمله آن می‌توان به CrudService پایه اشاره کرد.  متد الحاقی AddDNTUnitOfWork برای ثبت و معرفی واسط‌های IUnitOfWork و ITransactionProvider به عنوان مهیا کننده تراکنش به همراه پیاده سازهای آنها و همچنین ثبت یک سری Hook تعریف شده برای ردیابی تغییرات، در سیستم تزریق وابستگی، استفاده خواهد شد.

همچنین با نصب بسته بالا، امکان استفاده از مهیا کننده Logging با امکان ذخیره سازی در بانک اطلاعاتی را خواهید داشت:

 public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseDefaultServiceProvider((context, options) =>
                {
                    options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
                })
                .ConfigureLogging((hostingContext, logging) =>
                {
                    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                    logging.AddConsole();
                    logging.AddDebug();
                    logging.AddEntityFramework<ProjectDbContext>(options => options.MinLevel = LogLevel.Warning);
                })
                .UseStartup<Startup>();

متد جنریک الحاقی AddEntityFramework برای ثبت مهیا کننده مذکور استفاده می‌شود. 

PM> Install-Package DNTFrameworkCore.Web -Version 1.0.0

بسته نیوگت بالا شامل یکسری سرویس برای اعمال دسترسی‌های پویا، CrudController مبتنی بر ASP.NET Core Web API، فیلتر مدیریت سراسری خطاهای برنامه و سایر امکاناتی که در ادامه مقالات با جزئیات بیشتری بررسی خواهیم کرد، می‌باشد. برای ثبت سرویس‌های تعریف شده می‌توانید از متد الحاقی AddDNTCommonWeb و به منظور تغییر محل ذخیره سازی کلیدهای موقت رمزنگاری مرتبط با Data Protection API و انتقال آنها به بانک اطلاعاتی، استفاده کنید. 

services.AddDNTCommonWeb()
    .AddDNTDataProtection();

نکته: برای انتقال کلیدهای موقت رمزنگاری به بانک اطلاعاتی، نیاز است تا از متد الحاقی زیر که در بسته نیوگت DNTFrameworkCore.EntityFramework موجود می‌باشد، به شکل زیر استفاده کنید:

services.AddDNTProtectionRepository<ProjectDbContext>();

‎‎

اگر نیاز به شماره گذاری خودکار دارید، بسته زیر را نیز می‌بایست نصب کنید:
PM> Install-Package DNTFrameworkCore.EntityFramework.SqlServer -Version 1.0.0

بسته بالا از امکانات مخصوص SqlServer برای اعمال قفل منطقی برای مدیریت مباحث همزمانی استفاده می‌کند؛ همچنین PreUpdateHook مرتبط با تولید خودکار کد منحصر به فرد، در این کتابخانه پیاده سازی شده است. به شکل زیر می‌توانید سرویس‌های مرتبط با آن را به سیستم تزریق وابستگی‌های معرفی کنید:

services.AddDNTNumbering(options =>
{
    options.NumberedEntityMap[typeof(Task)] = new NumberedEntityOption
    {
        Start = 100,
        Prefix = "Task-",
        IncrementBy = 5
    };
});

‎‎به عنوان مثال برای شماره گذاری موجودیت Task، لازم است تنظیمات مرتبط آن را به شکل بالا به سیستم شماره گذاری معرفی کنید.

اگر قصد استفاده از کتابخانه FluentValidation را داشته باشید، می‌بایست بسته زیر را نیز نصب کنید:

PM> Install-Package DNTFrameworkCore.FluentValidation -Version 1.0.0  

برای ثبت و معرفی Adapter مرتبط، به سیستم اعتبارسنجی خودکار معرفی شده، لازم است از طریق متد الحاقی AddFluentModelValidation به شکل زیر اقدام کنید:

 services.AddDNTFramework()
     .AddDataAnnotationValidation()
     .AddModelValidation()
     .AddFluentModelValidation()
     .AddValidationOptions(options =>
     {
         /*options.IgnoredTypes.Add(typeof());*/
     })
     .AddMemoryCache()
     .AddAuditingOptions(options =>
     {
         // options.Enabled = true;
         // options.EnabledForAnonymousUsers = false;
         // options.IgnoredTypes.Add(typeof());
         // options.Selectors.Add(new NamedTypeSelector("SelectorName", type => type == typeof()));
     }).AddTransactionOptions(options =>
     {
         // options.Timeout=TimeSpan.FromMinutes(3);
         //options.IsolationLevel=IsolationLevel.ReadCommitted;
     });

‎‎

برای شروع پروژه جدید، نصب این بسته‌ها کفایت می‌کند. اگر نیاز به طراحی MultiTenancy دارید، بسته زیر را برای شناسایی Tenant جاری و از این قبیل کارها نیز می‌بایست نصب کنید:

PM> Install-Package DNTFrameworkCore.Web.MultiTenancy -Version 1.0.0
برای ثبت و معرفی ITenantResolver شخصی سازی شده خود، می‌توانید از متد الحاقی زیر استفاده کنید:
services.AddMultiTenancy<TenantResolver>();
همچنین نیاز است با استفاده از متد الحاقی زیر، Middleware تعریف شده در کتابخانه را به «HTTP Request Pipeline» سیستم معرفی کرده و ثبت کنید:
app.UseMultiTenancy();
نکته: بسته نیوگت DNTFrameworkCore.Web.MultitTenancy به منظور مهیا کردن طول عمر Tenant-Singleton، وابستگی به کتابخانه StructureMap نیز دارد. البته این بسته نیاز به بهبود هم دارد که در ادامه اعمال خواهد شد. همچنین امضای متدهای الحاقی بالا، در انتشارهای بعدی به AddDNTMultiTenancy و UseDNTMultiTenancy تغییر خواهند کرد.
در نهایت به منظور تزئین خودکار و پویای سرویس‌های برنامه برای اعمال یکسری Cross-Cutting Concern معرفی شده در بالا، از جمله اعتبارسنجی ورودی‌ها، مدیریت تراکنش‌ها و ... می‌توانید پس از ثبت و معرفی سرویس‌های خود به سیستم تزریق وابستگی توکار، با استفاده از Interceptor‌های پیاده سازی شده در زیرساخت، به شکل زیر اقدام کنید:
services.Scan(scan => scan
    .FromCallingAssembly()
    .AddClasses(classes => classes.AssignableTo<ISingletonDependency>())
    .AsMatchingInterface()
    .WithSingletonLifetime()
    .AddClasses(classes => classes.AssignableTo<IScopedDependency>())
    .AsMatchingInterface()
    .WithScopedLifetime()
    .AddClasses(classes => classes.AssignableTo<ITransientDependency>())
    .AsMatchingInterface()
    .WithTransientLifetime()
    .AddClasses(classes => classes.AssignableTo(typeof(IDomainEventHandler<>)))
    .AsImplementedInterfaces()
    .WithTransientLifetime());

foreach (var descriptor in services.Where(s => typeof(IApplicationService).IsAssignableFrom(s.ServiceType))
    .ToList())
{
    services.Decorate(descriptor.ServiceType, (target, serviceProvider) =>
        ProxyGenerator.CreateInterfaceProxyWithTargetInterface(
            descriptor.ServiceType,
            target, serviceProvider.GetRequiredService<ValidationInterceptor>(),
            (IInterceptor) serviceProvider.GetRequiredService<TransactionInterceptor>()));
}
به عنوان مثال در اینجا از ValidationInterceptor و TransactionInterceptor استفاده شده است.

پروژه نمونه‌ای هم برای نمایش امکانات زیرساخت را از اینجا می توانید دریافت کنید.
آزمون‌های واحد مرتبط با قسمت هایی از این زیرساخت را نیز می‌توانید در اینجا مشاهده کنید.
مطالب
EF Code First #8

ادامه بحث بررسی جزئیات نحوه نگاشت کلاس‌ها به جداول، توسط EF Code first


استفاده از Viewهای SQL Server در EF Code first

از Viewها عموما همانند یک جدول فقط خواندنی استفاده می‌شود. بنابراین نحوه نگاشت اطلاعات یک کلاس به یک View دقیقا همانند نحوه نگاشت اطلاعات یک کلاس به یک جدول است و تمام نکاتی که تا کنون بررسی شدند، در اینجا نیز صادق است. اما ...
الف) بر اساس تنظیمات توکار EF Code first، نام مفرد کلاس‌ها، حین نگاشت به جداول، تبدیل به اسم جمع می‌شوند. بنابراین اگر View ما در سمت بانک اطلاعاتی چنین تعریفی دارد:
Create VIEW EmployeesView
AS
SELECT id,
FirstName
FROM Employees

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

using System.ComponentModel.DataAnnotations;

namespace EF_Sample04.Models
{
[Table("EmployeesView")]
public class EmployeesView
{
public int Id { set; get; }
public string FirstName { set; get; }
}
}

در اینجا به کمک ویژگی Table، نام دقیق این View را در بانک اطلاعاتی مشخص کرده‌ایم. به این ترتیب تنظیمات توکار EF بازنویسی خواهد شد و دیگر به دنبال EmployeesViews نخواهد گشت؛ یا جدول متناظر با آن‌را به صورت خودکار ایجاد نخواهد کرد.
ب) View شما نیاز است دارای یک فیلد Primary key نیز باشد.
ج) اگر از مهاجرت خودکار توسط MigrateDatabaseToLatestVersion استفاده کنیم، پیغام خطای زیر را دریافت خواهیم کرد:

There is already an object named 'EmployeesView' in the database.

علت این است که هنوز جدول dbo.__MigrationHistory از وجود آن مطلع نشده است، زیرا یک View، خارج از برنامه و در سمت بانک اطلاعاتی اضافه می‌شود.
برای حل این مشکل می‌توان همانطور که در قسمت‌های قبل نیز عنوان شد، EF را طوری تنظیم کرد تا کاری با بانک اطلاعاتی نداشته باشد:

Database.SetInitializer<Sample04Context>(null);

به این ترتیب EmployeesView در همین لحظه قابل استفاده است.
و یا به حالت امن مهاجرت دستی سوئیچ کنید:
Add-Migration Init -IgnoreChanges
Update-Database

پارامتر IgnoreChanges سبب می‌شود تا متدهای Up و Down کلاس مهاجرت تولید شده، خالی باشد. یعنی زمانیکه دستور Update-Database انجام می‌شود، نه Viewایی دراپ خواهد شد و نه جدول اضافه‌ای ایجاد می‌گردد. فقط جدول dbo.__MigrationHistory به روز می‌شود که هدف اصلی ما نیز همین است.
همچنین در این حالت کنترل کاملی بر روی کلاس‌های Up و Down وجود دارد. می‌توان CreateTable اضافی را به سادگی از این کلاس‌ها حذف کرد.

ضمن اینکه باید دقت داشت یکی از اهداف کار با ORMs، فراهم شدن امکان استفاده از بانک‌های اطلاعاتی مختلف، بدون اعمال تغییری در کدهای برنامه می‌باشد (فقط تغییر کانکشن استرینگ، به علاوه تعیین Provider جدید، باید جهت این مهاجرت کفایت کند). بنابراین اگر از View استفاده می‌کنید، این برنامه به SQL Server گره خواهد خورد و دیگر از سایر بانک‌های اطلاعاتی که از این مفهوم پشتیبانی نمی‌کنند، نمی‌توان به سادگی استفاده کرد.



استفاده از فیلدهای XML اس کیوال سرور

در حال حاضر پشتیبانی توکاری توسط EF Code first از فیلدهای ویژه XML اس کیوال سرور وجود ندارد؛ اما استفاده از آن‌ها با رعایت چند نکته ساده، به نحو زیر است:

using System.ComponentModel.DataAnnotations;
using System.Xml.Linq;

namespace EF_Sample04.Models
{
public class MyXMLTable
{
public int Id { get; set; }

[Column(TypeName = "xml")]
public string XmlValue { get; set; }

[NotMapped]
public XElement XmlValueWrapper
{
get { return XElement.Parse(XmlValue); }
set { XmlValue = value.ToString(); }
}
}
}


در اینجا توسط TypeName ویژگی Column، نوع توکار xml مشخص شده است. این فیلد در طرف کدهای کلاس‌های برنامه، به صورت string تعریف می‌شود. سپس اگر نیاز بود به این خاصیت توسط LINQ to XML دسترسی یافت، می‌توان یک فیلد محاسباتی را همانند خاصیت XmlValueWrapper فوق تعریف کرد. نکته‌ دیگری را که باید به آن دقت داشت، استفاده از ویژگی NotMapped می‌باشد، تا EF سعی نکند خاصیتی از نوع XElement را (یک CLR Property) به بانک اطلاعاتی نگاشت کند.

و همچنین اگر علاقمند هستید که این قابلیت به صورت توکار اضافه شود، می‌توانید اینجا رای دهید!



نحوه تعریف Composite keys در EF Code first

کلاس نوع فعالیت زیر را درنظر بگیرید:

namespace EF_Sample04.Models
{
public class ActivityType
{
public int UserId { set; get; }
public int ActivityID { get; set; }
}
}

در جدول متناظر با این کلاس، نباید دو رکورد تکراری حاوی شماره کاربری و شماره فعالیت یکسانی باهم وجود داشته باشند. بنابراین بهتر است بر روی این دو فیلد، یک کلید ترکیبی تعریف کرد:

using System.Data.Entity.ModelConfiguration;
using EF_Sample04.Models;

namespace EF_Sample04.Mappings
{
public class ActivityTypeConfig : EntityTypeConfiguration<ActivityType>
{
public ActivityTypeConfig()
{
this.HasKey(x => new { x.ActivityID, x.UserId });
}
}
}

در اینجا نحوه معرفی بیش از یک کلید را در متد HasKey ملاحظه می‌کنید.

یک نکته:
اینبار اگر سعی کنیم مثلا از متد db.ActivityTypes.Find با یک پارامتر استفاده کنیم، پیغام خطای «The number of primary key values passed must match number of primary key values defined on the entity» را دریافت خواهیم کرد. برای رفع آن باید هر دو کلید، در این متد قید شوند:

var activity1 = db.ActivityTypes.Find(4, 1);

ترتیب آن‌ها هم بر اساس ترتیبی که در کلاس ActivityTypeConfig، ذکر شده است، مشخص می‌گردد. بنابراین در این مثال، اولین پارامتر متد Find، به ActivityID اشاره می‌کند و دومین پارامتر به UserId.


بررسی نحوه تعریف نگاشت جداول خود ارجاع دهنده (Self Referencing Entity)

سناریوهای کاربردی بسیاری را جهت جداول خود ارجاع دهنده می‌توان متصور شد و عموما تمام آن‌ها برای مدل سازی اطلاعات چند سطحی کاربرد دارند. برای مثال یک کارمند را درنظر بگیرید. مدیر این شخص هم یک کارمند است. مسئول این مدیر هم یک کارمند است و الی آخر. نمونه دیگر آن، طراحی منوهای چند سطحی هستند و یا یک مشتری را درنظر بگیرید. مشتری دیگری که توسط این مشتری معرفی شده است نیز یک مشتری است. این مشتری نیز می‌تواند یک مشتری دیگر را به شما معرفی کند و این سلسله مراتب به همین ترتیب می‌تواند ادامه پیدا کند.
در طراحی بانک‌های اطلاعاتی، برای ایجاد یک چنین جداولی، یک کلید خارجی را که به کلید اصلی همان جدول اشاره می‌کند، ایجاد خواهند کرد؛ اما در EF Code first چطور؟

using System.Collections.Generic;

namespace EF_Sample04.Models
{
public class Employee
{
public int Id { set; get; }
public string FirstName { get; set; }
public string LastName { get; set; }

//public int? ManagerID { get; set; }
public virtual Employee Manager { get; set; }
}
}

در این کلاس، خاصیت Manager دارای ارجاعی است به همان کلاس؛ یعنی یک کارمند می‌تواند مسئول کارمند دیگری باشد. برای تعریف نگاشت‌ این کلاس به بانک اطلاعاتی می‌توان از روش زیر استفاده کرد:

using System.Data.Entity.ModelConfiguration;
using EF_Sample04.Models;

namespace EF_Sample04.Mappings
{
public class EmployeeConfig : EntityTypeConfiguration<Employee>
{
public EmployeeConfig()
{
this.HasOptional(x => x.Manager)
.WithMany()
//.HasForeignKey(x => x.ManagerID)
.WillCascadeOnDelete(false);
}
}
}

با توجه به اینکه یک کارمند می‌تواند مسئولی نداشته باشد (خودش مدیر ارشد است)، به کمک متد HasOptional مشخص کرده‌ایم که فیلد Manager_Id را که می‌خواهی به این کلاس اضافه کنی باید نال پذیر باشد. توسط متد WithMany طرف دیگر رابطه مشخص شده است.
اگر نیاز بود فیلد Manager_Id اضافه شده نام دیگری داشته باشد، یک خاصیت nullable مانند ManagerID را که در کلاس Employee مشاهده می‌کنید،‌ اضافه نمائید. سپس در طرف تعاریف نگاشت‌ها به کمک متد HasForeignKey، باید صریحا عنوان کرد که این خاصیت، همان کلید خارجی است. از این نکته در سایر حالات تعاریف نگاشت‌ها نیز می‌توان استفاده کرد، خصوصا اگر از یک بانک اطلاعاتی موجود قرار است استفاده شود و از نام‌های دیگری بجز نام‌های پیش فرض EF استفاده کرده است.




مثال‌های این سری رو از این آدرس هم می‌تونید دریافت کنید: (^)

مطالب
بازسازی کد: پنهان سازی delegate یا Hide delegate

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

در این نمودار تکه کدی مدل شده است که در آن ClientClass استفاده کننده از امکانات دو کلاس دیگر است. برای بدست آوردن مدیر یک شخص در این طراحی نیاز است ابتدا ClientClass اطلاعات مربوط به department یک شخص را با استفاده از متد GetDepartment بدست آورد. سپس با استفاده از متد GetManager در کلاس Department اقدام به دریافت اطلاعات مدیر نماید.

در طراحی بالا، برای دریافت اطلاعات مدیر یک فرد، با تکه کدی مانند زیر روبرو خواهیم شد:  

var manager = person.GetDepartment().GetManager();

یکی از اصلی‌ترین اصول طراحی کلاس‌ها، کپسوله سازی اعضای کلاس، از استفاده کنندگان بیرونی آن است. کپسوله سازی به این معنی است که کلاس کمترین نیاز را به اطلاع از دیگر بخش‌های سیستم داشته باشد. بنابراین در زمان تغییر آن بخش‌ها دیگر نیازی نیست کلاس استفاده کننده از ریز تغییرات اطلاع پیدا کند.

روش کلی بازسازی کد پنهان سازی delegate، ایجاد یک کلاس (یا استفاده از کلاس‌های موجود) به عنوان سرویس دهنده یا server است. در این کلاس به ازای کارکردهایی که نیاز به استفاده از چندین شیء یا متد را داشته باشند، یک متد ایجاد می‌کنیم. این متد روال لازم برای فراخوانی‌ها را خود مدیریت و پیاده سازی می‌کند.

در مثال ذکر شده‌ی در ابتدای نوشتار می‌توان کلاس سرویس دهنده‌ی کارکرد دریافت مدیر را کلاس Person دانست. با این ترتیب بازسازی کد، رابطه‌ی بین کلاس‌ها را به صورت زیر تغییر می‌دهد.  

با کمی توجه در نمودار می‌توان متوجه شد متد موجود در کلاس Person به متد GetManager تغییر کرده است. زیرا در این کارکرد برای دریافت مدیر به کلاس Person رجوع می‌کنیم و نیازی نیست مستقیما به کلاس Department رجوع کنیم. مدیریت کردن نحوه دریافت مدیر یک Person نیز بر عهده این متد است.

همچنین برای دریافت مدیر یک شخص با چنین تکه کدی روبرو خواهیم شد:  

var manager = person.GetManager();

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

پاسخ به بازخورد‌های پروژه‌ها
علت استفاده از کلاس ActivityLogType
با در نظر گرفتن همچین کلاسی میتوان امکان این را قرار داد که مدیر سایت هر وقت نیاز بود مثلا نوعی از لاگ‌ها رو غیر فعال کنه . 
برای مثال:
در جدول ActivityLogType رکورد‌های {Products,Categories,... } تحت عنوان گروه‌های لاگ فعالیت در نظر گرفته شده اند. این رکورد‌ها فیلدی به نام IsActive هم دارند که امکان تغییر آن به true /false وجود دارد. بیشتر به منظور Audit Log در نظر گرفته ام که امکان مدیریت پیشرفته ای را برای مدیر مهیا میکند.
نظرات مطالب
یکپارچه سازی Angular CLI و ASP.NET Core در VS 2017
برای توسعه پروژه در کل بهتر است پروژه‌ها رو یکی کنیم یا جدا از هم توسعه بدیم؟
و اگر جدا کنیم باید قسمت backend خاصیت EnableCors را فعال کنیم ؟  تنظیمات اضافه‌تر دیگری هم لازم دارد؟
مطالب
خواندنی‌های 27 فروردین

  • اولین محصول نگارش 2010 مایکروسافت برای دریافت، exchange server 2010 beta (میل سرور)
مطابق سایت رسمی فوق اینطور به نظر میرسه که مایکروسافت قصد جدا سازی برنامه‌ها و مفهوم Office Web applications را از SharePoint دارد (هر چند مانند سابق توانایی یکپارچگی بی‌نظیری بین آفیس و شپرپوینت وجود خواهد داشت)
سایر اولین سری محصولات 2010 ، شامل Microsoft Office 2010 ، Microsoft Visio 2010 و Microsoft Project 2010 خواهند بود.
  • لیستی از 70+145 برگه مرجعه (+ و +)
  • مجموعه انتشارات مایکروسافت 25 امین سالگرد تاسیس خود را جشن می‌گیرد. به همین منظور دو کتاب زیر را به رایگان برای دریافت قرار داده‌اند:

عنوانی رو که براش انتخاب کردن جالب است "the world's most advanced open source database"