#Developers_Best_Practices
در این پست بهترین کار هایی که یک توسه دهنده میتونه انجام بده رو معرفی میکنیم.💡
همیشه به دنبال Best Practices برای برنامه ها و تکنولوژی هایی که استفاده میکنیم بودیم و گاها فراموش میکنیم که یک برنامه نویس خوب یه کد خوب می نویسه . نه اینکه یک کد خوب یه برنامه نویس خوب بسازه. این روند یه روند از بالا به پایینه پس تا خودتون رو بهبود نبخشین خروجی مهارت هاتون هم آنچنان تغییری نمیکنه .
💎 Practice
تمرین
اول بیایین یاد بگیریم اصلا تمرین چه معنی میده ؟
آیا تمرین یه رفتاره یا یه روند تکراریه یا کارهایی که لازم نیس روزانه دائما بخاطر داشته باشین که حتما انجامش بدین و طبق عادت انجام میشه.
تیراندازی، رانندگی و نوشتن
همه مهارت های ذکر شده حاصل تمرین هستش وقتی شروع به رانندگی میکنین باید هر محله شو به خاطر بسپارین و قبل انجام هر کاری فکر کنین اما به محض اینکه موفق به انجام یک رانندگی خوب شدین ،دیگه لازم نیس هی دائما مراحل رو حفظ کنین. چون تبدیل به یک عادت و یک امر عادی برای شما میشه.
توسعه نرم افزار هم با مهارت های ذکر شده تفاوتی نداره و برای اینکه به یک توسعه دهنده موفق تبدیل بشین باید و باید تمرین کنین.
❇️ Keep Reading Existing Software Source Code
آیا اصلا کد های نرم افزار ها یا کتابخونه های دیگه رو که به صورت متن باز منتشر میشن میخونین؟
فقط تعداد اندکی از توسعه دهنده ها پاسخ مثبت به این سوال میدن چون خوندن کدها کار کسل کننده ایه. اگر شما هم این کار رو یه کار کسل کننده میدونین و انجامش نمیدین باید بهتون بگم مهم ترین کاری که یک توسعه دهنده میتونه تو زندگیش انجام بده رو دارین از دست میدین. برای مثال اگه بخواین رمان نویس بشین .آیا در عین واحد میتونین شروع به نوشتن رمان کنین؟ قطعا پاسخ نه هست. برای اینکه یک رمان نویس خوب بنویسین اول باید صد ها رمان بخونین.
❇️ Complete your documents before next step
یکی از بدترین کارهایی که یک توسعه دهنده میتونه انجام بده مستقیم سراغ کد رفتنه . قبل از انجام هر کاری ابتدا دانسته ها و مستندات خودتون رو در مورد اون کار تکمیل کنین و بعد به سراغ مرحله کد نوشتن برین .قبل از استفاده از هر ابزاری یا تکنولوژی اول مستنداتش رو بخونین و تست هاشو ببینین. اگه غیر از این عمل کنین، در مرحله بعد خودتون رو داخل یک مشکل بزرگ پیدا میکنین. اینو همیشه سر لوحه کارتون قرار بدین که Documentation is the Key
فراموش نکنین که چیزهایی که امروز یاد میگیرن شمارو برای فردا اماده میکنه.
❇️ Follow the defined standards, don't create it
این نکته خیلی مهمه که همیشه سعی کنین از استاندارد هایی که توسط همه پذیرفته شده پیروی کنید و سعی نکنین دورباره اون هارو بسازین . این استاندارد ها توسط دولوپر هایی با سالها تجربه تنظیم و ساخته شده و پیروی کردن از این استاندارد ها مثل این میمونه که دارین پا تو ردپایه بزرگ اونها میذارین.
❇️ Code should be written to be reviewed
فراموش نکنین که کد باید طوری نوشته بشه تا توسط دیگران یا بعدا خودتون قابل بررسی باشه
سعی کنین بعد از اینکه کدی رو مینویسین حداقل یکبار خودتون مرورش کنین و به نوعی تو ذهنتون کامپایلش کنین اینجوری تا 90% مشکلاتی که وجود داره یا ممکنه وجود بیاد رو خودتون حل میکنین. بعد از تمام این مراحل از یه نفر بخاین که کد شمار رو بررسی کنه و از این بابت که داره ایرادات کد شمارو متذکر میشه بسیار خوشحال و سپاسگذار باشین.
بررسی شدن کدتون حتی اگه کدتون ضعیف باشه توسط دیگران به شما می اموزه که یک کد قوی بنویسین به شرط اینکه از نکاتش درس بگیرین و اون رو مثبت بشمارین.
هدفتون از کد نویسی ابتدا جلوگیری از باگ باشه و نوشتن یه کد بدون باگ. مثل Tester ها فک کنین و اینطور فک کردن و کد نوشتن برای کسی هم که کدتون رو تست میکنه میتونه یه چالش باشه.
❇️ Testing to be followed like a religion
به تست کردن کدتون مثل دینتون پایبند باشین.کدهاتونو بعد از هر تغییر بزرگ و کوچیکی تست کنین و اصلا به اینکه از زمانبندی تون عقب میوفتین اهمیت ندین
یادتون باشه موقع طراحی نرم افزار چیزی به نام "اعتماد" وجود نداره .
از اینکه باگ ها رو تو کدتون پیدا میکنین ناراحت نباشین و برعکس جشنش بگیرین و اصلا از اینکه Tester تو کدتون باگ پیدا میکنه ناراحت نباشین فراموش نکین که :
باگ ها دشمن شما هستن و باید اونارو بکشین و اشتباه ها تازمانی خوب ان که اونها رو تکرار نکنین.
❇️ Keep your Code and Documents Safe
یه توسعه دهنده باهوش عادت داره که از کارهای روزانش backup بگیره ازطرف دیگه اگه سیستمون crash کنه و به طریقی کدهاتون از بین بره درواقع اونی که crash کرده و از بین رفته شمایین.
پس نهایتا توصیه ای که میشه اینکه حتما از سورس کنترل ها استفاده کنین.
@fullStackDevs
در این پست بهترین کار هایی که یک توسه دهنده میتونه انجام بده رو معرفی میکنیم.💡
همیشه به دنبال Best Practices برای برنامه ها و تکنولوژی هایی که استفاده میکنیم بودیم و گاها فراموش میکنیم که یک برنامه نویس خوب یه کد خوب می نویسه . نه اینکه یک کد خوب یه برنامه نویس خوب بسازه. این روند یه روند از بالا به پایینه پس تا خودتون رو بهبود نبخشین خروجی مهارت هاتون هم آنچنان تغییری نمیکنه .
💎 Practice
تمرین
اول بیایین یاد بگیریم اصلا تمرین چه معنی میده ؟
آیا تمرین یه رفتاره یا یه روند تکراریه یا کارهایی که لازم نیس روزانه دائما بخاطر داشته باشین که حتما انجامش بدین و طبق عادت انجام میشه.
تیراندازی، رانندگی و نوشتن
همه مهارت های ذکر شده حاصل تمرین هستش وقتی شروع به رانندگی میکنین باید هر محله شو به خاطر بسپارین و قبل انجام هر کاری فکر کنین اما به محض اینکه موفق به انجام یک رانندگی خوب شدین ،دیگه لازم نیس هی دائما مراحل رو حفظ کنین. چون تبدیل به یک عادت و یک امر عادی برای شما میشه.
توسعه نرم افزار هم با مهارت های ذکر شده تفاوتی نداره و برای اینکه به یک توسعه دهنده موفق تبدیل بشین باید و باید تمرین کنین.
❇️ Keep Reading Existing Software Source Code
آیا اصلا کد های نرم افزار ها یا کتابخونه های دیگه رو که به صورت متن باز منتشر میشن میخونین؟
فقط تعداد اندکی از توسعه دهنده ها پاسخ مثبت به این سوال میدن چون خوندن کدها کار کسل کننده ایه. اگر شما هم این کار رو یه کار کسل کننده میدونین و انجامش نمیدین باید بهتون بگم مهم ترین کاری که یک توسعه دهنده میتونه تو زندگیش انجام بده رو دارین از دست میدین. برای مثال اگه بخواین رمان نویس بشین .آیا در عین واحد میتونین شروع به نوشتن رمان کنین؟ قطعا پاسخ نه هست. برای اینکه یک رمان نویس خوب بنویسین اول باید صد ها رمان بخونین.
❇️ Complete your documents before next step
یکی از بدترین کارهایی که یک توسعه دهنده میتونه انجام بده مستقیم سراغ کد رفتنه . قبل از انجام هر کاری ابتدا دانسته ها و مستندات خودتون رو در مورد اون کار تکمیل کنین و بعد به سراغ مرحله کد نوشتن برین .قبل از استفاده از هر ابزاری یا تکنولوژی اول مستنداتش رو بخونین و تست هاشو ببینین. اگه غیر از این عمل کنین، در مرحله بعد خودتون رو داخل یک مشکل بزرگ پیدا میکنین. اینو همیشه سر لوحه کارتون قرار بدین که Documentation is the Key
فراموش نکنین که چیزهایی که امروز یاد میگیرن شمارو برای فردا اماده میکنه.
❇️ Follow the defined standards, don't create it
این نکته خیلی مهمه که همیشه سعی کنین از استاندارد هایی که توسط همه پذیرفته شده پیروی کنید و سعی نکنین دورباره اون هارو بسازین . این استاندارد ها توسط دولوپر هایی با سالها تجربه تنظیم و ساخته شده و پیروی کردن از این استاندارد ها مثل این میمونه که دارین پا تو ردپایه بزرگ اونها میذارین.
❇️ Code should be written to be reviewed
فراموش نکنین که کد باید طوری نوشته بشه تا توسط دیگران یا بعدا خودتون قابل بررسی باشه
سعی کنین بعد از اینکه کدی رو مینویسین حداقل یکبار خودتون مرورش کنین و به نوعی تو ذهنتون کامپایلش کنین اینجوری تا 90% مشکلاتی که وجود داره یا ممکنه وجود بیاد رو خودتون حل میکنین. بعد از تمام این مراحل از یه نفر بخاین که کد شمار رو بررسی کنه و از این بابت که داره ایرادات کد شمارو متذکر میشه بسیار خوشحال و سپاسگذار باشین.
بررسی شدن کدتون حتی اگه کدتون ضعیف باشه توسط دیگران به شما می اموزه که یک کد قوی بنویسین به شرط اینکه از نکاتش درس بگیرین و اون رو مثبت بشمارین.
هدفتون از کد نویسی ابتدا جلوگیری از باگ باشه و نوشتن یه کد بدون باگ. مثل Tester ها فک کنین و اینطور فک کردن و کد نوشتن برای کسی هم که کدتون رو تست میکنه میتونه یه چالش باشه.
❇️ Testing to be followed like a religion
به تست کردن کدتون مثل دینتون پایبند باشین.کدهاتونو بعد از هر تغییر بزرگ و کوچیکی تست کنین و اصلا به اینکه از زمانبندی تون عقب میوفتین اهمیت ندین
یادتون باشه موقع طراحی نرم افزار چیزی به نام "اعتماد" وجود نداره .
از اینکه باگ ها رو تو کدتون پیدا میکنین ناراحت نباشین و برعکس جشنش بگیرین و اصلا از اینکه Tester تو کدتون باگ پیدا میکنه ناراحت نباشین فراموش نکین که :
باگ ها دشمن شما هستن و باید اونارو بکشین و اشتباه ها تازمانی خوب ان که اونها رو تکرار نکنین.
❇️ Keep your Code and Documents Safe
یه توسعه دهنده باهوش عادت داره که از کارهای روزانش backup بگیره ازطرف دیگه اگه سیستمون crash کنه و به طریقی کدهاتون از بین بره درواقع اونی که crash کرده و از بین رفته شمایین.
پس نهایتا توصیه ای که میشه اینکه حتما از سورس کنترل ها استفاده کنین.
@fullStackDevs
#Free
#tools
Remove Image Background
🧩ابزاری رایگان برای حذف Background
فقط کافیه تصویر مورد نظرتون را آپلود کنید !
📌 www.remove.bg
@fullStackDevs
#tools
Remove Image Background
🧩ابزاری رایگان برای حذف Background
فقط کافیه تصویر مورد نظرتون را آپلود کنید !
📌 www.remove.bg
@fullStackDevs
#gRPC
🔸 یک بررسی ساده و مفید از پروتکل gRPC
برای اینکه بدانیم gRPC چیست ابتدا باید با rpc و Protocol Buffers اشنایی داشته باشیم .
1️⃣ RPC
مخفف Remote Procedure Call می باشد و همچنین به عنوان subroutine call و function call نیز شناخته میشود.
در واقع RPC پروتکلی هست که یک برنامه می تواند با استفاده از ان به یک برنامه که در کامپیوتری دیگر واقع شده است بدون اینکه اطلاعاتی در مورد شبکه داشته باشد درخواست ارسال کند.
از این پروتکل در شبکه های client-server استفاده میشود.
یک درخواست RPC یک عملیات synchronous است و برنامه درخواست دهنده تا زمانی که سرور درخواستش را پردازش و نتیجه را بازگرداند منتظر مانده و block میشود.
2️⃣ Protocol Buffers
پروتکل بافر که protobuf هم گفته میشود یک روش سریالیزه کردن اطلاعات است که توسط گوگل برای استفاده داخلی توسعه یافته بود که بعداً برای استفاده عموم منتشر شد. از این روش برای برقرار کردن ارتباطات بین برنامهها توسط سیم یا ذخیره کردن اطلاعات استفاده میشود. این روش شامل یک زبان توصیف میانی و یک کامپایلر که کدهای مختلف برای زبانهای برنامهنویسی مختلف از این زبان توصیف میانی تولید میکند، است.
در ابتدای ارائه توسط "گوگل"، کامپایلر آن فقط برای زبانهای C++، جاوا و پایتون، کد تولید میکرد ولی توسط اشخاص ثالث، برای خیل بیشتر زبانهای دیگر هم ابزارهایی ارائه شده است.
❇️ grpc
حال که با این مفاهیم اشنا شدیم نوبت به gRPC میرسد.gRPC یک پروتکلی است که هر دوی این ها را پیاده ساری کرده و ویژگی اصلی ان این است که زبان های برنامه نویسی زیادی را پشتیبانی میکند. و اپلیکیشن ها براساس معماری TCP client-server با این پروتکل با هم ارتباط برقرار میکنند.
این به این معنی است که سرور endpoint های مشخصی را تعریف میکند که توسط هر client ای که قادر است از طریق TCP protocol با سرور ارتباط برقرار کند صدا زده میشود و شما میتوانید همانند REST به این endpoint ها فک کنید و رابط هایی برای سرور برای کار کردن با انها فراهم بیاورید.
پروتکل های زیادی هستند که چنین امکانات و ارتباطاتی را ممکن میسازند اما gRPC ویزگی هایی را به ارمغان می اورد که دیگر پروتکل ها ندارند.
1. این پروتکل در داخل گوگل استفاده میشود پس مراحل تست های خود را دیگر گذرانده است.
2. از انجایی که پیام ها به صورت باینری تبادل میشوند بنابراین به پهنای باند کمتر نسبت به جیسون و ایکس ام ال دارید.
3. جی آر سی پی بسیار پرطرفدار است و لایبری های زیادی برای تعداد زیادی زبان برنامه نویسی وجود دارد تا از آن استفاده کنید.
4. محبوبیت زیاد مستندات خوب و همچنین انجمن هایی را به وجود می اورد که شما را میتواند در کار کردن با ان کمک کند.
@fullStackDevs
🔸 یک بررسی ساده و مفید از پروتکل gRPC
برای اینکه بدانیم gRPC چیست ابتدا باید با rpc و Protocol Buffers اشنایی داشته باشیم .
1️⃣ RPC
مخفف Remote Procedure Call می باشد و همچنین به عنوان subroutine call و function call نیز شناخته میشود.
در واقع RPC پروتکلی هست که یک برنامه می تواند با استفاده از ان به یک برنامه که در کامپیوتری دیگر واقع شده است بدون اینکه اطلاعاتی در مورد شبکه داشته باشد درخواست ارسال کند.
از این پروتکل در شبکه های client-server استفاده میشود.
یک درخواست RPC یک عملیات synchronous است و برنامه درخواست دهنده تا زمانی که سرور درخواستش را پردازش و نتیجه را بازگرداند منتظر مانده و block میشود.
2️⃣ Protocol Buffers
پروتکل بافر که protobuf هم گفته میشود یک روش سریالیزه کردن اطلاعات است که توسط گوگل برای استفاده داخلی توسعه یافته بود که بعداً برای استفاده عموم منتشر شد. از این روش برای برقرار کردن ارتباطات بین برنامهها توسط سیم یا ذخیره کردن اطلاعات استفاده میشود. این روش شامل یک زبان توصیف میانی و یک کامپایلر که کدهای مختلف برای زبانهای برنامهنویسی مختلف از این زبان توصیف میانی تولید میکند، است.
در ابتدای ارائه توسط "گوگل"، کامپایلر آن فقط برای زبانهای C++، جاوا و پایتون، کد تولید میکرد ولی توسط اشخاص ثالث، برای خیل بیشتر زبانهای دیگر هم ابزارهایی ارائه شده است.
❇️ grpc
حال که با این مفاهیم اشنا شدیم نوبت به gRPC میرسد.gRPC یک پروتکلی است که هر دوی این ها را پیاده ساری کرده و ویژگی اصلی ان این است که زبان های برنامه نویسی زیادی را پشتیبانی میکند. و اپلیکیشن ها براساس معماری TCP client-server با این پروتکل با هم ارتباط برقرار میکنند.
این به این معنی است که سرور endpoint های مشخصی را تعریف میکند که توسط هر client ای که قادر است از طریق TCP protocol با سرور ارتباط برقرار کند صدا زده میشود و شما میتوانید همانند REST به این endpoint ها فک کنید و رابط هایی برای سرور برای کار کردن با انها فراهم بیاورید.
پروتکل های زیادی هستند که چنین امکانات و ارتباطاتی را ممکن میسازند اما gRPC ویزگی هایی را به ارمغان می اورد که دیگر پروتکل ها ندارند.
1. این پروتکل در داخل گوگل استفاده میشود پس مراحل تست های خود را دیگر گذرانده است.
2. از انجایی که پیام ها به صورت باینری تبادل میشوند بنابراین به پهنای باند کمتر نسبت به جیسون و ایکس ام ال دارید.
3. جی آر سی پی بسیار پرطرفدار است و لایبری های زیادی برای تعداد زیادی زبان برنامه نویسی وجود دارد تا از آن استفاده کنید.
4. محبوبیت زیاد مستندات خوب و همچنین انجمن هایی را به وجود می اورد که شما را میتواند در کار کردن با ان کمک کند.
@fullStackDevs
Wikipedia
پروتکل بافرز
پروتکل بافرز، یک روش سریالیزه کردن اطلاعات است که توسط گوگل برای استفاده داخلی توسعه یافته بود که بعداً برای استفاده عموم منتشر شد. از این روش برای برقرار کردن ارتباطات بین برنامهها توسط سیم یا ذخیره کردن اطلاعات استفاده میشود. این روش شامل یک زبان توصیف…
👍2
#Xamarin
#Announcing
Xamarin Announcements from .NET Conf 2019
Today at .NET Conf 2019, we shared some exciting announcements for Xamarin and Visual Studio developers, including:
▫️ XAML Hot Reload for Xamarin.Forms:
Make changes to your XAML UI. See them reflected live on your emulator, simulator, or physical device.
▪️ Xamarin Hot Restart:
Test changes made to your app, including multi-file code edits, resources, and references, while using a much faster build and deploy cycle.
▫️ iOS 13 and Android 10:
Take advantage of the full power and performance of native platforms and APIs. Including iPadOS, dark mode, and foldable support.
Content link:
https://devblogs.microsoft.com/xamarin/xamarin-dotnet-conf-2019/
@fullStackDevs
Tutorial Links :
Xamarin 101: Part 1 - Introduction to Xamarin
Xamarin 101: Part 2 - Installing Xamarin
Xamarin 101: Part 3 - Solution Architecture
Xamarin 101: Part 4 - Building a Xamarin.Forms UI with XAML
Xamarin 101: Part 5 - Xamarin.Forms MVVM with XAML
Xamarin 101: Part 6 - Xamarin.Forms Navigation with XAML
Xamarin 101: Part 7 - Wrapping Up
@fullStackDevs
#Announcing
Xamarin Announcements from .NET Conf 2019
Today at .NET Conf 2019, we shared some exciting announcements for Xamarin and Visual Studio developers, including:
▫️ XAML Hot Reload for Xamarin.Forms:
Make changes to your XAML UI. See them reflected live on your emulator, simulator, or physical device.
▪️ Xamarin Hot Restart:
Test changes made to your app, including multi-file code edits, resources, and references, while using a much faster build and deploy cycle.
▫️ iOS 13 and Android 10:
Take advantage of the full power and performance of native platforms and APIs. Including iPadOS, dark mode, and foldable support.
Content link:
https://devblogs.microsoft.com/xamarin/xamarin-dotnet-conf-2019/
@fullStackDevs
Tutorial Links :
Xamarin 101: Part 1 - Introduction to Xamarin
Xamarin 101: Part 2 - Installing Xamarin
Xamarin 101: Part 3 - Solution Architecture
Xamarin 101: Part 4 - Building a Xamarin.Forms UI with XAML
Xamarin 101: Part 5 - Xamarin.Forms MVVM with XAML
Xamarin 101: Part 6 - Xamarin.Forms Navigation with XAML
Xamarin 101: Part 7 - Wrapping Up
@fullStackDevs
Xamarin Blog
Xamarin Announcements from .NET Conf 2019 | Xamarin Blog
.NET Conf 2019 announcements for Xamarin & Visual Studio developers that enable better performance and capabilities of iOS and Android apps.
#JS
#Blocks
Creating beautiful websites (UI) without writing code
A JSX-based page builder
⚠️ Currently under development
blocks-ui.com
Github
@fullStackDevs
#Blocks
Creating beautiful websites (UI) without writing code
A JSX-based page builder
⚠️ Currently under development
blocks-ui.com
Github
@fullStackDevs
#Caching
کشینگ (Caching) چیست؟
از جمله مواردی که استفاده درست و بجا از آن به طور قابل ملاحظه ای باعث افزایش کارایی برنامه میشود Caching میباشد.درواقع Caching مکانیزمی است که داده ها را ذخیره میکند تا درخواست های آینده برای آن داده ها سریعتر انجام شود و نتیجه به کلاینت زودتر بازگشت داده شود.داده های ذخیره شده می تواند نتیجه محاسبات قبلی یا کپی ای از داده های دیگر در جای دیگری باشد.این کار برای جلوگیری از محاسبات تکراری و یا کاهش درخواست ها به دیتابیس،برای داده هایی که امکان تغییر مداوم آنها کم است و همچنین هزینه محاسبه و یا ساخت دوباره آن زیاد است، صورت میگیرد.
خوشبخانه AspNetCore از روش های مختلف Caching پشتیبانی میکند.
از جمله این روش ها به Cache In Memory و Distributed Cache می توان اشاره کرد.
روش Cache In Memory از حافظه رم سرور برای ذخیره داده های کش شده استفاده میکند. این نوع Cache متناسب برای یک سرور است و برای استفاده از این روش زمانی که چند سرور دارید از ویژگی یا تکنینک Sticky session ( که به معنی درخواست های کلاینت به همان سروری که داده ها را Cache کرده برای پردازش Route میشوند) استفاده کرد.
از روش Distributed Cache برای share کردن داده های کش شده بین چندین سرور استفاده میشود. معمولا داده ها در یک سرور خارجی نگه داشته میشوند و دیگر سرور ها به آن دسترسی دارند.
محل قرا گیری عملیات Caching در معماری پروژه هایمان کجاست؟
معماری رایج در بین وب اپلیکیشن ها غالبا یک معماری تمیز (Clean Architecture) میباشد . و ما در این پست به قرار دادن عملیات مربوط به caching در چنین معماری هایی میپردازیم.
در این قبیل معماری ها براساس اصول طراحی و قوائد تعیین شده در DDD اپلیکیشن به لایه هایی تقسیم میشود و به ترتیب داخلی ترین لایه که Domain layer میباشد و کمترین وابستگی را به یک Dll خارجی دارد و هرچه به لایه های بالاتر میرویم وابستگی لایه ها به یکدیگر بیشتر میشود. از ویژگی های یک معماری خوب Loose Coupling در بین لایه ها میباشد یعنی وابستگی لایه ها به یکدیگر را بقدری کاهش داد که با تغییر یک لایه خللی در کار دیگر لایه ها صورت نگیرد. البته در این تعریف منظور از کاهش وابستگی یعنی کاهش وابستگی در زمان Compile time.
در یک Clean Architecture یا به عبارتی در یک Clean DDD Architecture معمولا لایه های بدین شکل خواهند بود :
1 - Domain|Core layer
2 - Services | Application Layer
3 - Infrastructure Layer
4 - UI Layer
در لایه Domain اپلیکیشن Entitiy ها و Contract ها(interface) های قرار میگیرد و در لایه Infrastructure معمولا پیاده سازی دسترسی به داده ها و دیگر سرویس ها خارجی مانند FileLogger و SmtpNotifier میباشد.این لایه امکان دسترسی و ذخیره سازی دائمی داده ها را ممکن میسازد،همچنین اطلاعات موجود Domain Entity ها در دیتابیس یا هر store دیگری به صورت دائمی در این لایه برای ذخیره، پیاده سازی میشود.از سوی دیگر ریپازیتوری های ما در این لایه پیاده سازی میشوند.(ریپازیتوری محلی است که امکان دسترسی یه اینتیتی ها و valueObject ها را فراهم میکند).
برای پیدا کردن محل درست caching باید با وظیفه یک عامل دیگر اشنا باشیم.
Repository pattern
الگوی طراحی ریپازیتوری یک روش برای انتزاعی کردن دسترسی به داده ها به جای استفاده Concrete شده از آنها میباشد.
از جمله دلیل استفاده از این الگو جلوگیری از دوباره نویسی Query ها و همچنین امکان تغییر دیتابیس یا ORM اپلیکیشن را میتوان بر شمرد.
همانطور که گفتیم ریپازیتوری راه دسترسی ما به داده هاست ، این داده ها ممکن از از دیتابیس واکشی شوند یا اینکه از Cache خوانده شوند و از آنجایی که پیاده سازی الگوی Repository در لایه Infrastructure صورت میگیرد پس در نتیجه لایه قرارگیری caching نیز در همین لایه و در ریپازیتوری میباشد .
اما پیاده سازی caching در داخل خود ریپازیتوری چند مشکل اساسی دارد، مشکل، عدم تست پذیری و نقض اصل اول Solid یعنی Single responsibility میباشد.
برای حل این مشکل یک الگوی طراحی Structural به کمک ما می آید و با پیاده سازی آن این مشکل را حل میکنیم.
در این قسمت به بررسی یک سری از مسائل پایه پرداختیم و در قسمت بعدی این پست به طریقه پیاده سازی آن خواهیم پرداخت.
@fullStackDevs
کشینگ (Caching) چیست؟
از جمله مواردی که استفاده درست و بجا از آن به طور قابل ملاحظه ای باعث افزایش کارایی برنامه میشود Caching میباشد.درواقع Caching مکانیزمی است که داده ها را ذخیره میکند تا درخواست های آینده برای آن داده ها سریعتر انجام شود و نتیجه به کلاینت زودتر بازگشت داده شود.داده های ذخیره شده می تواند نتیجه محاسبات قبلی یا کپی ای از داده های دیگر در جای دیگری باشد.این کار برای جلوگیری از محاسبات تکراری و یا کاهش درخواست ها به دیتابیس،برای داده هایی که امکان تغییر مداوم آنها کم است و همچنین هزینه محاسبه و یا ساخت دوباره آن زیاد است، صورت میگیرد.
خوشبخانه AspNetCore از روش های مختلف Caching پشتیبانی میکند.
از جمله این روش ها به Cache In Memory و Distributed Cache می توان اشاره کرد.
روش Cache In Memory از حافظه رم سرور برای ذخیره داده های کش شده استفاده میکند. این نوع Cache متناسب برای یک سرور است و برای استفاده از این روش زمانی که چند سرور دارید از ویژگی یا تکنینک Sticky session ( که به معنی درخواست های کلاینت به همان سروری که داده ها را Cache کرده برای پردازش Route میشوند) استفاده کرد.
از روش Distributed Cache برای share کردن داده های کش شده بین چندین سرور استفاده میشود. معمولا داده ها در یک سرور خارجی نگه داشته میشوند و دیگر سرور ها به آن دسترسی دارند.
محل قرا گیری عملیات Caching در معماری پروژه هایمان کجاست؟
معماری رایج در بین وب اپلیکیشن ها غالبا یک معماری تمیز (Clean Architecture) میباشد . و ما در این پست به قرار دادن عملیات مربوط به caching در چنین معماری هایی میپردازیم.
در این قبیل معماری ها براساس اصول طراحی و قوائد تعیین شده در DDD اپلیکیشن به لایه هایی تقسیم میشود و به ترتیب داخلی ترین لایه که Domain layer میباشد و کمترین وابستگی را به یک Dll خارجی دارد و هرچه به لایه های بالاتر میرویم وابستگی لایه ها به یکدیگر بیشتر میشود. از ویژگی های یک معماری خوب Loose Coupling در بین لایه ها میباشد یعنی وابستگی لایه ها به یکدیگر را بقدری کاهش داد که با تغییر یک لایه خللی در کار دیگر لایه ها صورت نگیرد. البته در این تعریف منظور از کاهش وابستگی یعنی کاهش وابستگی در زمان Compile time.
در یک Clean Architecture یا به عبارتی در یک Clean DDD Architecture معمولا لایه های بدین شکل خواهند بود :
1 - Domain|Core layer
2 - Services | Application Layer
3 - Infrastructure Layer
4 - UI Layer
در لایه Domain اپلیکیشن Entitiy ها و Contract ها(interface) های قرار میگیرد و در لایه Infrastructure معمولا پیاده سازی دسترسی به داده ها و دیگر سرویس ها خارجی مانند FileLogger و SmtpNotifier میباشد.این لایه امکان دسترسی و ذخیره سازی دائمی داده ها را ممکن میسازد،همچنین اطلاعات موجود Domain Entity ها در دیتابیس یا هر store دیگری به صورت دائمی در این لایه برای ذخیره، پیاده سازی میشود.از سوی دیگر ریپازیتوری های ما در این لایه پیاده سازی میشوند.(ریپازیتوری محلی است که امکان دسترسی یه اینتیتی ها و valueObject ها را فراهم میکند).
برای پیدا کردن محل درست caching باید با وظیفه یک عامل دیگر اشنا باشیم.
Repository pattern
الگوی طراحی ریپازیتوری یک روش برای انتزاعی کردن دسترسی به داده ها به جای استفاده Concrete شده از آنها میباشد.
از جمله دلیل استفاده از این الگو جلوگیری از دوباره نویسی Query ها و همچنین امکان تغییر دیتابیس یا ORM اپلیکیشن را میتوان بر شمرد.
همانطور که گفتیم ریپازیتوری راه دسترسی ما به داده هاست ، این داده ها ممکن از از دیتابیس واکشی شوند یا اینکه از Cache خوانده شوند و از آنجایی که پیاده سازی الگوی Repository در لایه Infrastructure صورت میگیرد پس در نتیجه لایه قرارگیری caching نیز در همین لایه و در ریپازیتوری میباشد .
اما پیاده سازی caching در داخل خود ریپازیتوری چند مشکل اساسی دارد، مشکل، عدم تست پذیری و نقض اصل اول Solid یعنی Single responsibility میباشد.
برای حل این مشکل یک الگوی طراحی Structural به کمک ما می آید و با پیاده سازی آن این مشکل را حل میکنیم.
در این قسمت به بررسی یک سری از مسائل پایه پرداختیم و در قسمت بعدی این پست به طریقه پیاده سازی آن خواهیم پرداخت.
@fullStackDevs
blog.airbrake.io
Domain-Driven Design: What is it and how do you use it?
A detailed look at domain-driven design in software development, including basic implementation and a handful of advantages and disadvantages of its use.
#Github
#WebDevsOnGithub
با سلام خدمت اعضای محترم کانال 📣 WebDevs
🌀اتفاق خوبی که افتاده اینکه برای کانال یک organization در گیت هاب ساخته ایم 🤩.
🔹 از این به بعد هر یک از سورس ها در قالب یک ریپازیتوری اون جا قرار داده میشه و میتونین سورس ها رو بررسی کنین و خواندن سورس ها هم به مراتب راحت تره.
بررسی و مشاهده از طریق این 👈 لینک
@fullStackDevs
#WebDevsOnGithub
با سلام خدمت اعضای محترم کانال 📣 WebDevs
🌀اتفاق خوبی که افتاده اینکه برای کانال یک organization در گیت هاب ساخته ایم 🤩.
🔹 از این به بعد هر یک از سورس ها در قالب یک ریپازیتوری اون جا قرار داده میشه و میتونین سورس ها رو بررسی کنین و خواندن سورس ها هم به مراتب راحت تره.
بررسی و مشاهده از طریق این 👈 لینک
@fullStackDevs
#معرفی_نرم_افزار
#eye_protection
نرم افزار Iris یکی از آن نرم افزار های خوبی هست که با نصب آن میتوانید تاثیرات منفی نور صفحه نمایش کامپیوتر های خود را کاهش دهید.
از جمله قابلیت ها میتوان به ،کاهش نور آبی (یکی از نور هایی که اسیب زیادی به چشم وارد میکند) نام برد.
این نرم افزار دارای mode های زیادی برای تنظیم نور و حالت میباشد.
نحوه استفاده و تنظیم نرم افزار را در این ویدیو با یک موزیک متن جذاب تماشا کنید.
Download here
@fullStackDevs
#eye_protection
نرم افزار Iris یکی از آن نرم افزار های خوبی هست که با نصب آن میتوانید تاثیرات منفی نور صفحه نمایش کامپیوتر های خود را کاهش دهید.
از جمله قابلیت ها میتوان به ،کاهش نور آبی (یکی از نور هایی که اسیب زیادی به چشم وارد میکند) نام برد.
این نرم افزار دارای mode های زیادی برای تنظیم نور و حالت میباشد.
نحوه استفاده و تنظیم نرم افزار را در این ویدیو با یک موزیک متن جذاب تماشا کنید.
Download here
@fullStackDevs
#Caching
#قسمت_دوم
🔹در قسمت اول به معرفی caching و جزئیات آن در asp core پرداختیم . حال نوبت به پیاده سازی است.
همانطور که گفته بودیم در این قسمت با استفاده ار یک الگوی Structural مشکلی که وجود داشت را حل خواهیم کرد.
▪️این الگو ، الگوی Proxy میباشد . بیایید نگاهی به این الگو بیاندازیم.
▫️این الگو شئ ای را به وجود میاورد که به عنوان یک placeholder یا یک جایگزین برای شئ دیگری عمل میکند و وظیفه آن کنترل دسترسی به آن شی است.در این پست این شی را Proxy object مینامیم.
و همچنین شئ ای که Proxy object کنترل دسترسی را بروی آن انجام میدهد hidden object مینامیم.
✳️ چه زمانی از الگوی Proxy استفاده کنیم ⁉️
▪️اگر زمانی نیاز داشتید تا رفتار یک شئ (hidden object ) را تغییر دهید
حالا که با Proxy Pattern شدیم نوبت به استفاده از این الگو است .
🔹امروزه تقریبا همگی از الگوی Repository میکنیم همانطور که قبلا گفتیم "
▪️در این پست از روش Cache In Memory در AspNet Core استفاده میکنیم که برای فعال سازی آن باید سرویس زیر را در متد ConfigureServices کلاس startup اضافه کنید.
▫️services.AddMemoryCache();
بعد از انجام اینکار انحام عملیات in-memoryCache را از طریق اینترفیس IMemoryCache دسترسی خواهید داشت و با تزریق آن در متد سازنده (Constructor) کنترلر یا هر کلاس دیگری، وابستگی های آن در زمان اجرا توسط سیستم تزریق وابستگی تزریق میشود.
🔹موارد لازم برای پیاده سازی
▪️اینترفیس زیر ،اینترفیس ریپازیتوری میباشد که دارای یک متد GetAll() میباشد.
{
IEnumerable<Student> GetAll();
}```
▪️کلاس زیر هم ریپازیتوری میباشد که پیاده سازی کننده اینترفیس بالا است
```public class StudentRepository : IStudentRepository
{
public IEnumerable<Student> GetAll()
{
return dbContext.Students.ToList();
}
}```
▪️ حال proxy ریپازیتوری بدین شکل خواهد بود
```public class StudentRepositoryProxy
#قسمت_دوم
🔹در قسمت اول به معرفی caching و جزئیات آن در asp core پرداختیم . حال نوبت به پیاده سازی است.
همانطور که گفته بودیم در این قسمت با استفاده ار یک الگوی Structural مشکلی که وجود داشت را حل خواهیم کرد.
▪️این الگو ، الگوی Proxy میباشد . بیایید نگاهی به این الگو بیاندازیم.
▫️این الگو شئ ای را به وجود میاورد که به عنوان یک placeholder یا یک جایگزین برای شئ دیگری عمل میکند و وظیفه آن کنترل دسترسی به آن شی است.در این پست این شی را Proxy object مینامیم.
و همچنین شئ ای که Proxy object کنترل دسترسی را بروی آن انجام میدهد hidden object مینامیم.
✳️ چه زمانی از الگوی Proxy استفاده کنیم ⁉️
▪️اگر زمانی نیاز داشتید تا رفتار یک شئ (hidden object ) را تغییر دهید
(منظور از تغییر رفتار یک شی یعنی افزودن عملیاتی قبل یا بعد از اجرای هر یک از متد های آن است)
بدون اینکه در تعریف متد های اصلی آن شی(hidden object ) تغییری دهید میتوانید از این الگو استفاده کنید همچنین استفاده از این الگو در سناریو های testing زمانی که میخواهید رفتار یک کلاس را در جاهایی بدون پیاده سازی ای برای آن جایگزین کنید، بسیار کاربردی خواهد بود.حالا که با Proxy Pattern شدیم نوبت به استفاده از این الگو است .
🔹امروزه تقریبا همگی از الگوی Repository میکنیم همانطور که قبلا گفتیم "
ریپازیتوری راه دسترسی ما به داده هاست ، این داده ها ممکن از از دیتابیس واکشی شوند یا اینکه از Cache خوانده شوند
" برای انجام این امر و همچنین انجام عملیات caching میخواهیم برای ریپازیتوری خود یک Proxy بنویسیم به طوری که قبل از صدا زده شدن متد های Repository مثل GetAll() فرایند چک کردن cache صورت گیرد و اگر داده ها در cache وجود داشتند به کاربر باز گردانده شوند.▪️در این پست از روش Cache In Memory در AspNet Core استفاده میکنیم که برای فعال سازی آن باید سرویس زیر را در متد ConfigureServices کلاس startup اضافه کنید.
▫️services.AddMemoryCache();
بعد از انجام اینکار انحام عملیات in-memoryCache را از طریق اینترفیس IMemoryCache دسترسی خواهید داشت و با تزریق آن در متد سازنده (Constructor) کنترلر یا هر کلاس دیگری، وابستگی های آن در زمان اجرا توسط سیستم تزریق وابستگی تزریق میشود.
🔹موارد لازم برای پیاده سازی
▪️اینترفیس زیر ،اینترفیس ریپازیتوری میباشد که دارای یک متد GetAll() میباشد.
```public interface IStudentRepository
{
IEnumerable<Student> GetAll();
}```
▪️کلاس زیر هم ریپازیتوری میباشد که پیاده سازی کننده اینترفیس بالا است
```public class StudentRepository : IStudentRepository
{
public IEnumerable<Student> GetAll()
{
return dbContext.Students.ToList();
}
}```
▪️ حال proxy ریپازیتوری بدین شکل خواهد بود
```public class StudentRepositoryProxy
: IStudentRepository
{
private readonly IStudentRepository _studentRepository; private readonly IMemoryCache _memoryCache;
private const string CacheKey = "WebDevsTelegramChannel"; public StudentRepositoryProxy(ServiceResolver serviceAccessor,
IMemoryCache memoryCache)
{
_studentRepository = serviceAccessor("GetBasicObject");;
_memoryCache = memoryCache; }
public IEnumerable<Student> GetAll()
{
if (_memoryCache.TryGetValue(CacheKey, out object temp)) {
return _memoryCache.Get<IEnumerable<Student>>(CacheKey);
}
else {
var students = _studentRepository.GetAll();
_memoryCache.Set(CacheKey, students); return students;
}
}
}
```@fullStackDevs
#ادامه_پست_قبل
🔹کلاس StudentRepositoryProxy پیاده سازی کننده اینترفیس IStudentRepository و هم چنین خود کلاس ریپازیتوری ما (StudentRepository) نیز این اینترفیس را پیاده سازی کرده است . یعنی به ازای یک اینترفیس دو کلاس پیاده سازی کننده داریم با این تفاوت که جزئیات پیاده سازی درStudentRepository و جزئیتات Checking ها در StudentRepositoryProxy اعمال میشود. همچنین در داخل خود کلاس StudentRepositoryProxy به یک نمونه از StudentRepository نیاز داریم (
در واقع کلاس StudentRepositoryProxy به عنوان یک placeholder برای کلاس StudentRepository عمل میکند.
▪️در هنگام استفاده درخواست های خود را فقط و فقط به StudentRepositoryProxy خواهیم داد و این کلاس هست که بعد از اعمال و کنترل دسترسی و انجام Checking ها و فیلتر های تعریف شده قبل از اجرای متدهای ریپازیتوری با StudentRepository ارتباط برقرار کرده و داده ها درصورت لزوم cache میکند.اکنون برای Register کردن وابستگی ها یک چالش در پیش داریم چون به ازای یک اینترفیس دو کلاس پیاده سازی کننده داریم .
✳️چگونه به ازای یک اینترفیس دو یا چند سرویس را در DI Container پیشفرض Register کنیم⁉️
▪️برای حل این چالش از این تکنیک میتوانیم استفاده کنیم .یعنی در متد ConfigureServices سرویس ها را بدین شکل اضافه کنیم :
▫️ابتدا یک delegate به صورت پراپرتی برای کلاس startup تعریف میکنیم
public delegate
و بعد سرویس ها را بدین گونه اضافه میکنیم.
▫️اگر نیاز به چک کردن و همچنین cache کردن اطلاعات داشتید پس باید به ازاری اینترفیس
}
🔻نکته : Register کردن دو یا چند سرویس به ازای یک interface در دیگر Di Container هایی مانند
🔻نکته بعدی در مورد caching در این پست MemoryCacheEntryOptions است که با ساخت یک نمونه از روی این کلاس و پاس دادن ان به متد _memoryCacheObject.Set() در هنگام افزودن داده ها درون cache میتوانید برای آن تنظیماتی از جمله size و AbsoluteExpiration و Priority و .. اعمال کنید .
🌀سورس این پست را در اینجا میتوانید بررسی کنید.
@fullStackDevs
🔹کلاس StudentRepositoryProxy پیاده سازی کننده اینترفیس IStudentRepository و هم چنین خود کلاس ریپازیتوری ما (StudentRepository) نیز این اینترفیس را پیاده سازی کرده است . یعنی به ازای یک اینترفیس دو کلاس پیاده سازی کننده داریم با این تفاوت که جزئیات پیاده سازی درStudentRepository و جزئیتات Checking ها در StudentRepositoryProxy اعمال میشود. همچنین در داخل خود کلاس StudentRepositoryProxy به یک نمونه از StudentRepository نیاز داریم (
این مورد از قوائد پیاده سازی الگوی Proxy میباشد
) که این نمونه توسط سیستم تزریق وابستگی ساخته خواهد شد.در واقع کلاس StudentRepositoryProxy به عنوان یک placeholder برای کلاس StudentRepository عمل میکند.
▪️در هنگام استفاده درخواست های خود را فقط و فقط به StudentRepositoryProxy خواهیم داد و این کلاس هست که بعد از اعمال و کنترل دسترسی و انجام Checking ها و فیلتر های تعریف شده قبل از اجرای متدهای ریپازیتوری با StudentRepository ارتباط برقرار کرده و داده ها درصورت لزوم cache میکند.اکنون برای Register کردن وابستگی ها یک چالش در پیش داریم چون به ازای یک اینترفیس دو کلاس پیاده سازی کننده داریم .
✳️چگونه به ازای یک اینترفیس دو یا چند سرویس را در DI Container پیشفرض Register کنیم⁉️
▪️برای حل این چالش از این تکنیک میتوانیم استفاده کنیم .یعنی در متد ConfigureServices سرویس ها را بدین شکل اضافه کنیم :
▫️ابتدا یک delegate به صورت پراپرتی برای کلاس startup تعریف میکنیم
public delegate
IStudentRepository
ServiceResolver(string key);و بعد سرویس ها را بدین گونه اضافه میکنیم.
```services.AddScoped<StudentRepository>();
services.AddScoped<StudentRepositoryProxy>();services.AddTransient<ServiceResolver>
(serviceProvider =>key
=>key
{
switch (
)"GetBasicObject"
{
case
:serviceProvider.GetService<StudentRepository>();
return
case"GetProxyObject"
:serviceProvider.GetService<StudentRepositoryProxy>();
return
default
:new KeyNotFoundException();
throw
}▪️ پس از انجام این مراحل از این به بعد قادر خواهید بود تا در هر کنترلر یا ApplicationBusinessService یا هر جایی که لازم دارید که از
});```
IStudentRepository
استفاده کنید و میتوانید بدین شکل عمل کنید :▫️اگر نیاز به چک کردن و همچنین cache کردن اطلاعات داشتید پس باید به ازاری اینترفیس
IStudentRepository
یک نمونه از StudentRepositoryProxy در زمان اجرا ساخته شود که این امر با پاس دادن مقدار کلید "GetProxyObject" به دلیگیت ServiceResolver مشخص میشود. بدین شکل :```public class StudentsController
{
private readonly IStudentRepository _studentRepositoryProxy;
public StudentsController(
ServiceResolver serviceAccessor)
{
_studentRepositoryProxy =
serviceAccessor("GetProxyObject
"); }
}```
▫️ اگر هم میخواستید از داده های orginal استفاده کنید و عملیات checking ای برای cache کردن داده ها صورت نگیرد کافیست از سیستم تزریق وابستگی بخواهید تا به ازای اینترفیس IStudentRepository
یک نمونه از کلاس StudentRepository
بسازد. این امر با پاس دادن مقدار کلید "GetBasicObject" به دلیگیت ServiceResolver مشخص میشود. بدین شکل :public
StudentsController(ServiceResolver serviceAccessor)
{
_studentRepositoryProxy =
serviceAccessor("GetBasicObject");}
🔻نکته : Register کردن دو یا چند سرویس به ازای یک interface در دیگر Di Container هایی مانند
Autofac
و Windsor وStructureMap
به راحتی امکان پذیر است.🔻نکته بعدی در مورد caching در این پست MemoryCacheEntryOptions است که با ساخت یک نمونه از روی این کلاس و پاس دادن ان به متد _memoryCacheObject.Set() در هنگام افزودن داده ها درون cache میتوانید برای آن تنظیماتی از جمله size و AbsoluteExpiration و Priority و .. اعمال کنید .
🌀سورس این پست را در اینجا میتوانید بررسی کنید.
@fullStackDevs
#Bmw
#AI_algorithms
🔹شرکت خودروسازی آلمانی BMW الگوریتم های هوش مصنوعی خود را که در تولید محصولاتش استفاده میکرده است به صورت متن باز در گیت هاب منتشر کرد.
در متن این خبر آمده است :
🔸"ما در زمینه هوش مصنوعی سرمایه گذاری های اساسی انجام می دهیم. با به اشتراک گذاشتن الگوریتم های خود با جامعه جهانی توسعه دهندگان ، می خواهیم سهم خود را انجام دهیم و هوش مصنوعی را برای گروه وسیعی از کاربران در اختیار قرار دهیم. ما انتظار داریم که توسعه بیشتر منابع متن باز منجر به پیشرفت سریع و چابک نرم افزار ها شود."
▫️Kai Demtröder, Head of Artificial Intelligence, Data Platforms at BMW Group IT.
لینک خبر
ادرس گیت هاب
@FullStackDevs
#AI_algorithms
🔹شرکت خودروسازی آلمانی BMW الگوریتم های هوش مصنوعی خود را که در تولید محصولاتش استفاده میکرده است به صورت متن باز در گیت هاب منتشر کرد.
در متن این خبر آمده است :
🔸"ما در زمینه هوش مصنوعی سرمایه گذاری های اساسی انجام می دهیم. با به اشتراک گذاشتن الگوریتم های خود با جامعه جهانی توسعه دهندگان ، می خواهیم سهم خود را انجام دهیم و هوش مصنوعی را برای گروه وسیعی از کاربران در اختیار قرار دهیم. ما انتظار داریم که توسعه بیشتر منابع متن باز منجر به پیشرفت سریع و چابک نرم افزار ها شود."
▫️Kai Demtröder, Head of Artificial Intelligence, Data Platforms at BMW Group IT.
لینک خبر
ادرس گیت هاب
@FullStackDevs
#LinqToSql
در این پست می خواهیم به این سوال ها پاسخ دهیم که :
🔹 انواع join در LINQ چیست و چگونه انواع مختلف join را در LinqToSql انجام دهیم ❓
▪️Cross Join
🔸نام دیگر آن Cartesian Product یا ضرب دکارتی میباشد.
در Cross Join هر یک از آیتم ها در DataSource یا Collection اول با تک تک آیتم های DataSource یا Collection دوم با هم مپ میشوند.
مثال
a = {"C#","Java" }
b ={1,2}
=>
یک مثال با LinqToSql :
var result = context.Products.SelectMany(p => context.Categories, (p, c) => new { p.Name, c.Title }).ToList();
❗️ توجه داشته باشید که در Cross Join دو DataSource یا Collection لزوما نیاز به داشتن ارتباط با همدیگر برای فیلتر کردن Data ندارند.
▪️Group Join
🔸این متد برای تولید ساختار های سلسله مراتبی استفاده میشود. بدین صورت که براساس یک کلید هر یک از ایتم های Collection سمت چپ با مجموعه ای از ایتم های مرتبط در Collection سمت راست تشکیل یک زوج را میدهند.یعنی یک ایتم از Collection سمت چپ لیستی از آیتم های Collection سمت راست خواهد داشت.
❗️ اگر یک آیتم در Collection سمت چپ با هیچ یک از آیتم های Collection سمت راست براساس کلید تعیین شده وجه اشتراک نداشته باشند باز هم در نتیجه نهایی کوئری وجود خواهد داشت.
کاربرد اصلی آن برای رابطه های یک به چند میباشد .
var result = context.Orders.
GroupJoin(context.OrderDetails, o => o.ID, od => od.OrderId,
(o, od) => new
{
o,
od
}).ToList();
▪️Inner Join
🔸رایج ترین نوع جوین inner join میباشد از این نوع Join برای ادغام دو جدول به یک جدول براساس یک یا چند مشخصه (کلید) مشترک استفاده میشود.
❗️در این نوع join اگر یک آیتم از Collection سمت چپ با هیچ یک از آیتم های Collection سمت راست براساس کلید تعیین شده وجه اشتراکی نداشته باشد ، آن آیتم در نتیجه تولید شده نهایی کوئری وجود نخواهد داشت
در واقع این نوع Join فقط و فقط وجه اشتراک دو Collection را بر اساس کلید تعیین شده در خروجی نمایش خواهد داد.
var result = context.Orders.Join(context.OrderDetails, o => o.ID, od => od.OrderId,
(o, od) => new
{
o,
od
}).ToList();
✳️تفاوت Group Join و Inner Join چیست ⁉️
🔸همانطور که در توضیحات هرکدام گفتیم در Group Join اگر به ازای یک آیتم در Collection سمت چپ، آیتم متناظری در Collection سمت راست، براساس کلید مشترک تعیین شده وجود نداشته باشد آن آیتم باز هم در نتیجه تولید شده نهایی کوئری حضور خواهد داشت.
این در حالی است که در Inner Join چنین اتفاقی نمی افتد و فقط ایتم های مشترک انتخاب خواهند شد.
▪️Left Join
🔸 نام دیگر آن Left Outer Join میباشد. این نوع Join بروی دو Collection که بایستی کلید مشترکی با یکدیگر داشته باشند انجام میشود و در left Join تمام آیتم های موجود
در Collection سمت چپ بعلاوه آنهایی که وجه اشتراکی با Collection سمت راست دارند بر اساس کلید تعیین شده در نتیجه نهایی کوئری ظاهر میشوند.
var result = context.Orders.
.SelectMany(c => c.OrderDetail.
(x, y) => new
{
Order = x.Order,
OrderDetail = y
}).ToList();
🔹 متد
🔸اگر OrderDetail شامل مقداری نبود، در نتیجه تولید شده مقدار Default را برای آن تولید کن. این امر برای جلوگیری از صادر شدن استثنا Null صورت میگیرد و علت وقوع آن زمانی است که
به ازای یک آیتم در Collection سمت چپ دارای هیچ آیتمی بر اساس کلید تعیین شده
در Collection سمت راست، نباشد.
▪️Right Join
🔸این نوع جوین برعکس Left Join میباشد و نام دیگر آن Right Outer Join میباشد. برای نوشتن کوئری آن نیز فقط باید در کوئری بالا جای Collection های سمت چپ و راست را عوض کنید.
اما از نطر تعریف در Right Join تمام آیتم های موجود در Collection سمت راست بعلاوه آن ایتم هایی که براساس کلید تعیین شده داری وجه اشتراکی با آیتم های Collection سمت چپ دارند در نتیجه نهایی ظاهر خواهد شد.
@FullStackDevs
در این پست می خواهیم به این سوال ها پاسخ دهیم که :
🔹 انواع join در LINQ چیست و چگونه انواع مختلف join را در LinqToSql انجام دهیم ❓
▪️Cross Join
🔸نام دیگر آن Cartesian Product یا ضرب دکارتی میباشد.
در Cross Join هر یک از آیتم ها در DataSource یا Collection اول با تک تک آیتم های DataSource یا Collection دوم با هم مپ میشوند.
مثال
a = {"C#","Java" }
b ={1,2}
=>
result = { {"C#",1} ,
{"C#",2} , {"Java",1},
{"Java",2} }
❗️اندازه خروجی (result) برابر با ضرب دکارتی دو ارایه خواهد بود.یک مثال با LinqToSql :
var result = context.Products.SelectMany(p => context.Categories, (p, c) => new { p.Name, c.Title }).ToList();
❗️ توجه داشته باشید که در Cross Join دو DataSource یا Collection لزوما نیاز به داشتن ارتباط با همدیگر برای فیلتر کردن Data ندارند.
▪️Group Join
🔸این متد برای تولید ساختار های سلسله مراتبی استفاده میشود. بدین صورت که براساس یک کلید هر یک از ایتم های Collection سمت چپ با مجموعه ای از ایتم های مرتبط در Collection سمت راست تشکیل یک زوج را میدهند.یعنی یک ایتم از Collection سمت چپ لیستی از آیتم های Collection سمت راست خواهد داشت.
❗️ اگر یک آیتم در Collection سمت چپ با هیچ یک از آیتم های Collection سمت راست براساس کلید تعیین شده وجه اشتراک نداشته باشند باز هم در نتیجه نهایی کوئری وجود خواهد داشت.
کاربرد اصلی آن برای رابطه های یک به چند میباشد .
var result = context.Orders.
GroupJoin(context.OrderDetails, o => o.ID, od => od.OrderId,
(o, od) => new
{
o,
od
}).ToList();
▪️Inner Join
🔸رایج ترین نوع جوین inner join میباشد از این نوع Join برای ادغام دو جدول به یک جدول براساس یک یا چند مشخصه (کلید) مشترک استفاده میشود.
❗️در این نوع join اگر یک آیتم از Collection سمت چپ با هیچ یک از آیتم های Collection سمت راست براساس کلید تعیین شده وجه اشتراکی نداشته باشد ، آن آیتم در نتیجه تولید شده نهایی کوئری وجود نخواهد داشت
در واقع این نوع Join فقط و فقط وجه اشتراک دو Collection را بر اساس کلید تعیین شده در خروجی نمایش خواهد داد.
var result = context.Orders.Join(context.OrderDetails, o => o.ID, od => od.OrderId,
(o, od) => new
{
o,
od
}).ToList();
✳️تفاوت Group Join و Inner Join چیست ⁉️
🔸همانطور که در توضیحات هرکدام گفتیم در Group Join اگر به ازای یک آیتم در Collection سمت چپ، آیتم متناظری در Collection سمت راست، براساس کلید مشترک تعیین شده وجود نداشته باشد آن آیتم باز هم در نتیجه تولید شده نهایی کوئری حضور خواهد داشت.
این در حالی است که در Inner Join چنین اتفاقی نمی افتد و فقط ایتم های مشترک انتخاب خواهند شد.
▪️Left Join
🔸 نام دیگر آن Left Outer Join میباشد. این نوع Join بروی دو Collection که بایستی کلید مشترکی با یکدیگر داشته باشند انجام میشود و در left Join تمام آیتم های موجود
در Collection سمت چپ بعلاوه آنهایی که وجه اشتراکی با Collection سمت راست دارند بر اساس کلید تعیین شده در نتیجه نهایی کوئری ظاهر میشوند.
var result = context.Orders.
GroupJoin
(context.OrderDetails, order => order.ID, orderDetail => orderDetail.OrderId, (x, y) => new { Order = x, OrderDetail = y }).SelectMany(c => c.OrderDetail.
DefaultIfEmpty
(),(x, y) => new
{
Order = x.Order,
OrderDetail = y
}).ToList();
🔹 متد
DefaultIfEmpty
() در مثال بالا تعیین کننده این است که :🔸اگر OrderDetail شامل مقداری نبود، در نتیجه تولید شده مقدار Default را برای آن تولید کن. این امر برای جلوگیری از صادر شدن استثنا Null صورت میگیرد و علت وقوع آن زمانی است که
به ازای یک آیتم در Collection سمت چپ دارای هیچ آیتمی بر اساس کلید تعیین شده
در Collection سمت راست، نباشد.
▪️Right Join
🔸این نوع جوین برعکس Left Join میباشد و نام دیگر آن Right Outer Join میباشد. برای نوشتن کوئری آن نیز فقط باید در کوئری بالا جای Collection های سمت چپ و راست را عوض کنید.
اما از نطر تعریف در Right Join تمام آیتم های موجود در Collection سمت راست بعلاوه آن ایتم هایی که براساس کلید تعیین شده داری وجه اشتراکی با آیتم های Collection سمت چپ دارند در نتیجه نهایی ظاهر خواهد شد.
@FullStackDevs
#ادامه
#LinqToSql
▪️Full Join
🔸نام دیگر این نوع جوین Full Oter Join میباشد و باید بدانید که Linq به صورت مستقیم آنرا پشتیبانی نمیکند .در Full Join تمامیه آیتم های Collection سمت چپ بعلاوه تمامی آیتم های Collection سمت راست بعلاوه تمامی آیتم های مشترک دو Collection در نتیجه نهایی کوئری تولید خواهند شد.برای انجام Full Join در بین دو Collection باید از دو Collection یکبار Left join گرفته و
بار دیگر از آنها Right Join بگیرید و در نهایت نتیجه دو Join انجام شده را
باهم Union نمایید.
var left = context.Orders.
GroupJoin(context.OrderDetails, order => order.ID, orderDetail => orderDetail.OrderId, (x, y) => new { Order = x, OrderDetail = y })
.SelectMany(c => c.OrderDetail.DefaultIfEmpty(),
(x, y) => new Dto
{
Order = x.Order,
OrderDetail = y
}).ToList();
var right = context.OrderDetails.
GroupJoin(context.Orders, orderDetail => orderDetail.OrderId, order => order.ID, (x, y) => new { OrderDetail = x, Order = y })
.SelectMany(c => c.Order.DefaultIfEmpty(),
(x, y) => new Dto
{
OrderDetail = x.OrderDetail,
Order = y
}).ToList();
var fullJoin = left.Union(right);
✳️سوالی که اکنون ممکن است برای شما پیش آید این است که تفاوت بین Full Join و Union در LINQ چیست ⁉️
🔸در Union نتیجه دو کوئری را به صورت یک نتیجه واحد با هم ترکیب میکنیم که شامل تمام آیتم های دو کوئری میباشد و قوانین آن این است که :
تعداد و ترتیب ستونها باید در دو کوئری یکسان باشد.
انواع داده ها باید سازگار باشند.
🔸در Full Join نتیجه left Join و Right Join با هم ترکیب شده و تمام آیتم های دارای وجه اشتراک وحتی آنهایی که با هم وجه اشتراکی براساس کلید تعیین شده ندارند در نتیجه نهایی کوئری نمایش داده میشوند.
درواقع هدف از full Join واکشی تمام آیتم های دو Collection به همراه روابط و نقاط متناظر آنها براساس کلید تعیین شده میباشد در حالی که Union در صورت برقرار بودن شروط لازم صرفا فقط نتیجه دو کوئری را بدون در نظر گرفتن رابطه بین آیتم های آنها با هم ترکیب میکند.
@FullStackDevs
#LinqToSql
▪️Full Join
🔸نام دیگر این نوع جوین Full Oter Join میباشد و باید بدانید که Linq به صورت مستقیم آنرا پشتیبانی نمیکند .در Full Join تمامیه آیتم های Collection سمت چپ بعلاوه تمامی آیتم های Collection سمت راست بعلاوه تمامی آیتم های مشترک دو Collection در نتیجه نهایی کوئری تولید خواهند شد.برای انجام Full Join در بین دو Collection باید از دو Collection یکبار Left join گرفته و
بار دیگر از آنها Right Join بگیرید و در نهایت نتیجه دو Join انجام شده را
باهم Union نمایید.
var left = context.Orders.
GroupJoin(context.OrderDetails, order => order.ID, orderDetail => orderDetail.OrderId, (x, y) => new { Order = x, OrderDetail = y })
.SelectMany(c => c.OrderDetail.DefaultIfEmpty(),
(x, y) => new Dto
{
Order = x.Order,
OrderDetail = y
}).ToList();
var right = context.OrderDetails.
GroupJoin(context.Orders, orderDetail => orderDetail.OrderId, order => order.ID, (x, y) => new { OrderDetail = x, Order = y })
.SelectMany(c => c.Order.DefaultIfEmpty(),
(x, y) => new Dto
{
OrderDetail = x.OrderDetail,
Order = y
}).ToList();
var fullJoin = left.Union(right);
✳️سوالی که اکنون ممکن است برای شما پیش آید این است که تفاوت بین Full Join و Union در LINQ چیست ⁉️
🔸در Union نتیجه دو کوئری را به صورت یک نتیجه واحد با هم ترکیب میکنیم که شامل تمام آیتم های دو کوئری میباشد و قوانین آن این است که :
تعداد و ترتیب ستونها باید در دو کوئری یکسان باشد.
انواع داده ها باید سازگار باشند.
🔸در Full Join نتیجه left Join و Right Join با هم ترکیب شده و تمام آیتم های دارای وجه اشتراک وحتی آنهایی که با هم وجه اشتراکی براساس کلید تعیین شده ندارند در نتیجه نهایی کوئری نمایش داده میشوند.
درواقع هدف از full Join واکشی تمام آیتم های دو Collection به همراه روابط و نقاط متناظر آنها براساس کلید تعیین شده میباشد در حالی که Union در صورت برقرار بودن شروط لازم صرفا فقط نتیجه دو کوئری را بدون در نظر گرفتن رابطه بین آیتم های آنها با هم ترکیب میکند.
@FullStackDevs
#Remote_attribute🔹 حتما تاکنون برای شما پیش آمده است که در هنگام ثبت نام در سایتی در هنگام وارد کردن ایمیل با Validation ارور هایی مبتنی بر تکراری بودن آدرس ایمیل بدون Submit کردن اطلاعات فرم دریافت کرده باشید.
راه حل انجام این کار بسیار آسان است. استفاده از Remote اتریبیوت بر بالای پراپرتی ای در ویو مدل که میخواهید برای آن Remote Validation به سرور بزنید.
▪️Remote Attribute
🔸این attribute این امکان را به برنامه نویس میدهد که با یک اسکریپت در سمت کلاینت (استفده از ایجکس) اکشن متدی را در سمت سرور صدا بزند و نتیجه را دریافت کند.
public class User
{
[Required]
[DataType(DataType.EmailAddress)]
[Remote("ValidateEmailAddress","Home")] public string Email { get; set; }
}🔸 در کد بالا
ValidateEmailAddress
اکشنی است درون Homecontroller
که در صورت وجود داشتن ایمیل مشابه در دیتابیس مقدار True
را باز میگرداند. public IActionResult
ValidateEmailAddress
(string email
){
return
Json
(_repository.CheckEmailExists(email) ?"true" : string.Format("an account for address {0} already exists.", email));
}
🔻در سمت کلاینت هم جز افزودن لایبری های مورد نیاز ، دیگر لازم به انجام کاری نیست .
<script src="~/Scripts/jquery.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/additional-methods.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
<form asp-action="SignIn" asp-controller="home" class="form-horizontal"><div class="form-group">
<label asp-for="Email" class="col-sm-2 control-label">Subscribe</label>
<div class="col-sm-10">
<input type="email" class="form-control" asp-for="Email" placeholder="Email address" />
<span asp-validation-for="Email"></span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Sign in</button>
</div>
</div>
</form>
@FullStackDevs
Forwarded from Web Devs
#High_Performance
#EfCore_Best_Practice
#DbContext_pooling
🔸 در این پست به معرفی یک روش جدید Register کردن DbContext به Di Container در متد ConfigureServices در کلاس Startup می پردازیم.
ابتدایی ترین و ساده ترین روش که برای Register کردن custom DbContext خود به سیستم dependency injection استفاده میکنیم تا بعدا نمونه ای از custom DbContext خود به صورت constructor parameters و یا دیگر روش های دریافت Instance از DI، دریافت کنیم روش زیر است :
در نسخه 2.0 از Ef Core روش جدید برای Register کردن DbContext به سیستم dependency injection معرفی شد که همانطور که در مثال بعدی خواهید به صورت شفاف مجموعه ای از موارد DbContext قابل استفاده مجدد را ارائه می دهد.
در نهایت هنگامی که Request پردازش شد و کار ان با نمونه دریافت شده DbContext تمام شد، Ef تمامیه State های قابل ردیابی DbContext را که از آنها آگاه هست را reset کرده و DbContext inctance دوباره به Context Pool بر میگردد.
این روال از نظر مفهومی شبیه connection pooling در Ado.net است و از مزیت های آن میتوان به کاهش هزینه ساخت DbContext instance اشاره کرد.
استفاده از این متد البته باعث محدودیت های اندکی در متد OnConfiguring() در DbContext میشود.
🔻 نکته بسیار مهم
نکته مهم این است که اگر به صورت Custom مکانیزمی را در derived DbContext class خود پیاده کرده باشید که باعث نگه داری state ای شود و از انجایی که Ef core فقط state هایی که از آنها اگاه هست را reset میکند پس در نتیجه state که شما به صورت custom ایجاد کرده اید در DbContext instance باقی میماند و باعث share شدن آن در بین درخواست ها میشود.
@fullStackDevs
#EfCore_Best_Practice
#DbContext_pooling
🔸 در این پست به معرفی یک روش جدید Register کردن DbContext به Di Container در متد ConfigureServices در کلاس Startup می پردازیم.
ابتدایی ترین و ساده ترین روش که برای Register کردن custom DbContext خود به سیستم dependency injection استفاده میکنیم تا بعدا نمونه ای از custom DbContext خود به صورت constructor parameters و یا دیگر روش های دریافت Instance از DI، دریافت کنیم روش زیر است :
services.AddDbContext<
BloggingContext
>(options => options.UseSqlServer("ConnectionString"));
🔹 که Register کردن DbContext به این طریق به معنی ساختن یک instance جدید از DbContext برای هر Request میباشد که مطمئنا روال Instance سازی از DbContext هزینه هایی برای اپلیکیشن دارد.در نسخه 2.0 از Ef Core روش جدید برای Register کردن DbContext به سیستم dependency injection معرفی شد که همانطور که در مثال بعدی خواهید به صورت شفاف مجموعه ای از موارد DbContext قابل استفاده مجدد را ارائه می دهد.
services.AddDbContextPool<BloggingContext>(
options => options.UseSqlServer(
ConnectionString
));▪️ اگر از این متد برای Register کردن DbContext استفاده کنید زمانیه که در اپلیکیشن درخواست نمونه ای جدید از DbContext داده شود ابتدا در Context Pool چک میشود که ایا نمونه ای از DbContext وجود دارد و اگر نمونه ای وجو داشت،در اختیار درخواست دهنده قرار میدهد.
در نهایت هنگامی که Request پردازش شد و کار ان با نمونه دریافت شده DbContext تمام شد، Ef تمامیه State های قابل ردیابی DbContext را که از آنها آگاه هست را reset کرده و DbContext inctance دوباره به Context Pool بر میگردد.
این روال از نظر مفهومی شبیه connection pooling در Ado.net است و از مزیت های آن میتوان به کاهش هزینه ساخت DbContext instance اشاره کرد.
استفاده از این متد البته باعث محدودیت های اندکی در متد OnConfiguring() در DbContext میشود.
🔻 نکته بسیار مهم
نکته مهم این است که اگر به صورت Custom مکانیزمی را در derived DbContext class خود پیاده کرده باشید که باعث نگه داری state ای شود و از انجایی که Ef core فقط state هایی که از آنها اگاه هست را reset میکند پس در نتیجه state که شما به صورت custom ایجاد کرده اید در DbContext instance باقی میماند و باعث share شدن آن در بین درخواست ها میشود.
@fullStackDevs
#Keyless_Entity
🔴این پست شامل دو پیام میباشد
✳️Keyless Entity Types
🔸این ویژگی از EF Core 2.1 با نام query type به Ef Core اضافه شد که در Ef Core 3.0 به keyless entity type تغییر نام پیدا کرد است.
از این رو EF Core علاوه بر Entity های معمولی، Model میتواند شامل Entity هایی باشد که
▪️یک keyless Entity میتواند قالب یا مدل خروجی یک کوئری،procedure که از نتیجه Join چند Table در دیتابیس به وجود می اید باشد.
علاوه بر این یک Keyless Entity اکثر ویژگی های یک Entity که شامل inheritance mapping و navigation property و ... است، پشتیبانی میکند.
همچنین میتواند یک Keyless Entity Type را به یک آبجکت نظیر Table یا View در دیتابیس Map کرد.این کار را با کمک fluent API یا data annotations میتوانید انجام دهید.
🔸با همه این ویژگی های مشترک اما یک Keyless Entity تفاوتهایی نسبت به یک Entity دارد که میتوان به موارد ذیل اشاره کرد :
▫️نمیواند کلید اصلی داشته باشند
▫️تغییرات آنها اصلا توسط Change Tracker ردیابی نمیشود پس درنتیجه هرگز امکان درج و حذف و آبدیت انها در DbContext را ندارید.
▫️برای آنها قرار دادی (Convention) وجود ندارد یعنی کلیه Convention هایی که به صورت پیشفرض برای Entity ها در Ef Core وجود دارد برای یک keyless Entity وجود ندارد.
▫️تنها از زیر مجموعه ای از navigation mapping پشتیبانی میکند که به طور خاص دارای شرایط زیر باشد :
🔹خروجی یک navigation mapping در انتهای رابطه به مانند یک principal Entity نباشد..
🔹اگر یکی از پراپرتی ها یک keyless Entity یک Complex type باشد، باید به ازای تک تک پراپرتی های آن Cpmplex type خروجی همنام متناظر داشته باشید.
🔹در هنگام navigation mapping یک keyless Entity فقط میتواند شامل reference navigation property باشد.
🔹انیتی ها نمیتوانند یک keyless Entity را به عنوان navigation property در برداشته باشند.
▫️در هنگام Configuration باید به صورت .HasNoKey() تنظیم شوند.
▫️همچنین ممکن است به یک defining query مپ شود.
🔻یک defining query کوئری است که درون Model تعریف شده و به عنوان Data Source برای keyless Entity عمل میکند.
✳️ موارد استفاده از یک keyless Entity
▪️به عنوان یک نوع بازگشتی برای raw SQL query بکار برده شود.
▪️به یک View در دیتابیس Map شود که هیچ کلید اصلی نیز ندارد.
▪️به یک جدول در دیتابیس Map شود که هیچ کلید اصلی ندارد.
▪️به کوئری های تعریف شده در مدل (defining query) مپ شود.
✳️ نحوه مپ کردن یک Keyless Entity به آبجکنی در دیتابیس
🔸با استفاده از متد های ToTable و ToView در fluent API میتوانید اینکار را انجام دهید.
▪️از دیدگاه Ef Core دیتابیس Object مشخص شده در متد ToView یک view در دیتابیس است و به یک view نمیتوان چیزی را ADD ، DELETE،UPDATE کرد. البته این به این معنی نیست که لزوما آبجکت سمت دیتابیس باید یک View باشد . میتوانید از یک Table استفاده کنید اما این Table به صورت ReadOnly رفتار میکند.
🔻نکته : زمانی که از متد ToView استفاده میکنید ویو مشخص شده باید در دیتابیس وجود داشته باشد و همچنین به صورت خودکار در هنگام مایگریشن و update Database ساخته نخواهد شد.
@FullStackDevs
🔴این پست شامل دو پیام میباشد
✳️Keyless Entity Types
🔸این ویژگی از EF Core 2.1 با نام query type به Ef Core اضافه شد که در Ef Core 3.0 به keyless entity type تغییر نام پیدا کرد است.
از این رو EF Core علاوه بر Entity های معمولی، Model میتواند شامل Entity هایی باشد که
کلید اصلی
ندارند.▪️یک keyless Entity میتواند قالب یا مدل خروجی یک کوئری،procedure که از نتیجه Join چند Table در دیتابیس به وجود می اید باشد.
علاوه بر این یک Keyless Entity اکثر ویژگی های یک Entity که شامل inheritance mapping و navigation property و ... است، پشتیبانی میکند.
همچنین میتواند یک Keyless Entity Type را به یک آبجکت نظیر Table یا View در دیتابیس Map کرد.این کار را با کمک fluent API یا data annotations میتوانید انجام دهید.
🔸با همه این ویژگی های مشترک اما یک Keyless Entity تفاوتهایی نسبت به یک Entity دارد که میتوان به موارد ذیل اشاره کرد :
▫️نمیواند کلید اصلی داشته باشند
▫️تغییرات آنها اصلا توسط Change Tracker ردیابی نمیشود پس درنتیجه هرگز امکان درج و حذف و آبدیت انها در DbContext را ندارید.
▫️برای آنها قرار دادی (Convention) وجود ندارد یعنی کلیه Convention هایی که به صورت پیشفرض برای Entity ها در Ef Core وجود دارد برای یک keyless Entity وجود ندارد.
▫️تنها از زیر مجموعه ای از navigation mapping پشتیبانی میکند که به طور خاص دارای شرایط زیر باشد :
🔹خروجی یک navigation mapping در انتهای رابطه به مانند یک principal Entity نباشد..
🔹اگر یکی از پراپرتی ها یک keyless Entity یک Complex type باشد، باید به ازای تک تک پراپرتی های آن Cpmplex type خروجی همنام متناظر داشته باشید.
🔹در هنگام navigation mapping یک keyless Entity فقط میتواند شامل reference navigation property باشد.
🔹انیتی ها نمیتوانند یک keyless Entity را به عنوان navigation property در برداشته باشند.
▫️در هنگام Configuration باید به صورت .HasNoKey() تنظیم شوند.
▫️همچنین ممکن است به یک defining query مپ شود.
🔻یک defining query کوئری است که درون Model تعریف شده و به عنوان Data Source برای keyless Entity عمل میکند.
✳️ موارد استفاده از یک keyless Entity
▪️به عنوان یک نوع بازگشتی برای raw SQL query بکار برده شود.
▪️به یک View در دیتابیس Map شود که هیچ کلید اصلی نیز ندارد.
▪️به یک جدول در دیتابیس Map شود که هیچ کلید اصلی ندارد.
▪️به کوئری های تعریف شده در مدل (defining query) مپ شود.
✳️ نحوه مپ کردن یک Keyless Entity به آبجکنی در دیتابیس
🔸با استفاده از متد های ToTable و ToView در fluent API میتوانید اینکار را انجام دهید.
▪️از دیدگاه Ef Core دیتابیس Object مشخص شده در متد ToView یک view در دیتابیس است و به یک view نمیتوان چیزی را ADD ، DELETE،UPDATE کرد. البته این به این معنی نیست که لزوما آبجکت سمت دیتابیس باید یک View باشد . میتوانید از یک Table استفاده کنید اما این Table به صورت ReadOnly رفتار میکند.
🔻نکته : زمانی که از متد ToView استفاده میکنید ویو مشخص شده باید در دیتابیس وجود داشته باشد و همچنین به صورت خودکار در هنگام مایگریشن و update Database ساخته نخواهد شد.
@FullStackDevs
#ادامه
#Keyless_Entity
🔹مثال
ابتدا مدل های زیر را تعریف میکنیم
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
}
▪️در خط زیر نیست یک view ساده در دیتابیس تعریف میکتیم که هر Post به همراه Blog مرتبطش برمیگرداند.
db.Database.ExecuteSqlRaw(
@
▪️در نهایت Keyless Entity خود را متناظر با نوع خروچی View ای که ساختیم به اینصورت تعریف میکنیم.
public class BlogPostsCount
{
public string BlogName { get; set; }
public int PostCount { get; set; }
}
▪️و آنرا بدین شکل در متد OnModelCreating کانفیگ میکنیم.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
eb.ToView("View_BlogPostCounts");
eb.Property(v => v.BlogName).HasColumnName("Name");
▪️ حال نوبت به معرفی کرد keyless Entity به DbContext میباشد.که بدین شکل در Db Context تعریف میشود
var postCounts = db.BlogPostCounts.ToList();
foreach (var postCount in postCounts)
{
Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
Console.WriteLine();
}
لینک منبع
🔹سورس این پست رو در اینجا بررسی کنید.
@FullStackDevs
#Keyless_Entity
🔹مثال
ابتدا مدل های زیر را تعریف میکنیم
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
}
▪️در خط زیر نیست یک view ساده در دیتابیس تعریف میکتیم که هر Post به همراه Blog مرتبطش برمیگرداند.
db.Database.ExecuteSqlRaw(
@
"CREATE VIEW View_BlogPostCounts AS
SELECT b.Name, Count(p.PostId) as PostCount
FROM Blogs b
JOIN Posts p on p.BlogId = b.BlogId
GROUP BY b.Name"
);▪️در نهایت Keyless Entity خود را متناظر با نوع خروچی View ای که ساختیم به اینصورت تعریف میکنیم.
public class BlogPostsCount
{
public string BlogName { get; set; }
public int PostCount { get; set; }
}
▪️و آنرا بدین شکل در متد OnModelCreating کانفیگ میکنیم.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<BlogPostsCount>(eb =>
{
eb.HasNoKey();eb.ToView("View_BlogPostCounts");
eb.Property(v => v.BlogName).HasColumnName("Name");
});
}▪️ حال نوبت به معرفی کرد keyless Entity به DbContext میباشد.که بدین شکل در Db Context تعریف میشود
public DbQuery<BlogPostsCount> BlogPostCounts { get; set; }
در آخر نیز بدین شکل میتوانید از آن استفاده کنید.var postCounts = db.BlogPostCounts.ToList();
foreach (var postCount in postCounts)
{
Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
Console.WriteLine();
}
لینک منبع
🔹سورس این پست رو در اینجا بررسی کنید.
@FullStackDevs
#آشنایی_با_تاریخ_و_زمان
#قسمت_اول
▪️تاریخ و زمان بخش مهمی از زندگیه روزمره و همچنین جزئی جدایی ناپذیر در پروژه های ماست
در این مقاله به بررسی تایپ های مختلف برای نگه داری تاریخ و زمان می پردازیم و پیرامون آنها طی قسمت های مختلف بحث خواهیم کرد.
🔸این نوع داده یک ساختار
یک شئ از نوع
یکی از این مشخصه ها
کاربران و همچنین برنامه نویسان به فرمت های مختلفی از زمان تاریخ و زمان نیاز دارند. برای مثال تاریخ در فرمت
🔸 همانطور که گفته شد
🔸گاهی نیاز داریم تا یک رشته را که فرمت تاریخ و زمان دارن به یک شئ
🔸پاسخ واضح است . هر متد برای هدف خاصی است . در اینجا به بررسی برخی میپردازیم
🔸این متد یه شما این اطمینان را میدهد که رشته خودرا به یک فرمت مشخص تبدیل کنید . اما اگر فرمت رشته ورودی با فرمت تعیین شده توسط شما متفاوت باشد سبب صادر شدن یک خطا در برنامه میشود پس اگر از فرمت رشته ورودی خود مطممئن هستید وقصد تبدیل آن به فرمت مورد نظر خود را دارید این متد انتخاب خوبی است.
🔸خروجی این متد یه مفدار بولین است و این اطمینان رو به شما میدهد که رشته ورودی قابل تبدیل به فرمت مشخص شده میباشد یا خیر. واگر قابل تبدیل نباشد خطاهای صادر شده را مدیریت میکند.پس از این جهت هیچ نگرانی برای شما وجود ندارد.
▫️DateTimeOffset
🔸 این تایپ در
فرمت ذخیره سازی تاریخ و زمان در این تایپ به این شکل است
اکثر مشخصه های این تایپ با تایپ DateTime یکسان هستند اما مشخصه های جدیدی نیز به آن اضافه شده است
این مشخصه مقدار زمان را بدون تبدیل ان به زمان محلی برمی گرداند.
این مشخصه مقدار زمان را براساس زمان محلی برمیگرداند.
این مشخصه میزان Offset از UTC را برمیگرداند.
این مشخصه زمان را براساس UTC برمیگرداند.
🔸برای مثال اگر متغیری از نوع
▪️Storing DateTime (UTC) vs. storing DateTimeOffset
🔸 همیشه و همیشه زمان را به صورت
اما در بعضی سناریو های خاص مشکلاتی و چالش هایی وجود دارد به عنوان مثال اگه سناریویی مانند مثال زیر داشته باشید :
@FullStackDevs
#قسمت_اول
▪️تاریخ و زمان بخش مهمی از زندگیه روزمره و همچنین جزئی جدایی ناپذیر در پروژه های ماست
در این مقاله به بررسی تایپ های مختلف برای نگه داری تاریخ و زمان می پردازیم و پیرامون آنها طی قسمت های مختلف بحث خواهیم کرد.
▫️
DateTime🔸این نوع داده یک ساختار
ValueType
مانند int , double
و .. است که در فضای نام System
قابل دسترسی میباشد. این struct
اینتر فیس های IComparable, IComparable<DateTime>, IConvertible, IEquatable<DateTime>, IFormattable, System.Runtime.Serialization.ISerializable
پیاده سازی کرده است .یک شئ از نوع
DateTime
دارای متد هایی برای دستکاری زمان میباشد، متدهایی برای افزودن Day ,Hour,Minute
و همچنین متدهایی یرای تبدیل یک رشته با فرمت تاریخ و زمان به یک شئ ار نوع DateTime
و همچنین دارای مشخصه هایی برای دریافت روز ، ماه ، ساعت از آن شی است.یکی از این مشخصه ها
Kind
میباشد و مشخص کننده نوع زمان برساس مقادیر خروجی زیر است Unspecified، Utc، Local time
DateTime Formattingکاربران و همچنین برنامه نویسان به فرمت های مختلفی از زمان تاریخ و زمان نیاز دارند. برای مثال تاریخ در فرمت
"mm/dd/yyyy"
که به صورت 05/31/2019 نمایش داده خواهد شد.▫️
Handling Nullable DateTime🔸 همانطور که گفته شد
DateTime
یک ValueType
است و به طور پیشفرض نمیتوان به آن مقدار(به اصطلاح) null
را اختصاص داد . یکی از راه های اینکه یک ValueType
مقدار null
را بپذیرد باید elvis-operator را بعد از تعریف نوغ یک متغیر استفاده کرد DateTime? nullDateTime = null;
بدین ترتیب valueType
شما نال پذیر خواهد شد .▫️
Parse string to DateTime object🔸گاهی نیاز داریم تا یک رشته را که فرمت تاریخ و زمان دارن به یک شئ
DateTime
تبدیل کنیم تا عملیات مورد نظرمان را روی انجام دهیم برای انجام دادن این کار متد های متعددی در اختیارمان قرار دارد مثال : Convert.ToDateTime()
DateTime.Parse()
DateTime.ParseExact()
DateTime.TryParse()
DateTime.TryParseExact()
✳️ سوالی که ممکن است در ذهن شما ایجاد شود این است که دلیل این تعداد متد برای تبدیل رشته به زمان چیست⁉️🔸پاسخ واضح است . هر متد برای هدف خاصی است . در اینجا به بررسی برخی میپردازیم
▫️
DateTime.ParseExact()🔸این متد یه شما این اطمینان را میدهد که رشته خودرا به یک فرمت مشخص تبدیل کنید . اما اگر فرمت رشته ورودی با فرمت تعیین شده توسط شما متفاوت باشد سبب صادر شدن یک خطا در برنامه میشود پس اگر از فرمت رشته ورودی خود مطممئن هستید وقصد تبدیل آن به فرمت مورد نظر خود را دارید این متد انتخاب خوبی است.
▫️
DateTime.TryParseExact()🔸خروجی این متد یه مفدار بولین است و این اطمینان رو به شما میدهد که رشته ورودی قابل تبدیل به فرمت مشخص شده میباشد یا خیر. واگر قابل تبدیل نباشد خطاهای صادر شده را مدیریت میکند.پس از این جهت هیچ نگرانی برای شما وجود ندارد.
▫️DateTimeOffset
🔸 این تایپ در
Net framework 3.5
معرفی شد از این نوع تایپ زمانی باید استفاده کرد که اختلاف زمانی برحسب UTC برای ما مهم باشد و بخواهیم در هنگام ذخیره سازی تاریخ و زمان ، زمان به صورت محلی ذخیره نشود و به همراه آن اختلاف زمانی(Offset) نیز ذخیره شود.فرمت ذخیره سازی تاریخ و زمان در این تایپ به این شکل است
Date + Time + Offset
❗️درواقع تعبیر و نام گذاری این تایپ به این شکل( DateTimeWithOffset
) باعث درک بهتر این مسئله میشود.اکثر مشخصه های این تایپ با تایپ DateTime یکسان هستند اما مشخصه های جدیدی نیز به آن اضافه شده است
🔻
DateTimeOffset.DateTimeاین مشخصه مقدار زمان را بدون تبدیل ان به زمان محلی برمی گرداند.
🔻
DateTimeOffset.LocalDateTimeاین مشخصه مقدار زمان را براساس زمان محلی برمیگرداند.
🔻
DateTimeOffset.Offsetاین مشخصه میزان Offset از UTC را برمیگرداند.
🔻
DateTimeOffset.UtcDateTimeاین مشخصه زمان را براساس UTC برمیگرداند.
🔸برای مثال اگر متغیری از نوع
DateTimeOffset
تعریف کنیم وزمان حال را به آن اختصاص دهیم نتیجه به این صورت خواهد بود05/31/2019 03:11:56 PM +04:30
که 05/31/2019 03:11:56 PM
تاریخ و زمان و +04:30
و اختلاف زمانی نسبت به UTC
خواهد بود که اگر اختلاف زمانی را با تاریخ و زمان جمع کنیم UTC
بدست خواهد آمد. این بهترین راه برای کار کردن با محدوده زمانی های مختلف است.▪️Storing DateTime (UTC) vs. storing DateTimeOffset
🔸 همیشه و همیشه زمان را به صورت
UTC
در دیتابیس ذخیره کنید و متناسب با منطقه زمانی کاربر نمایش دهید.اما در بعضی سناریو های خاص مشکلاتی و چالش هایی وجود دارد به عنوان مثال اگه سناریویی مانند مثال زیر داشته باشید :
@FullStackDevs
#ادامه
https://t.iss.one/fullStackDevs/481
🔻زمانی که شما یک سرور و چندین کلاینت با time zone های متفاوت دارید
🔻کلاینت اطلاعاتی را با توجه به تاریخ میسازد
🔻کلاینت قرار است اطلاعات ساخته شده را روی سرور ذخیره کند
🔸برای سناریو بالا اگر زمان را با نوع
و همچنین همه ی کلاینت ها از زمان UTC همه دیتا ها و همچنین از زمان محلی جایی که هر داده در ان سازماندهی شده است اطلاع دارند.
🔸برای سناریو پیشین اگر زمان را فقط به صورت
🔻زمان فقط به صورت UTC ذخیره می شود و دیگر کلاینت ها از زمان محلیه جایی که دیتای مربوطه در آن سازمندهی و ساخته شده اطلاعاتی ندارند (چون اختلاف زمانی محلی که دادها در آنجا ثبت شده مشخص نیست)
🔻 اطلاعاتی در مورد زمان محلی مکانی که اطلاعات در آن ساخته شده است ندارید
و دیگر کلاینت ها تنها می توانند زمان محلی خود را از پایگاه داده (با استفاده از زمان UTC) محاسبه کنند نه زمان محلیه کلاینتی که داده ها در آن ایجاد شده است.
▫️مثال ساده در این مورد سیستم رزرو بلیط هواپیما است که بلیط باید دو زمان را شامل شود.1-زمان بلند شدن هواپیما (منطقه زمانی شهری که از ان پرواز را شروع کرده است) و زمان فرود هواپیما (منطقه زمانی شهری که در آن فرود می آید)
▫️TimeSpan
🔸 ازکاربردهای این نوع داده برای ذخیره فواصل زمانی استفاده میشود . که میتواند این فواصل زمانی را در قالب اعداد مثبت و منفی ذخیره کند. این نوع تایپ بهترین نوع برای ذخیره سازی ساعت میباشد
🔹به دلیل گستردگی مبحث زمان بقیه توضیحات در قسمت های بعد ارائه خواهد شد
@FullStackDevs
https://t.iss.one/fullStackDevs/481
🔻زمانی که شما یک سرور و چندین کلاینت با time zone های متفاوت دارید
🔻کلاینت اطلاعاتی را با توجه به تاریخ میسازد
🔻کلاینت قرار است اطلاعات ساخته شده را روی سرور ذخیره کند
🔸برای سناریو بالا اگر زمان را با نوع
DateTimeOffset
ذخیره کنیم،زمان هم به صورت UTC
و همچنین اختلاف زمانی (Offset
) نسیت به زمان محلی کلاینت ذخیره میشود .و همچنین همه ی کلاینت ها از زمان UTC همه دیتا ها و همچنین از زمان محلی جایی که هر داده در ان سازماندهی شده است اطلاع دارند.
🔸برای سناریو پیشین اگر زمان را فقط به صورت
UTC
ذخیره کنیم در اینصورت 🔻زمان فقط به صورت UTC ذخیره می شود و دیگر کلاینت ها از زمان محلیه جایی که دیتای مربوطه در آن سازمندهی و ساخته شده اطلاعاتی ندارند (چون اختلاف زمانی محلی که دادها در آنجا ثبت شده مشخص نیست)
🔻 اطلاعاتی در مورد زمان محلی مکانی که اطلاعات در آن ساخته شده است ندارید
و دیگر کلاینت ها تنها می توانند زمان محلی خود را از پایگاه داده (با استفاده از زمان UTC) محاسبه کنند نه زمان محلیه کلاینتی که داده ها در آن ایجاد شده است.
▫️مثال ساده در این مورد سیستم رزرو بلیط هواپیما است که بلیط باید دو زمان را شامل شود.1-زمان بلند شدن هواپیما (منطقه زمانی شهری که از ان پرواز را شروع کرده است) و زمان فرود هواپیما (منطقه زمانی شهری که در آن فرود می آید)
▫️TimeSpan
🔸 ازکاربردهای این نوع داده برای ذخیره فواصل زمانی استفاده میشود . که میتواند این فواصل زمانی را در قالب اعداد مثبت و منفی ذخیره کند. این نوع تایپ بهترین نوع برای ذخیره سازی ساعت میباشد
🔹به دلیل گستردگی مبحث زمان بقیه توضیحات در قسمت های بعد ارائه خواهد شد
@FullStackDevs
Telegram
Web Devs
#آشنایی_با_تاریخ_و_زمان
#قسمت_اول
▪️تاریخ و زمان بخش مهمی از زندگیه روزمره و همچنین جزئی جدایی ناپذیر در پروژه های ماست
در این مقاله به بررسی تایپ های مختلف برای نگه داری تاریخ و زمان می پردازیم و پیرامون آنها طی قسمت های مختلف بحث خواهیم کرد.
▫️DateTime…
#قسمت_اول
▪️تاریخ و زمان بخش مهمی از زندگیه روزمره و همچنین جزئی جدایی ناپذیر در پروژه های ماست
در این مقاله به بررسی تایپ های مختلف برای نگه داری تاریخ و زمان می پردازیم و پیرامون آنها طی قسمت های مختلف بحث خواهیم کرد.
▫️DateTime…