<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Mohammad Rabiee</title>
        <link>https://virgool.io/feed/@mrabiee1996</link>
        <description>محمد ربیعی هستم،یک توسعه دهنده نرم افزارهای BackEnd</description>
        <language>fa</language>
        <pubDate>2026-06-16 10:29:31</pubDate>
        <image>
            <url>https://static.virgool.io/images/default-avatar.jpg</url>
            <title>Mohammad Rabiee</title>
            <link>https://virgool.io/@mrabiee1996</link>
        </image>

                    <item>
                <title>مغایرت و خطا در پیاده سازی پرداخت اینترنتی(بخش دوم)</title>
                <link>https://virgool.io/@mrabiee1996/%D9%85%D8%BA%D8%A7%DB%8C%D8%B1%D8%AA-%D9%88-%D8%AE%D8%B7%D8%A7-%D8%AF%D8%B1-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D9%BE%D8%B1%D8%AF%D8%A7%D8%AE%D8%AA-%D8%A7%DB%8C%D9%86%D8%AA%D8%B1%D9%86%D8%AA%DB%8C%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-rdzxl4exrtmv</link>
                <description>در بخش اول مقاله(برای مشاهده کلیک کنید.)، به بررسی و معرفی مفاهیم دخیل در بروز مغایرت و سناریوهای مختلف پرداختیم. در این مقاله تجربیات و الزاماتی را در راستای کاهش و مدیریت بهتر خطاها و جلوگیری حداکثری از بروز مغایرت مطرح میکنیم.بخش دوم : ملاحظات پیاده سازی فلوی پرداختزمانی که کاربر پس از انتخاب محصول و تکمیل اطاعات لازم، روی گزینه پرداخت کلیک کند تا وارد درگاه پرداخت شود.؛ سه مرحله زیر به ترتیب اتفاق می افتد:1) ثبت درخواست کاربر و الگوریتم پیش از ورود به درگاه و انتقال کاربر به درگاه(Before Payment)2) پرداخت توسط کاربر در درگاه3) بازگشت کاربر به نرم افزار، تایید پرداخت و ارائه خدمات توسط سیستم(After Payment)این سه مرحله متوالی، از ضریب حساسیت بسیار بالایی برخوردار هستند. بنابراین برای جلوگیری از خطاهای رایج، حتما نکات زیر را پیاده کنید.بررسی مجدد تمام محدودیت ها در Before Paymentممکن است از زمان تصمیم گیری کاربر برای خرید تا زمانی که اطلاعات خود را تکمیل میکند و دکمه پرداخت را میزند، فعل و انفعالات از جمله تغییر قیمت محصول، ناموجود شدن محصول و موارد مشابه اتفاق بیفتد. بنابراین حتما و حتما باید تمامی موارد حساس مجددا توسط سیستم محاسبه شود و سپس در صورت عدم وجود مشکل کاربر به درگاه منتقل شود. به زبان دیگر، محاسباتی که تا زمان رسیدن کاربر به این مرحله اتفاق افتاده، به هیچ وجه قابل اعتماد نیست و همگی باید مجددا توسط سیستم بررسی شود.1) قیمت ها بررسی شود.2) موجود بودن کالا بررسی شود.3) مجاز بودن کاربر برای خرید بررسی شود.4) در صورت ورود کد تخفیف توسط کاربر، اعتبار کد تخفیف مجددا بررسی شود.5) سایر ملاحظات حساس که در کسب و کار وجود دارد.سناریوی غلط پنهان در پرداخت را نادیده نگیرید!!!زمانی که شما به عنوان توسعه دهنده در حال تست سیستم هستید، ممکن است متوجه مشکلاتی که ممکن است در همزمانی رخ دهد نباشید. در صورتی که تجربه کافی نداشته باشید، ممکن است سناریوی غلط زیر را نادیده بگیرید.زمانی که چند متقاضی برای خرید یک کالا وجود دارد و این کالا یکتاست و یا فقط به تعداد کمی از محصول در انبار وجود دارد، آنگاه اگر محصول را با ورود یک کاربر به درگاه رزرو نکنید، مشکل زیر به وقوع خواهد پیوست.اگر رزرو کردن موقت محصول را فراموش کنید، همانطور که در تصویر فوق میبینید، از نظر سیستم هنوز کالا برای هر دو متقاضی موجود است، چرا که هنوز هیچ یک به مرحله ارائه محصول نرسیده اند، بنابراین هر دو اشتباها وارد درگاه میشوند و کاربری که دیرتر از درگاه خارج میشود دچار مشکل خواهد شد. اما سناریوی درست به صورت زیر است.طول زمان رزرو موقت را بیشتر از مدت مجاز برای پرداخت در درگاه بگذارید.بازبینی مجدد اطلاعات در AfterPaymentپس از تکمیل بازگشت کاربر از درگاه پرداخت، قبل از ارائه خدمات مجددا تمام موارد حساس را بازبینی کنید و اگر مشکلی وجود نداشت خدمات را ارائه کنید.به Client اعتماد نکنیدگاهی حفره های امنیتی زمانی ایجاد میشوند که داده های حساس سیستم را از کلاینت دریافت کنید. مثلا در یکی از مراحل سفارش گیری، قیمت را پس از محاسبه به کاربر اعلام میکنید و سپس به دلایل مختلف(مثلا عدم محاسبه مجدد قیمت به دلیل پیچیدگی) همان قیمت را از کاربر دریافت میکنید و او را با همان مبلغ به درگاه میفرستید. قاعدتا اگر شخص هکری از این موضوع اگاه شود، به سادگی با تغییر در قیمت، با مبلغ بسیار پایین خدمات را دریافت خواهد کرد.البته شاید سناریوی مطرح شده بدیهی به نظر برسد، اما موارد متعددی وجود دارد که به دلیل پیچیدگی سیستم و کم تجربگی، از دید توسعه دهنده دور میماند. بنابراین همیشه داده های حساس قابل محاسبه توسط سیستم را در تمامی مراحل حساس مثل پرداخت، مجددا محاسبه کنید و از Client داده حساسی را دریافت نکنید.(در سناریوی فوق در Before مجددا قیمت را محاسبه کنید و از کاربر فیلد قیمت نگیرید.)از Double Spanding جلوگیری کنیدزمانی که کاربر در درگاه پرداخت اطلاعات کارت را وارد نموده و روی دکمه تکمیل پرداخت کلیک میکند، توسط سرویس بانک به یک ادرس اینترنتی از نرم افزار ما منتقل میشود.(ادرس After Payment) ممکن است کاربر بارها و بارها این صفحه از نرم افزار را رفرش کند. در این زمان چه اتفاقی خواهد افتاد؟ اگر الگوریتم شما به دلیل عدم شناخت صحیح سرویس بانک و یا کم دقتی به گونه ای نوشته شده باشد که با هر بار رفرش و دریافت پیام موفق، خدمات را مجددا ارائه کنید، آنگاه به ازای یک پرداخت چندین بار خدمات داده اید. بنابراین حتما موضوع Double Spanding را تست نموده و از صحت عملکرد سیستم در چنین مواردی اطمینان حاصل کنید.ترجیحا ساز و کاری ایجاد کنید که در صورت رفرش صفحه پرداخت توسط یک کاربر در یک بازه زمانی مشخص(مثلا 1 دقیقه) خود به خود با نمایش پیام مناسب از انجام الگوریتم AfterPayment جلوگیری شود.(به زبان عامیانه اگر کاربر تا یک دقیقه، ادرس After رو رفرش کرد، بفرستیدش به فلوی عملیات مشکوک و اجازه اجرای الگوریتم اصلی پرداخت رو ندید.)از ORM استفاده نکنید!!!اگر از پایگاه داده RDBMS استفاده میکنید، در هیچ یک از بازبینی های فوق از ORM به هیچ وجه استفاده نکنید. ORM به دلیل کندی که به صورت ذاتی ایجاد میکند، امکان محاسبات لحظه ای و دقیق را از بین میبرد و قطعا با مشکل مواجه خواهید شد.مدیریت خطاهای Exception را فراموش نکنیددر مراحل پرداخت به هیچ وجه Exception مدیریت نشده‌ای باقی نگذارید. در تمامی بلاک های خاص و حساس بر حسب الگوریتم پرداخت، Exception ها را مدیریت کنید و در صورت بروز آنها عملیات صحیحی را انجام دهید. به طور مثال گاهی ممکن است مدیریت یک Exception مشخص کننده ناموفق بودن عملیات باشد و پول کاربر را بازگردانید و در یک قطعه کد دیگر ممکن است Exception به معنی نامشخص بودن نتیجه عملیات باشد و به کاربر پیام خطای مناسب نمایش داده و مبلغ را تا زمان مشخص شدن علت مشکل نزد خود نگه دارید.ثبت لاگ را فراموش نکنیددر تمامی قسمت های حساس و مهم که ممکن است خطایی رخ بدهد لاگ ثبت کنید. لاگ ها، نیروهای ویژه و قدرتمندی برای تشخیص و رفع مغایرت هستند.با صبوری تمام سناریوهای محتمل را تست کنید.تمامی کدهایی که توسعه داده اید را تست کنید و هیچ یک را به صورت پیشفرض صحیح و بدیهی تصور نکنید.اگر این مقاله برای شما مفید بود لطفا با سایر دوستان به اشتراک بگذارید.مقاله مرتبط قبلی (بخش اول مقاله)شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-3120برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.org</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Thu, 28 Apr 2022 20:51:51 +0430</pubDate>
            </item>
                    <item>
                <title>مغایرت و خطا در پیاده سازی پرداخت اینترنتی(بخش اول)</title>
                <link>https://virgool.io/@mrabiee1996/%D9%85%D8%BA%D8%A7%DB%8C%D8%B1%D8%AA-%D9%88-%D8%AE%D8%B7%D8%A7-%D8%AF%D8%B1-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D9%BE%D8%B1%D8%AF%D8%A7%D8%AE%D8%AA-%D8%A7%DB%8C%D9%86%D8%AA%D8%B1%D9%86%D8%AA%DB%8C%D8%A8%D8%AE%D8%B4-%D8%A7%D9%88%D9%84-eyf4pcsgnvbc</link>
                <description>قطعا در هر سیستم نرم افزاری، &quot;پرداخت&quot; یکی از مهم ترین و چالش برانگیزترین قسمت هاست و پیاده سازی درگاه های پرداخت نیازمند دقت بسیار بالایی در رعایت برخی اصول است. به طور کلی در تمامی کسب و کارها قسمت هایی که با پول و یا اعتبار کاربران درگیر است از اهمیت و حساسیت بسیار بالایی برخوردار است و وجود مغایرت در پرداخت میتواند عواقب جبران ناپذیری برای کسب و کار به همراه داشته باشد.در این مقاله قصد داریم شکل های معمول و پرتکرار بروز مغایرت و روش های جلوگیری از آن را بررسی کنیم.مقاله در دو بخش نوشته شده است. در بخش اول به معرفی مفاهیم دخیل در بروز مغایرت و سناریوهای مختلف میپردازیم و در بخش دوم(برای مشاهده کلیک کنید.) به بیان تجربیاتی کلی و بسیار مهم در مورد نحوه پیاده سازی سیستم پرداخت و اصولی که باید رعایت کنید میپردازیم. در صورتی که تجربه کمی در پیاده سازی سیستم های پرداخت دارید، در این مقاله بسیاری از فاکتورها و تجربیات مهم در پیاده سازی یک سیستم پرداخت دقیق و بدون خطا را خواهید شناخت.بخش اول : مغایرت و خطا در پیاده سازی یک سیستم پرداختمغایرت چیست؟مغایرت در سیستم را میتوان به معنی عدم تطابق سناریوی رخ داده در سیستم و سناریویی که انتظار آن را داریم دانست که موجب وقوع عدم همخوانی ارقام و داده ها میشود.(طبیعتا در سیستم های مالی، عدم تطابق ارقام ممکن است موجب ضرر و زیان قابل توجهی شود. به طور مثال فرض کنید که در یک ماه، به اندازه 100 میلیون تومان کالا فروخته باشیم و در حساب 80 ملیون تومان واریز شده باشد. در این سناریو 20 ملیون تومان مغایرت داریم که ممکن است به دلیل خطاهای سیستم اتفاق بیفتد.)خطا چیست؟· عدم اجرای صحیح سناریوهای موفق در ارائه خدمات که در صورت عدم کنترل صحیح میتواند موجب بروز مغایرت شود.به طور کلی در سیستم های نرم افزاری و با توجه به ماژولهای مختلفی که در یک عملیات پرداخت دخیل هستند، امکان بروز خطا و مشکل انکارناپذیر است و عامل اصلی بروز مغایرت همین خطاهاست. بنابراین رویکرد ما در جلوگیری از مغایرت به دو شکل زیر خواهد بود:1) جلوگیری از وقوع خطا و مشکل تا حد ممکن.طبیعتا هیچ گاه نمیتوان خطا را به صفر رساند و در بسیاری از سیستم ها، عناصر و ماژولهای بیرونی در بروز یک خطا دخیل هستند؛ اما باید تمام تلاش خود را برای کاهش خطا به کار بگیریم.2) رویکرد مناسب در هنگام بروز خطا و مشکل.زمانی که یک خطا روی میدهد و میتواند بستر وقوع یک مغایرت را فراهم کند، باید همواره تلاش کنیم تا پیشبینی صحیحی از خطاهای ممکن داشته باشیم و در صورت وقوع هر یک سناریوی متناسبی را در راستای رفع مغایرت اجرا کنیم.  به زودی یک سناریوی خاص از این مورد را بررسی خواهیم کرد.انواع محصولاتمفهوم پرداخت در یک سیستم، زمانی معنی خواهد داشت که قصد ارائه یک محصول به کاربر داشته باشیم. با توجه به اینکه چه نوع محصولی ارائه میکنیم، الگوریتم های متفاوتی را برای پیاده سازی درگاه پرداخت خواهیم داشت.به طور کلی محصولات قابل ارائه به صورت زیر هستند.سناریو های مختلف مغایرت و خطا با توجه به قرارگیری کالا در دسته بندی های فوق متفاوت است که مواردی از این تفاوت ها در به صورت زیر است.· فروش یک کالای یکتا به چند کاربر به دلیل عدم کنترل خطای صحیح· فروش بیشتر از ظرفیت یک کالای غیریکتا به مشتریان· فروش کالا با قیمت نادرست به دلایلی همانند عدم کنترل دقیق تغییر قیمت لحظه ای، عدم شناخت صحیح توسعه دهنده از فرآیندهای مالی سیستم و یا سوء استفاده کاربران از سناریوهای دیده نشده امنیتی در سیستم.عناصر دخیل در یک فرآیند پرداختبرای انجام موفق یک پرداخت معمولا ماژولهای نرم افزاری مختلفی که الزاما متعلق به یک سیستم نیستند و از طریق وب سرویس ها با یکدیگر در ارتباط هستند وجود دارد. از جمله این ماژولها میتوان موارد زیر را نام برد.1) سرویس درگاه پرداخت بانکی2) ماژول پرداخت در نرم افزار ما3) ماژول های ارائه دهنده خدمات در سیستم های نرم افزاری دیگربرای روشن تر شدن موضوع به مثال زیر توجه کنید.سامانه واسط فروش بلیت هواپیمافرض کنید که در نرم افزار خود قصد فروش بلیت پرواز دارید. سناریوی پرداخت شامل سه قسمت زیر است.1) سرویسهای درگاه پرداخت: ممکن است از هر یک از PSP هایی که امکان ارائه درگاه دارند، سرویس بگیرید. (درگاه های مختلف مثل بانک زرین پال، سداد، به پرداخت ملت، آسان پرداخت و ...)2) الگوریتم های نرم افزار ما: قطعا شما نیاز دارید اطلاعات پرواز خریدار را به سرویس دهنده ارائه کنید، مبلغ را از طریق درگاه پرداخت دریافت کنید و سپس دستور صدور بلیت را به سرویس دهنده بدهید.3) ماژول ارائه سرویس پرواز: آژانس های هواپیمایی مختلفی هستند که به صورت وب سرویس امکان رزرو بلیت را فراهم میکنند و شما باید از طریق آنها بلیت را دریافت کرده و به کاربر تحویل دهید.همانطور که در مطالب بالا مشاهده کردید، در یک فرآیند فروش بلیت سه ماژول از سه سامانه مختلف دخیل هستند. در صورت عدم پاسخگویی صحیح هر یک از ماژولهای فوق، یک خطا روی خواهد داد و اگر خطا به درستی مدیریت نشود، میتواند موجب بروز مغایرت شود.مدیریت خطامدیریت خطا به این معنی نیست که سیستم به هیچ وجه نباید با مشکل مواجه شود. طبیعتا هر مقدار که تعداد ماژولهای نرم افزاری دخیل در یک عملیات افزایش میابد، جلوگیری از خطا سخت تر و ناممکن تر میشود. بنابراین مدیریت خطا را میتوان در دو مورد زیر خلاصه کرد:1) پیاده سازی سناریوهای مدیریت خطا به صورت خودکار در سیستم تا حد ممکن و جلوگیری از مغایت2) مدیریت خطاهای غیرقابل کنترل توسط سیستم از طریق تیم پشتیبانی محصولطبیعتا اگر سیستم نتواند به صورت خودکار خطا را مدیریت کند، نیاز است تا ماژولهای اطلاع رسانی تقویت شوند و تیم پیشتیبانی با روشهای صحیح مانع بروز مغایرت شود.با توجه به دو مورد فوق، کلید اصلی مدیریت خطا و جلوگیری از مغایرت را میتوان، پیشبینی صحیح از خطاهای ممکن در سیستم و ارائه راهکار سیستمی یا غیر سیستمی برای هر نوع خطا دانست.مثال هایی از سناریوی خطاخطا در سیستم رزرو بلیتمراحل رزرو بلیت معمولا به صورت زیر است:1) رزرو اولیه بلیت2) دریافت مبلغ از کاربر3) صدور نهایی بلیتسناریو شماره 1در موارد بسیاری ممکن است در مرحله صدور نهایی بلیت و پس از دریافت مبلغ از کاربر به دلیل طولانی شدن بیش از حد فرآیند توسط سرویس دهنده، خطای time out اتفاق بیفتد. در این زمان دو سناریوی زیر اتفاق میفتد:1) اگر پول را به کاربر پس بدهیم، ممکن است سمت سرویس دهنده صدور بلیت موفق بوده باشد و متضرر شویم.2) اگر پول را برنگردانیم، کاربر نسبت به عدم دریافت بلیت معترض خواهد بود.هر دو سناریوی فوق در حالت عادی باعث بروز مغایرت میشود. در چنین مواردی باید یک تصمیم گیری کلی از سمت سازمان در مورد برگرداندن یا عدم برگرداندن پول به کاربر اتخاذ شود و باقی مراحل رفع مغایرت توسط تیم پشتیبانی و از روش های غیرسیستمی حل شود.سناریو شماره 2در مواردی ممکن است، قیمت بلیت در حین عملیات پرداخت دچار تغییر شود. دو سناریوی زیر ممکن است اتفاق بیفتد:1) تکمیل پرداخت با قیمت قبلی که موجب بروز مغایرت میشود.2) اصلاح قیمت در حین مراحل پرداخت که تقریبا ناممکن و بسیار پیچیده است.3) ناموفق کردن عملیات، عدم درخواست صدور بلیت نهایی و برگرداندن مبلغ پرداخت شده به کاربرخطا در سیستم فروش شارژ سیمکارتفرض کنید که قصد دارید تا سامانه ای برای فروش شارژ راه اندازی کنید. اگر در این سامانه خطای time out اتفاق بیفتد دو سناریوی زیر محتمل است.1) پول کاربر را پس بدهیم. ممکن است شارژ سیمکارت انجام شده باشد و چون غیرقابل بازپس‌گیری است محتمل ضرر شویم.2) پول کاربر را نگه داریم. ممکن است شارژ انجام نشده باشد و موجب نارضایتی کاربر شود.در سناریوهای فوق راه حل جلوگیری از مغایرت را سازمان تعیین میکند و صرفا با پیشبینی خطا و تصمیم گیری در مورد آن در سازمان میتوان از مغایرت جلوگیری کرد. ممکن است برخی از سناریوهای پیشبینی شده به صورت سیستمی و برخی به صورت غیر سیستمی مدیریت شوند.مروری بر روند تایید تراکنش در درگاه های پرداختزمانی که کاربر در درگاه پرداخت اطلاعت کارت خود را وارد میکند مبلغ از حساب او کسر شده و کاربر به نرم افزار باز میگردد. در این زمان نرم افزار باید پرداخت کاربر را تایید نهایی و خدمات را ارائه کند. برای تایید نهایی باید دو سرویس زیر به ترتیب فراخوانی شود، در غیر این صورت بانک عملیات پرداخت را ناموفق تلقی کرده و مبلغ کسر شده را پس از نهایتا 24 ساعت به حساب کاربر بازمیگرداند.1) Verify Transaction2) Sattle Transactionزمانی که Sattle انجام شود، مبلغ به طور قطع از حساب کاربر کسر میشود. اما در اینجا یک نکته قابل توجه است. زمانی که کاربر از درگاه پرداخت به نرم افزار منتقل میشود، نوبت به ارائه خدمات ما میرسید. اگر به هر دلیل در ارائه خدمات ناموفق باشیم نیاز است تا مبلغ به حساب کاربر بازگردد. بنابراین درگاه های پرداخت سرویسی با عنوان Reverse Transaction  برای بازگرداندن آنی پول به حساب کاربر نیز ارائه میکنند.یک نکته مهمسناریوی ایده آل برای کسب و کار به صورت زیر است.اما همیشه این سناریوی ایده آل قابل پیاده سازی نیست. چرا که برخی از درگاه های پرداخت پس از عملیات Sattle، اجازه فراخوانی Reverse را نمیدهند.در اینگونه موارد دو سناریو از سمت کسب و کار مطرح میشود.1) سناریوی به نفع مشتریناچاریم قبل از عملیات Sattle، سرویس را ارائه کنیم. در این صورت اگر در ارائه سرویس ناموفق باشیم، متد Reverse قابل فراخوانی بوده و مبلغ به حساب کاربر باز میگردد. اما زنگ خطر زمانی به صدا در می‌آید که اگر با موفقیت سرویس را ارائه کنیم و سپس Sattle را فراخوانی کنیم، اگر فراخوانی Sattle به هر دلیل با خطا مواجه شود، خدمات را به کاربر ارائه کرده ایم و مبلغ نیز به حساب کاربر باز خواهد گشت.2) سناریوی به نفع کسب و کارمتد Reverse را نادیده میگیریم و قبل از ارائه خدمات، Sattle را انجام میدهیم. بنابراین حتی اگر در ارائه خدمات ناموفق باشیم، امکان بازگشت پول به حساب کاربر به صورت سیستمی وجود ندارد و کاربر از کسب و کار طلبکار میشود.اجرای هر یک از سناریوهای فوق، وابسته به تصمیم گیری سازمان است و هیچ یک را نمیتوان سناریوی درست تر در نظر گرفت.اگر این مقاله برای شما مفید بود لطفا با سایر دوستان به اشتراک بگذارید.مقاله مرتبط بعدی (بخش دوم مقاله)شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-3119برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.org</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Thu, 28 Apr 2022 20:40:22 +0430</pubDate>
            </item>
                    <item>
                <title>پیاده سازی SignalR به عنوان کلاینت در JavaScript</title>
                <link>https://virgool.io/@mrabiee1996/%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-signalr-%D8%A8%D9%87-%D8%B9%D9%86%D9%88%D8%A7%D9%86-%DA%A9%D9%84%D8%A7%DB%8C%D9%86%D8%AA-%D8%AF%D8%B1-javascript-qwisewthg4uk</link>
                <description>در این مقاله قصد داریم تا ارسال پیام به سرور و دریافت پیام با استفاده از سیگنال در javascript را پیاده سازی کنیم.برای این مثال به صورت ساده به یک صفحه Html ایجاد نموده و فریم ورک SignalR و کدهای js خود را به آن جهت ارسال و دریافت پیام در سیگنال به آن اضافه میکنیم.1) ابتدا فریم ورک جاوا اسکریپت سیگنال را از طریق این لینک دانلود کنید و به صفحه html اضافه کنید.2) سپس باید قطعه کد مربوط به اتصال به سرور سیگنال را از طریق کد زیر وارد کنیم.
var connection = newsignalR.HubConnectionBuilder().withUrl(&amp;quothttp://localhost:5076/hub&amp;quot,
{
//accessTokenFactory: () =&gt; token,
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
}).build();
connection.start();
همانطور که در قطعه کد فوق مشخص است، ابتدا یک کانکشن ایجاد و سپس با فراخوانی متد start، ارتباط را آغاز میکنیم. همچنین  آدرس هاب را در قسمت url فوق قرار داده ایم. لازم به ذکر است، از هاب ایجاد شده در مقاله قبل و متدهای پیاده شده در آن به عنوان سرور استفاده نموده ایم.در صورتی که نیاز به ارسال توکن به هاب داشته باشید، قسمت acceccTokenFactory را از کامنت خارج کرده و پارامتر token را که یک متغیر شامل رشته توکن است به آن بدهید.3)اکنون نیاز داریم تا بتوانیم از طریق سیگنال به سرور پیام ارسال کنیم. برای ارسال پیام به سرور مطابق قطعه کد زیر عمل میکنیم.function AlertToAll() {
connection.invoke(&amp;quotAllertToAll&amp;quot, &amp;quotHello&amp;quot).catch(function (err) {
returnconsole.error(err.toString());
});
}در این مثال فرض بر آن است که متدی تحت عنوان AllertToAll در هاب سرور پیاده سازی شده است و این متد یک رشته را به عنوان ورودی دریافت میکند(برای اطلاع از متدهای هاب و ادرس آن، باید با توسعه دهنده سمت سرور هماهنگ باشید و یا از او یک داکیومنت شامل نام متدها و نوع ورودی های  آن دریافت نمایید و سپس کد خود را توسعه دهید.). بنابراین در قطعه کد فوق، این متد را در سرور و از طریق سیگنال فراخوانی نموده ایم و کلمه Hello را به عنوان ورودی متد ارسال نموده ایم. در صورتی که ارسال پیام با خطا مواجه شود، بلاک catch اجرا میشود. به روش مشابه شما میتوانید هر متدی را در هاب فراخوانی به سادگی فراخوانی نمایید.4) اکنون قصد داریم تا متدهایی را ایجاد کنیم تا سرور بتواند با فراخوانی آنها اطلاعات لازم را به کلاینت ارسال کند. از انجا که ما در حال پیاده سازی قطعه کد JS هستیم، لذا با دریافت پیام از سرور میتوان اطلاعات پوش شده را در هر جای لازم از صفحه استفاده نموده و نمایش داد.(از این طریق به صورت RealTime صفحه به روز میشود).برای این امر از قطعه کد زیر استفاده میکنیم.connection.on(&amp;quotAlertEvent&amp;quot, function (res) {
alert&#40;res&#41;;
});سرور میتواند پیامی را با عنوان AlertEvent به کلاینت پوش کند و پس از آن، بلاک دستورات function که در بالا قابل مشاهده است اجرا میشود. همچنین ورودی که از سمت سرور ارسال میشود در قالب متغیر res در دسترس است که در مثال فوق به صورت alert نمایش داده میشود.5) در نهایت لازم به ذکر است که میتوانید جهت اطلاع از قطعی اتصال به سرور از متد زیر استفاده کنید.connection.(e =&gt; {
//Reconnect  Code
});داخل بلاک دستورات متد میتوانید قطعه کدی جهت اتصال مجدد به هاب قرار دهید.سخن پایانیدر این مجموعه مقاله سعی داشتم تا ضمن معرفی signalR، نحوه استفاده از اون و چالشهای مربوط به سیگنال رو در قالب سه مقاله شامل مباحث تئوری، پیاده سازی سمت سرور و پیاده سازی سمت کلاینت(به عنوان نمون در زبان JS) خدمت شما عزیزان ارائه کنم.سورس کد کامل پیاده سازی سمت سرور و کلاینت رو میتونید از طریق لینک زیر دانلود و سپس اجرا کنید.اگر این مقاله برای شما مفید بود لطفا با سایر دوستان به اشتراک بگذارید.مشاهده و دانلود سورس کد پروژه در گیت هابمقاله مرتبط قبلی (پیاده سازی سمت سرور SignalR)شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-3118برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.org</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Thu, 21 Apr 2022 12:49:34 +0430</pubDate>
            </item>
                    <item>
                <title>پیاده سازی سمت سرور SignalR</title>
                <link>https://virgool.io/@mrabiee1996/%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D8%B3%D9%85%D8%AA-%D8%B3%D8%B1%D9%88%D8%B1-signalr-emcfuq96zlgo</link>
                <description>بعد از بیان مطالب تئوری مربوط به سیگنال، در این مقاله قصد داریم تا به پیاده سازی سمت سرور با استفاده از asp.net core نسخه 6 بپردازیم.(در نسخه های مختلف .net core عملیات مشابهی داریم و جزئیات ممکن است کمی متفاوت باشد.)سورس کد مربوط به مجموعه مقالات SignalR شامل پیاده سازی سمت سرور و کلاینت، جهت یادگیری بهتر شما عزیزان در انتهای این مقاله قابل دانلود و مشاهده است.Hub در SignalR در توسعه یک نرم افزار RealTime، گاها سرور نقش یک واسط میان چند کلاینت و گاها نقش یک منبع تزریق کننده اطلاعات به کلاینت ها مورد استفاده قرار میگیرد.کلاسهای Hub نقطه اتصال کلاینت ها به سرور سیگنال هستند. هر کلاس hub از ادرس مشخصی در شبکه (لوکال یا اینترنت) برخوردار است و کلاینت ها با استفاده از این ادرس به هاب به عنوان دروازه ای در سرور سیگنال متصل میشوند. بنابراین ابتدا باید به نصب فریم ورک مورد نیاز و پیکربندی پروژه و هاب ها بپردازیم.1)  ابتدا یک پروژه از نوع Asp.net core WebApp با نام SignalRSample ایجاد میکنیم.(در این مثال جهت توضیح بهتر از mvc استفاده شده است، شما میتوانید به شکل مشابه در یک پروژه web api پیکربندی را انجام دهید.)میتوانید جهت ایجاد پروژه، مطابق تصویر زیر عمل کنید.2) بعد از ایجاد پروژه فولدر Pages را از طریق Solution Explorer در صورت وجود حذف کنید.3) فریم ورک SignalR را از طریق Nuget Package Manager به پروژه اضافه کنید.میتوانید با استفاده از دستور زیر در Package Manager Console نیز فریم ورک مد نظر را اضافه کنید.Install-Package Microsoft.AspNetCore.SignalR -Version 1.1.04) سپس باید از طریق کلاس Program (Startup در نسخه کور 5 به قبل) مشخص کنیم که در پروژه قصد داریم تا سرویس دهی سیگنال انجام دهیم. (ترتیب قرار دادن کد در کلاس Program اهمیت دارد و باید قبل از فراخوانی متد builder.Build() باشد.)builder.Services.AddSignalR();5) پس از افزودن فریم ورک، باید به ایجاد هاب بپردازیم.a. ابتدا یک فولدر با عنوان ServerHub در سورس پروژه ایجاد کنید.b. سپس کلاس زیر را در فولدر ایجاد کنید.usingMicrosoft.AspNetCore.SignalR;
namespace SignalRSample.ServerHub
{
public class SignalHub:Hub
{
}
}همانطور که میبینید، کلاس فوق از Hub که یک کلاس مربوط به فریم ورک سیگنال است مشتق شده است. در حال حاضر پیاده سازی خاصی از متدهای کلاس هاب نداریم و صرفا پیکربندی های ابتدایی را انجام میدهیم.6) اکنون باید یک ادرس EndPoint به هاب ایجاد شده اختصاص دهیم.در نسخه Core6 کد زیر را به کلاس Program اضافه میکنیم.app.MapHub&lt;SignalHub&gt;(&amp;quot/Hub&amp;quot);· کد بالا باید حتما قبل از فراخوانی متد app.Run() باشد.· در کد بالا مشخص کردیم که از طریق ادرس زیر، هاب همواره در دسترس است.{BaseUrl}/Hub· آدرس پایه (BaseUrl) در فایل زیر مشخص شده است./Properties/ launchSettings.jsonهمانطور که میبینید دو ادرس در تصویر فوق وجود دارد که در صورت دیباگ پروژه از طریق iis ادرس بالا و در صورت استفاده از kestrel ادرس پایین به عنوان ادرس پایه استفاده میشود.نکته مهم: ممکن است کلاینت ها در زمان اتصال به سرور با خطای Cors Error مواجه شوند. جهت جلوگیری از این خطا میتوانید تنظیمات Cors را در کلاس Program یا Startup انجام دهید.(در انتهای مقاله، سورس کد پروژه جهت دانلود قرار گرفته و تنظیمات Cors در آن قابل مشاهده است.)بعد از تنظیمات فوق و با جست و جوی آدرس هاب در مرورگر با خطای &quot;Connection Id required&quot; مواجه میشویم که نشان از درستی انجام پیکربندی فوق است.7) در این مرحله نوبت به تکمیل هاب و اضافه کردن متدهای لازم میرسید.در این مقاله دو نوع ارسال پیام زیر را مورد بررسی قرار میدهیم.1) Broadcast: ارسال یک پیام از سرور به تمامی کلاینت ها2) One-To-One: ارسال پیام از سرور به یک مقصد مشخصاز آنجا که سناریوهای متفاوتی به صورت تجربی وجود دارد، در ادامه مقاله ابتدا به بیان سناریو و سپس کدنویسی میپردازیم.سناریوی شماره یکارسال پیام به صورت Broadcast بر اساس درخواست یک Clientدر این سناریوی ساده، متدی به نام AllertToAll را پیاده سازی میکنیم. متد مد نظر میتواند توسط هر یکی از کلاینت ها فراخوانی شود و پس از فراخوانی شدن ، یک پیام برودکست به تمامی کلاینت ها ارسال میشود.از آنجا که این متد باید توسط یکی از کلاینت ها قابل فراخوانی باشد و سپس Broadcast انجام شود، باید آن را در کلاس هاب که دروازه ارتباطی کلاینت ها با سرور است پیاده سازی کنیم. بنابراین در کلاس هاب مطابق کد زیر، متد AllertToAll را مینویسیم.public class SignalHub:Hub
{
public async Task AllertToAll(string clientMessage)
{
await Clients.All.SendAsync(&amp;quotAlertEvent&amp;quot, clientMessage);
}
}همانطور که میبینید متد AllertToAll در کلاس هاب اضافه شده و متشکل از چند قسمت مختلف است.1) ورودی متد: کلاینت میتواند در زمان فراخوانی این متد، یک مقدار ورودی نیز به آن ارسال کند که از طریق متغیر clientMessage در دسترس است.2) بلاک دستورات متد: شامل کدی که مشخص میکند به تمامی کلاینت ها پیامی با عنوان AlertEvent و مقدار داخل متغیر clientMessage به عنوان بدنه پیام ارسال شود. (طبیعتا کلاینت در زبان برنامه نویسی خود باید متدی جهت دریافت پیام AllertEvent پیاده و ساختار ورودی مناسب پیاده سازی کند.)یک کلاینت میتواند با استفاده از ادرس هاب به سرور متصل شده و ارتباط دائمی را ایجاد کند و سپس در بستر ارتباط ایجاد شده، به متد AllertToAll در هاب پیامی ارسال کند. سپس این پیام به تمامی کلاینت ها برودکست میشود.سناریوی شماره دوارسال پیام به صورت Broadcast بر اساس یک Event در سروربدیهی است که ما الزاما نیاز نداریم تا یک کلاینت شروع کننده یک Broadcast یا هر گونه ارسال پیام باشد. گاها ما نیاز داریم تا پس از یک رویداد در سیستم، یک پیام به کاربران ارسال شود. به طور مثال کدی داشته باشیم تا در ساعت 00:00 هر شب، یک پیام به تمامی کاربران بفرستد.قاعدتا در سناریوی مطرح شده نوشتن متد در هاب کاربردی ندارد، چرا که متدهای هاب با فراخوانی یک کلاینت قابل استفاده هستند و در این سناریو یک کلاینت آغازکننده broadcast نیست. بنابراین نیاز داریم تا بتوانیم به شکل دیگری در هر نقطه از کد سمت سرور خود(خارج از هاب) یک پیام به کاربران ارسال کنیم.برای این منظور میتوانید از قطعه کدی مشابه کد زیر استفاده کنید. در این قطعه کد از طریق کلاسی غیر از هاب(در کد شما میتواند هر کلاسی در هر نقطه از یک سیستم باشد.) یک پیام ارسال میکنیم.public class SampleClass
{
private IHubContext&lt;SignalHub&gt; _hubContext;
public SampleClass(IHubContext&lt;SignalHub&gt; hubContext)
{
_hubContext = hubContext;
}
public void SendBroadcastMessageSample()
{
_hubContext.Clients.All.SendAsync(&amp;quotHelloMessage&amp;quot, &amp;quotHelloWord&amp;quot);
}
}کلاس Sample مثالی از هر نوع کلاس در هر نقطه از پروژه است. آبجکتی از نوع IHubContext&lt;SignalHub&gt; در کلاس Inject شده است و با استفاده از این آبجکت میتوان همانند سناریوی قبل یک پیام به تمام کاربران برودکست نمود.اطلاعات اضافی: در سورس کد پروژه که در انتهای مقاله قرار داده شده،SampleClass در کنترلر Home به عنوان نمونه Inject  و در اکشن SendTest، متد SendBroadcastSample استفاده شده است. از آنجا که مباحث Dependency Injectionخارج از موضوع سیگنال است، از توضیح آن خودداری نموده اما نمونه ای از آن در سورس کد قرار داده ایم. همچنین در صورتی که قصد دارید کلاس SampleClass قابل اینجکت در کلاسهای دیگر باشد باید قطعه کد زیر را به کلاس Programاضافه کنید.builder.Services.AddScoped&lt;SampleClass&gt;();سناریوی شماره سهارسال پیام از یک کلاینت به کلاینتی دیگر بر اساس UserIdدر این سناریو، ما نیاز داریم تا پیام یک کلاینت را مستقیما به کلاینت دیگری بفرستیم. بنابراین نیاز داریم تا بدون broadCast این اتفاق انجام شود بنابراین به کدی برای سازماندهی کلاینت های متصل به سرور نیاز داریم. ابتدا اشاره ای به کاری که باید انجام شود میکنیم:1) گاها کاربران در سیستم ما دارای یک شناسه منحصر به فرد(در این مثال UserId هستند) که صرف نظر از سیگنال، برای ذخیره سازی کاربران در پایگاه داده ها و مدیریت آنها از این آیدی استفاده میشود.2) کاربر پس از اتصال به سیگنال یک ConnectionId منحصر به فرد خواهد داشت.با توجه به دو مورد بالا، ما به لیستی نیاز داریم که پس از اتصال هر کاربر به سیستم، ConnectionId و UserId او را در کنار هم نگهداری کند تا در هر زمان که نیاز بود، با استفاده از UserId به ConnectionId کاربر دسترسی پیدا کنیم و سپس پیامی را به کاربر ارسال کنیم.· نکته بسیار مهم: از آنجا که مبحث توکن دهی به کاربران خارج از موضوع سیگنال است ، در این مثال به هر کلاینت یک Guid که رشته ای منحصر به فرد است به عنوان UserId اختصاص میدهیم. در مثال های واقعی معمولا UserId باید از طریق Token دریافت شود.ابتدا یک کلاس برای نگهداری UserId و ConnectionId کاربران درکنار هم ایجاد میکنیم. طبیعتا این کلاس دارای دو فیلد از نوع رشته است.public class HubConnections
{
public string UserId { set; get; }
public string ConnectionId { set; get; }
}سپس یک لیست استاتیک شامل آبجکت هایی از جنس کلاس فوق در کلاس هاب ایجاد میکنیم.public static List&lt;HubConnections&gt; Connections = new List&lt;HubConnections&gt;();پس از اتصال هر کابر به هاب، باید یک آبجکت متناسب به لیست فوق اضافه شود و با قطع اتصال از لیست فوق حذف شود. اکنون به پیاده سازی متدهای اتصال و قطع اتصال از هاب میپردازیم. برای این منظور دو متد OnConnectedAsync را OnDisconnectedAsync که متدهایی از کلاس پایه هستند override میکنیم. این دو متد به صورت خودکار با اتصال هر کاربر به هاب و قطع اتصال کاربر از هاب فراخوانی میشوند.public class SignalHub : Hub
{
public static List&lt;HubConnections&gt; Connections = new List&lt;HubConnections&gt;();
........
public override Task OnConnectedAsync()
{
var ConnectionId = Context.ConnectionId;
//در مثالهای واقعی میتوانیم یوزر آیدی را از توکن کاربر دریافت کنیم
var UserId = Guid.NewGuid().ToString();
Connections.Add(new HubConnections
{
ConnectionId = ConnectionId,
UserId = UserId,
});
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception? exception)
{
var ConnectionId = Context.ConnectionId;
Connections.RemoveAll(a =&gt; a.ConnectionId == ConnectionId);
return base.OnDisconnectedAsync(exception);
}
}همانطور که ذکر شد متدهای مد نظر override شده و با اتصال کلاینت به هاب، مشخصات او به لیست اضافه شده و با قطع ارتباط از لیست حذف میشود. اگر میخواستیم userId را از Token دریافت کنیم میتوانستیم از کد زیر استفاده کنیم که در این مثال چون سیستم توکن دهی پیاده سازی نشده و این موضوع خارج از مبحث سیگنال است، به یوزر یک آیدی فیک به صورت Guid اختصاص دادیم.public override Task OnConnectedAsync()
{
var ConnectionId = Context.ConnectionId;
string UserId = Context.User.Identity.Name;
Connections.Add(new HubConnections
{
ConnectionId = ConnectionId,
UserId = UserId,
});
return base.OnConnectedAsync();
}با آماده شدن کانکشن میتوانیم متدهای هاب جهت تبادل پیام از یک کلاینت به کلاینت دیگر را بنویسیم.به این منظور متد SendMessage را در هاب پیاده سازی میکنیم. متد SendMessage، یک رشته Json شامل متن پیام و آیدی مقصد را از کلاینت مبدا دریافت میکند.ابتدا کلاس زیر را شامل فیلدهای آیدی کاربر مقصد و متن پیام جهت دیسریالایز کردن Json ورودی، ایجاد میکنیم.public class SendMessageInput
{
public string DestinationUserId { set; get; }
public string Message { set; get; }
}سپس متد را به شکل زیر در هاب پیاده سازی میکنیم.public class SignalHub : Hub
{
public static List&lt;HubConnections&gt; Connections = new List&lt;HubConnections&gt;();
.........
public async Task SendMessage(string input)
{
var inputObject = JsonConvert.DeserializeObject&lt;SendMessageInput&gt;(input);
var destinationConnectionId = Connections.FirstOrDefault(a =&gt; a.UserId == inputObject.DestinationUserId).ConnectionId;
awaitClients.Client(destinationConnectionId).SendAsync(&amp;quotSendMessageEvent&amp;quot,inputObject.Message);
}
}همانطور که میبینید، ابتدا رشته Json به آبجکت سیشارپی دیسریالایز شده،سپس ConnectionId مقصد بر اساس یوزر آیدی ورودی استخراج شده و سرانجام پیام مد نظر مستقیما به مقصد ارسال میشود. (به طریق مشابه با مثالهای قبل، کلاینت باید در کد خود متدی جهت دریافت پیام SendMessageEvent را پیاده سازی کند.)سناریوی شماره چهارارسال پیام از سرور به یک کلاینت خاص بر اساس UserIdبه طریق مشابه با سناریوی شماره دو، گاها ما نیاز داریم تا بدون دخالت یک کلاینت مبدا، پیامی را بر اساس ایونتی خاص در هر نقطه از سیستم(خارج از هاب) به یک کلاینت مشخص ارسال کنیم.  این متد را در کلاس SampleClass با همان توضیحات سناریوی شماره دو اضافه میکنیم.public class SampleClass
{
private IHubContext&lt;SignalHub&gt; _hubContext;
public SampleClass(IHubContext&lt;SignalHub&gt; hubContext)
{
_hubContext = hubContext;
}
.......
public void SendMessage(string userId,string message)
{
var destinationConnectionId =SignalHub.Connections.FirstOrDefault(a =&gt; a.UserId == userId).ConnectionId;
_hubContext.Clients.Client(destinationConnectionId).SendAsync(&amp;quotSendMessageEvent&amp;quot, message);
}
}تنها تفاوت با پیاده سازی متد در هاب آن است که ارسال پیام به کاربران را با استفاده از آبجکتی که در کلاس SampleClass اینجکت شده است انجام میدهیم.همانطور که در مقاله قبلی اشاره شد، ما نیاز داشتیم تا در هر زمان بتوانیم متدی را سمت کلاینت فراخوانی کنیم، و همانطور که در کدهای فوق میبینید، ما در حال ارسال یک پیام به کلاینت هستیم.توضیحات تکمیلیدر این مقاله با عمده مطالب مربوط به پیاده سازی سیگنال سمت سرور آشنا شدیم. نکات تکمیلی زیر قابل توجه است:· فرآیند ارسال پیام به کلاینت توسط سرور را، اصطلاحا پوش کردن نیز میگویند.· با استفاده از سیگنال میتوان پروژه هایی در Scale متوسط را پیاده سازی کرد و برای پروژه های بسیار بزرگ بهتر است به سراغ گزینه های دیگر یا حتی پیاده سازی پایه ای سوکت بروید.· در این مقاله به موضوع امنیت اشاره ای نشد، چرا که بحث امنیت فراتر از سیگنال است و باید به صورت جداگانه بررسی شود.· در این مقاله به معماری کدنویسی سمت سرور اشاره ای نشد. شما میتوانید مطالب ذکر شده را به شکل متناسب با معماری خود استفاده کنید.· یکی از امکانات دیگر SignalR ایجاد گروه ها و ارسال پیام به گروه است. گروه ها متشکل از چند کلاینت هستند و هر گروه شناسه منحصر به فرد خود را دارد. میتوانید در این مورد تحقیق کنید و آموزش های لازم را فراگیرید.مشاهده و دانلود سورس کد پروژه در گیت هابمقاله مرتبط قبلی (آشنایی با فریم ورک SignalR)مقاله مرتبط بعدی (پیاده سازی SignalR به عنوان کلاینت در JavaScript)شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-3117برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Thu, 21 Apr 2022 12:48:27 +0430</pubDate>
            </item>
                    <item>
                <title>آشنایی با فریم ورک SignalR</title>
                <link>https://virgool.io/@mrabiee1996/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-signalr-bmm4ajovrezr</link>
                <description>با سلام، در این مقاله قصد دارم تا شما عزیزان رو با مفاهیم تئوری مربوط به فریم ورک سیگنال که یکی از فریم ورک های پرکاربرد برای توسعه نرم افزار های RealTime است، آشنا کنم.توضیحات رو با یک سوال آغاز میکنیم  و بعد از آشنایی کامل با مفاهیم ابتدایی و ضروری به کدنویسی میپردازیم.فریم ورک نام آشنای SignalR چه کاربردی داره؟اگر توسعه دهنده Back-End باشید، قطعا تا به حال براتون سوال شده که اگر بخواهیم یک نرم افزار به گونه ای توسعه بدیم که به صورت آنی (RealTime) ، کلاینت های ما(صفحات نرم افزار ما) بر اساس رویداد های مختلف آپدیت بشن، باید چیکار کنیم؟نمونه های مختلفی از نرم افزارهای RealTime در دنیای امروز ما قابل مشاهده هست. برای روشن تر شدن سوالمون به چند تا مثال میپردازیم:· یک پیام رسان رو تصور کنید که به محض ارسال پیام از سمت مبدا، در دستگاه هوشمند مقصد پیام نمایش داده میشه.· یک وبسایت که بدون رفرش توسط شما، در صفحات اون اطلاعات آپدیت میشه. مثل وبسایت های کارگزاری بورس یا وبسایت های نمایش لحظه ای نرخ ارز و ....اگر با RestApi ها که مبتنی بر پروتکل HTTP هستند آشنا باشید، قطعا متوجه خواهید شد که از طریق هر RestApi(و هر آنچه که مبتنی بر پروتکل HTTP هست)، نمیتوان نرم افزار RealTime توسعه داد. اما چرا؟به زبان ساده در پروتکل HTTP همیشه یک درخواست(Request) از سمت کلاینت به سرور ارسال میشه. اما وقتی ما بخوایم برعکس این اتفاق بیفته، یعنی سرور این امکان رو داشته باشه تا کلاینت ها رو از یک رویداد و یک تغییر با خبر کنه، در پروتکل http دست ما بسته است و سرور نمیتونه شروع کننده یک درخواست باشه.حالا که با صورت مسئله کاملا آشنا شدید بپردازیم به راه حل:اگر بخواهیم ارتباط پایداری میان کلاینت و سرور برقرار کنیم تا در زمان لازم هر یک از طرفین بتواند آغاز کننده یک تبادل پیام باشد، باید از پروتکل سوکت استفاده کنیم.استفاده از سوکت به خودی خود شاید کمی دشوار باشه، برای همین فریم ورک هایی بر بستر سوکت توسعه داده شده که این اجازه رو به ما میده تا خیلی ساده تر و با حداقل درگیری با مفاهیم پایه بتونیم یک بستر تبادل اطلاعات سوکتی و RealTime رو پیاده سازی کنیم و یکی از این فریم ورک ها سیگنال هست.اگر علاقه مندید تا به صورت پایه ای تر با سوکت و پروتکل Http آشنا بشید، میتونید روی لینک زیر کلیک کنید.حالا که فهمیدیم سیگنال چه کاربردی داره سوال دیگه ای رو مطرح میکنیم:سیگنال چجوری کار میکنه؟همونطور که بالاتر اشاره کردیم، اگر بتونیم از طریق سرور، کلاینت های خودمون رو از یک رویداد مطلع کنیم، بخش عمده ای از مسئله ی RealTime بودن رفع شده.سیگنال برای زبانهای برنامه نویسی معروف، به عنوان سرور و کلاینت توسعه داده شده و توسعه دهندگان زبانهای مختلف به سادگی میتوانند از سیگنال استفاده کنند.بنابراین با روشهای بسیار ساده که کمی جلوتر به صورت عملیاتی به شما نشون خواهیم داد، بعد از برقراری ارتباط بین طرفین (Handshake) سرور میتونه یک تابعی در نرم افزار کلاینت و همینطور کلاینت یک تابع از نرم افزار سمت سرور رو در زمان لازم و با حداقل محدودیت فراخوانی کنه و کاملا با هم به تبادل اطلاعات بپردازند.(در پروتکل http فقط کلاینت میتونست یک تابع رو از طریق RestApi یا روشهای دیگه، بر روی نرم افزار سمت سرور فراخوانی کنه و یک جواب متقابل دریافت کنه، اما اینجا دو طرف کاملا آزاد هستند تا به هم پیام بفرستند.)حالا نوبت میرسه به توضیحات جزئی ترسیگنال به چه صورت امکان شروع یک درخواست رو برای هر دو طرف سرور و کلاینت فراهم میکنه و چرا در روشهای مبتنی بر HTTP این امکان وجود نداره؟سیگنال و روشهای مبتنی بر HTTP هر دو بر بستر سوکت فعالیت میکنند، اما در سطح بالاتر از سوکت، از پیاده سازی های متفاوتی برخوردارند.· نحوه عملکرد پروتکل HTTP به این صورت هست که در هر درخواست ابتدا کلاینت به سرور متصل شده و یک درخواست به سمت سرور ارسال و با دریافت پاسخ از سرور، ارتباط کاملا قطع میشود.به زبان دیگر، چون سرور از آیپی ثابتی برخوردار است و نرم افزار سرور در حالت عادی همیشه در حال اجراست، هر زمان که کلاینت نیاز داشته باشد، یک Request به سرور ارسال میکند.بنابراین در پروتکل HTTP ارتباط ماندگار عملا معنایی نخواهد داشت. در واقع HTTP یک پروتکل مبتنی بر سوکت با قوانین سطح بالاتری است.· سیگنال مبتنی بر سوکت است، اما ارتباط در سیگنال به صورت پایدار برقرار میشود. یعنی ابتدا میان کلاینت و سرور یک Handshake رخ میدهد و سپس تا زمانی که شرایط لازم (مثل وصل بودن شبکه و موارد مشابه) برقرار باشد، ارتباط قطع نخواهد شد.بنابراین در این ارتباط پایدار، کلاینت هر زمان که نیاز داشته باشد، به سرور درخواست خواهد داد و سرور هر زمان که بخواهد تابعی سمت کلاینت فراخوانی میکند.(شاید بپرسید اگر سیگنال انقدر راحته، پس چرا از RestApi با محدودیت های ذکر شده استفاده میکنیم؟ جواب این سوال رو با مطالعه مقاله های مربوط به پروتکل HTTP و آشنایی با سوکت خواهید فهمید.)در سیگنال کلاینت ها بر چه اساسی تفکیک میشن؟در ارتباط با استفاده از سیگنال، طرفین ارتباط باید اطلاعاتی از طرف مقابل در اختیار داشته باشند. قاعدتا برای کلاینت، از طریق ادرس ip سرور، همواره امکان ارسال پیام به سرور مقدور خواهد بود. اما مسئله اصلی تشخیص کلاینت ها از طریق سرور است.بعد از عملیات Handshake و شروع ارتباط ماندگار میان سرور و کلاینت که از طریق کلاینت آغاز میشود (به زبان ساده کلاینت به سرور برای ایجاد ارتباط درخواست میده) سرور به هر کلاینت یک Id منحصر به فرد تحت عنوان Connection Id اختصاص خواهد داد. توسعه دهنده سمت سرور این آیدی های مربوط به کلاینت های مختلف را در یک لیست نگهداری خواهد کرد.هر زمان که نیاز داشته باشیم تا به یک کلاینت خاص از سمت سرور پیامی بفرستیم، از طریق این Connection Id به سادگی به کلاینت دسترسی خواهیم داشت.(به زبان ساده، سرور میتونه به یک کلاینت با سشن ایدی مشخص پیام بفرسته.) از آنجا که ارتباط بین کلاینت و سرور پایدار است، این Connection Id تا زمانی که به دلایل مختلف ارتباط قطع نشود اعتبار دارد.پس از قطع ارتباط میان سرور و کلاینت، سرور Connection Id مربوط به کلاینت را از لیست خود حذف میکند. اگر نیاز به برقراری مجدد ارتباط باشد، کلاینت مجددا Handshake انجام داده و با Connection Id جدید ارتباط دائمی اتفاق می‌افتد.(قطعی ارتباط در سوکت یک امر اجتناب ناپذیر است. عواملی همانند قطعی اینترنت به صورت خواسته یا ناخواسته، پالیسی های امنیتی و ... میتواند موجب قطع شدن ارتباط سوکتی شود و با رفع مشکل مجددا ارتباط برقرار میشود.)بنابراین تا زمانی که ارتباط قطع نشود، کلاینت از طریق ادرس IP به سرور و سرور از طریق Connection Id به کلاینت دسترسی دائمی دارد.(Connection Id شناسه ای است که فریم ورک در اختیار ما قرار میدهد، و در بک گراند ماجرا ممکن است اطلاعات بیشتری همانند آیپی موقت کلاینت یا ... بدون اطلاع ما استفاده شود.)در مقالات بعد، مطالبی که در این مقاله به صورت تئوری توضیح داده شد، کدنویسی میکنیم و بعد از کدنویسی های ابتدایی به توضیحات مباحث پیشرفته تر از جمله مدیریت کاربران و توکن دهی در سیگنال خواهیم پرداخت.مقاله مرتبط بعدی (پیاده سازی سمت سرور SignalR)شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-3116برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Thu, 21 Apr 2022 12:47:06 +0430</pubDate>
            </item>
                    <item>
                <title>آشنایی با الگوی Generic Repository</title>
                <link>https://virgool.io/Solidity/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%A7%D9%84%DA%AF%D9%88%DB%8C-generic-repository-ceswijve6y7t</link>
                <description>در این مقاله به بررسی الگویی بسیار مهم و جذاب با عنوان Generic Repository میپردازیم. این الگو را میتوان برای استفاده های مختلف پیاده سازی نمود، اما به طور عمده برای ارتباط نرم افزار و پایگاه داده کاربرد دارد. از مزایای این الگو میتوان به موارد زیر اشاره کرد: (ترجیحا مفاهیم مختصر زیر را مطالعه کنید تا به چرایی استفاده از این الگو پی ببرید.)· تسهیل و الگوپذیر بودن پیاده سازی ارتباط با دیتابیس و عملیات CRUD· پیاده سازی دقیق مفهوم Encapsulationهمانطور که میدانید، مفهوم کپسوله سازی، یکی از مفاهیم بسیار مهم در کدنویسی شیء‎‌گراست. (البته امروزه تقریبا تمام زبانهای غیر شیء گرا نیز اهمیت بسیار زیاد این موضوع را انکار نمیکنند.) به طور معمول یک پروژه برنامه نویسی از ماژول های مختلفی تشکیل شده است. اگر مفهوم کپسوله سازی در پیاده سازی ماژول ها رعایت شود، ماژول A صرفا میداند که ماژول B چه کاری میکند و از اینکه چگونه کار میکند اطلاعی ندارد. بنابراین اگر در نحوه پیاده سازی یک ماژول تغییری ایجاد شود، سایر ماژول ها دست خوش تغییر نخواهند شد(چون به چگونه کار کردن یا همان نحوه پیاده سازی هیچ وابستگی ندارند).اگر بخواهیم مفهوم کپسوله سازی را در سطح این مقاله شرح دهیم، میتوان گفت که ماژولهای پروژه ما نیاز دارند تا عملیات Crud را انجام دهند، اما معمولا نیازی به اینکه بدانند ما از چه پایگاه داده ای استفاده کرده ایم و یا برای ارتباط با پایگاه داده از چه فریم ورک هایی استفاده کرده ایم ندارند.(مثلا ماژول ثبت نام نیاز دارد تا یک کاربر را در دیتابیس درج کند، اما اینکه دیتابیس پروژه چیست و با چه فریم ورکی اینزرت انجام میشود اصلا اهمیتی ندارد.) به زبان دیگر، شاید نیاز باشد تا ما از یک پایگاه داده(مثلا Sql Server) به یک پایگاه داده دیگر(مثلا Mongo DB) کوچ کنیم. قاعدتا ماژولهای پروژه ما بر اساس این تغییر نباید نیاز به اصلاح پیدا کنند و صرفا باید نحوه پیاده سازی ماژول ارتباط با پایگاه داده اصلاح شود. در یک سناریوی دیگر، شاید نیاز داشته باشیم تا در تمام قسمتهای پروژه Entity Framework را حذف و Dapper را جایگزین کنیم. اگر این تغییر باعث شود که تمام ماژولهای پروژه نیاز به اصلاح پیدا کنند قطعا کپسوله سازی رعایت نشده است. با استفاده از الگوی جنریک، این مورد به شکل بسیار دقیقی قابل پیاده سازی است.در این مقاله·  معماری پروژه را در نظر نمیگیریم و صرفا به نحوه پیاده سازی جنریک میپردازیم. این الگو را میتوان در معماری های مختلفی استفاده نمود.· از پروژه و پایگاه داده ایجاد شده در مقاله «طراحی پایگاه داده codefirst» استفاده میکنیم. در صورت نیاز ابتدا به مطالعه مقاله مذکور بپردازید.· پروژه از نوع Asp.net WebApi و Core 6 است. در Core 6 پیکربندی های پروژه از طریق کلاس Program انجام میشود، در حالی که در نسخه های پایین تر ، به جای کلاس Program از کلاس Startup استفاده میشود، اما شکل کلی پیکربندی ها مشابه و با کمی اصلاح قابل پیاده سازی است.· از EntityFramework استفاده شده است و در مقالات بعدی Dapper را نیز بررسی خواهیم کرد.(خب توضیحات تئوری کافیه، بریم سراغ پیاده سازی و کد زدن:)Generic Repository از چه اجزایی تشکیل میشود.· به طور کلی ما در این الگو یک قسمت پایه داریم که شامل عملیات مشترک میان تمام انتیتی ها میشود. در این قسمت متدهای Insert، Update، Delete و هر آنچه که مشترکا برای کار با تمام انتیتی ها نیاز داریم را جهت جلوگیری از کدنویسی اضافه و تکراری پیاده سازی میکنیم.این قسمت شامل اینترفیس IBaseRepository و کلاس BaseRepository است.· یک قسمت اختصاصی برای انتیتی ها داریم که در حالت عادی شامل تمام متدهای قسمت پایه به علاوه متدهای ویژه و خاص هر انتیتی است.این قسمت به ازای هر انتیتی شامل یک اینترفیس و یک کلاس است.مراحل کدنویسی1) ابتدا فولدر Infrastructure را که خود شامل دو فولدر Interface و Repository است در سورس پروژه میکنیم.اینترفیس های مربوطه را در فولدر Interface و کلاس ها را در فولدر Repository پیاده سازی میکنیم.2) ابتدا اینترفیس IBaseRepository را که شامل تعریف متدهای پایه و مشترک است ایجاد میکنیم. https://gist.github.com/rabieedev1996/438562df71136ad9e258fe71e5a98597 3) کلاس BaseRepository که وظیفه پیاده سازی متدهای موجود در IBaseRepository را دارد پیاده سازی میکنیم. دقت کنید که TEntity در این نمونه، مشخص کننده نوع کلاس انتیتی است و در ادامه مراحل کاربرد آن را خواهید دید. https://gist.github.com/rabieedev1996/564359cf6e43fb06b49010261821e56b در مراحل فوق، قسمت مشترک میان تمام انتیتی ها پیاده سازی شد.4) به ازای هر انتیتی یک اینترفیس و یک کلاس خواهیم ساخت. این اینترفیس ها و کلاسها محل اتصال ماژول های ما و انتیتی جهت عملیات Crudخواهند بود که در انتهای مقاله خواهید دید. https://gist.github.com/rabieedev1996/845d94a1d525ef8ba57b2d1da431e438 در این نمونه، اینترفیس و کلاس جنریک مربوط به انتیتی User را پیاده سازی کردیم. همانطور که میبینید به واسطه ارث بری کلاس UserRepository از BaseRepository تمامی متدهای کلاس پایه در UserRepository وجود دارد. اگر بخواهیم متدهای اضافه تری، مخصوص انتیتی یوزر داشته باشیم، میتوانیم ابتدا در اینترفیس IUserRepository تعریف و سپس در کلاس UserRepository پیاده سازی کنیم. همچنین TEntity نیز با تایپ انتیتی(User) مقداردهی شده است.1) TEntity در کلاس BaseRepository چه کاربردی دارد؟از آنجا که کلاسهای پایه به تمامی انتیتی ها اختصاص دارند، نیاز است تا مشخص شود که دقیقا کلاس پایه عملیات خود را روی کدام انتیتی(کدام جدول) انجام دهد. بنابریاین TEntity وظیفه مشخص کردن این موضوع را بر عهده دارد و از طریق کلاسهای جنریک مربوط به هر انتیتی، همانند نمونه فوق مشخص میشوند.2) چرا برای هر انتیتی یک اینترفیس استفاده کردیم؟این موضوع دقیقا به توضیحات ابتدای مقاله، پیرامون موضوع کپسوله سازی دلالت دارد. اینترفیس ها مشخص میکنند که ماژول ما چه کاری میکند و همانطور که میبینید خالی از هرگونه پیاده سازی هستند. کلاسها وظیفه پیاده سازی وظایف را بر عهده دارند. بدون اینترفیس ها در بسیاری از موارد(به طور مثال در معماری کلین) به هیچ وجه قادر نخواهیم بود تا کپسوله سازی را پیاده سازی کنیم. هر چند این موضوع به معماری پروژه ما وابستگی زیادی دارد، اما بهترین شکل پیاده سازی کپسوله سازی، صرفا با وجود اینترفیس ها مقدور است.5) به روش مشابه، برای تمام انتیتی ها پیاده سازی را انجام میدهیم.الگوی ما پیاده سازی شده است، اکنون ماژولهای مختلف میتوانند با استفاده از یکی از دو روش مرسوم زیر عملیات CRUD را به راحتی انجام دهند.برای اینکه بتوانیم در نهایت از الگوی فوق استفاده کنیم،  یک کنترلر نمونه به نام Homeایجاد و در آن یک اکشن به نام Sample اضافه نموده ایم. اکشن Sample، از الگوی فوق به دو روش زیر جهت دریافت یک User با نام کاربری Rabiee از پایگاه داده استفاده میکند.روش اول: UnitOfWorkدر این روش، یک کلاس به نام UnitOfWork خواهیم داشته که از هر ریپازیتوری، یک آبجکت به عنوان پارامتر دارد. هر زمان که بخواهیم از ریپازیتوری ها استفاده کنیم، یک آبجکت از کلاس UnitOfWorkمیسازیم و به این واسطه به تمام ریپازیتوری ها دسترسی داریم. پیاده سازی کلاس UnitOfWork در نمونه ما به شکل زیر خواهد بود. https://gist.github.com/rabieedev1996/116ff5a4f00cf31df1f7276d71792b7e برای اینکه بتوانیم از UnitOfWorkاستفاده کنیم، یک پارامتر از این نوع با نام _Context در کنترلر قرار داده ایم. اکشن Sample، از _Context جهت دریافت یک User با نام کاربری Rabiee استفاده میکند. https://gist.github.com/rabieedev1996/2c2f64f7db57cd70c290976beccd3f2d همانطور که میبینید،در سازنده کنترلر یک آبجکت از نوع UnitOfWork به نام _Context ایجاد نموده و در اکشن Sample با استفاده از آن کاربری را که نام کاربری او Rabiee است خارج کردیم.در نهایت، در صورتی که قصد دارید با استفاده از UnitOfWork پیاده سازی را انجام دهید، قطعه کد زیر را به کلاس Context اضافه کنید.   protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
           if (!optionsBuilder.IsConfigured)
           {
                   optionsBuilder.UseSqlServer(&amp;quotServer=.;Database=Seller;User Id=sa;Password=123456;&amp;quot);
            }
     }روش دوم: استفاده از تزریق وابستگی(Dependency Injection)این روش مرسوم تر و بسیار کاربردی تری نسبت به UnitOfWork است، چرا که در معماری های سطح بالا نمیتوان از UnitOfWork استفاده کرد اما این روش در هر معماری به شکل دقیقی و بسیار کارآمد قابل استفاده است.در پروژه های Asp.net Core، میتوان از تزریق وابستگی به صورت Built In استفاده نمود. ابتدا باید در کلاس Program یا Startup، مشخص کنیم که قرار است چه کلاسهایی Inject شود. قاعدتا در این مثال باید بتوانیم اینترفیس های مربوط به انتیتی ها را در تمامی ماژول ها Inject کنیم تا در صورت نیاز استفاده کنند. بنابراین از قطعه کد زیر استفاده میکنیم.builder.Services.AddScoped(typeof(IBaseRepository&lt;&gt;), typeof(BaseRepository&lt;&gt;));
builder.Services.AddScoped(typeof(IUserRepository), typeof(UserRepository));
builder.Services.AddScoped(typeof(ICategoryRepository), typeof(CategoryRepository));
builder.Services.AddScoped(typeof(IProductRepository), typeof(ProductRepository));
builder.Services.AddScoped(typeof(IPaymentRepository), typeof(PaymentRepository));
builder.Services.AddScoped(typeof(IBasketRepository), typeof(BasketRepository));به واسطه کد فوق، میتوانیم ریپازیتوری مد نظر را در سازنده کلاسهای مختلف به عنوان ورودی درج و از آن استفاده کنیم.(اینجکت کنیم)در کنترلر Home، ریپازیتوری مربوط به User را اینجکت میکنیم. سپس از آن در اکشن Sample جهت استخراج کاربری با نام Rabiee استفاده میکنیم. پیاده سازی به شکل زیر است. https://gist.github.com/rabieedev1996/4b5df41cb33eaccc714436d086a03078 در نهایت با فراخوانی سرویس  Sample(http://localhost:5232/home/sample) خواهید دید که ارتباط با پایگاه داده به درستی برقرار خواهد شد.· این مقاله صرف نظر از پیاده سازی معماری است. به طور کلی الگوی جنریک شامل همین مفاهیم است و معماری صرفا محل قرار گیری کلاسها و اینترفیس ها را در پروژه تغییر میدهد.· در این مقاله جهت پیاده سازی کلاسهای پایه از EntityFramework استفاده شد، اما این اجبار نیست و شما میتوانید در هر یک از متدها، از framework مد نظر خود استفاده کنید.· همانطور که در ابتدای مقاله اشاره شد، اگر بخواهیم پایگاه داده پروژه را تغییر دهیم صرفا پیاده سازی های داخل کلاسهای ریپازیتوری را تغییر میدهیم و سایر ماژولها که صرفا اینترفیس ها را میبینند با تغییری مواجه نخواهند شد.سورس کد پروژه در گیت هاب(کلیک کنید)در مقالات بعد جهت آشنایی با فریم ورک پرکاربرد Dapper، سناریوی نمونه ای را پیاده سازی خواهیم کرد.شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-3113برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Sat, 12 Mar 2022 22:34:41 +0330</pubDate>
            </item>
                    <item>
                <title>طراحی پایگاه داده به روش CodeFirst</title>
                <link>https://virgool.io/Solidity/%D8%B7%D8%B1%D8%A7%D8%AD%DB%8C-%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87-%D8%AF%D8%A7%D8%AF%D9%87-codefirst-b2qvluik9nr6</link>
                <description>در این مقاله قصد داریم تا به ایجاد یک دیتابیس نمونه در پایگاه داده sql Server با روش codefirst و با استفاده از migration ها بپردازیم. هدف اصلی از ایجاد این پایگاه داده، پیاده سازی الگوی Generic Repository در مقالات بعدی است؛ لذا تصمیم گرفتم تا مراحل طراحی این پایگاه داده را به صورتcode first انجام داده و به صورت یک مقاله آموزشی به انتشار آن بپردازم. همچنین جهت توسعه از  Asp.net Web Api و Core6 استفاده نموده ایم.پیش نیاز های این مقاله1) آشنایی با پایگاه داده های رابطه ای2) آشنایی با زبان برنامه نویسی سیشارپ3) نصب پایگاه داده Sql Server و آماده سازی آن جهت اتصال از طریق connection string(جهت یادگیری مراحل نصب Sql server به این لینک مراجعه نمایید.)4) ترجیحا آشنایی با محیط ویژوال استدیواکنون برای آن دسته از عزیزانی که با کلمه مایگریشن آشنایی ندارند به سوال زیر پاسخ میدهیم.Migrationچیست؟از مایگریشن ها برای ایجاد پایگاه داده بر اساس کدهایی که توسعه داده ایم، استفاده میکنیم. همانطور که از عنوان Code First مشخص است؛ در ابتدا entity ها (در واقع مدل متناظر با جداول ما در پایگاه داده هستند) و روابط آنها و سایر پیکربندی ها را پیاده سازی میکنیم و سپس با استفاده از مایگریشن، دیتابیس اصلی خود را روی سرور RDBMS که در اینجا sql server و به صورت لوکال سرور(روی رایانه شما) است ایجاد میکنیم.پایگاه داده‌ای که قصد داریم بسازیم مربوط به یک سیستم فروشگاهی و شامل جداول زیر است.(این پایگاه داده نمونه و جهت یادگیری است و ممکن است از دقت بیزینسی  جهت پیاده سازی دقیق برخوردار نباشد.)1) Categories: شامل اطلاعات دسته بندی محصولات2) Products: شامل اطلاعات محصولات3) Users: شامل اطلاعات کاربران4) Payments: شامل اطلاعات پرداخت ها5) Baskets: شامل اطلاعات سبد خرید مربوط به پرداخت های کاربراندیاگرام پایگاه دادهدیاگرام پایگاه داده نهایی و روابط آن به صورت زیر خواهد بود.مراحل پیاده سازی1) ابتدا یک پروژه از نوع Asp.Net Core Web App با نامی دلخواه(در اینجا CodeFirst) ایجاد نمایید.(در این مثال از این نوع پروژه استفاده شده است، اما این اجباری نیست و به نیاز شما بستگی خواهد داشت.)2) در پروژه ایجاد شده framework های زیر را از طریق کنسول یا ویزارد NuGet اضافه نمایید.Install-Package Microsoft.EntityFrameworkCore -Version 6.0.2
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 6.0.2
Install-Package Microsoft.EntityFrameworkCore.Tools -Version 6.0.2فریم ورک های فوق مربوط به entity framework جهت کار با پایگاه داده ‌ها از جمله sql server و همچنین امکان انجام مایگریشن است.3) سپس در مسیر پروژه ایجاد شده، فولدری با نام Entities جهت قرار دادن کلاسهای entity اضافه کنید.4) سپس کلاسهای انتیتی زیر را به پروژه اضافه میکنیم.· این انتیتی ها مربوط به جداول پایگاه داده هستند که در ابتدای مقاله نام برده شد.· هر یک از انتیتی ها شامل کلید Id به عنوان PrimaryKey و همچنین  ForeignKey(در صورت لزوم) است.·  سایر فیلدهای انتیتی صرفا به عنوان نمونه قرار داده شده و از آنجا که در محتوی آموزشی ما نقش چندانی ندارند بسیاری از فیلدهایی که در پیاده سازی عملیاتی ممکن است لازم باشد در نظر گرفته نشده است.· کلاس EntityBase به خودی خود یک جدول در پایگاه داده نیست اما در سطح کد، شامل فیلدهای مشترکی است که در سایر انتیتی ها باید وجود داشته باشد. از جمله این فیلدها میتوان به تاریخ ایجاد یک رکورد(CreatedDate)، فیلد مربوط به حذف یک رکورد(IsDeleted) و فیلد مربوط به تاریخ ویرایش یک رکورد(LastModifiedDate) اشاره کرد.  قاعدتا سایر انتیتی ها باید این فیلدها را از EntityBase به ارث ببرند. https://gist.github.com/mrabiee1375/ed47971884dc0ed0fe43c3f6ea92cc5c نکته مهم: در طراحی انتیتی ها، برای ایجاد روابط یک به چند(one to many)  همانند رابطه دسته بندی و محصول(یک دسته بندی شامل چند محصول است.) باید در کلاس طرف one (Category) لیستی از کلاسهای طرف  many(Product) قرار داده و همچنین در طرف کلاس many (در اینجا Product) یک ابجکت از جنس کلاس طرف one (در اینجا Category) قرار دهید  که در کلاسهای فوق پیاده سازی شده است.به زبان ساده تر، از آنجا که یک کتگوری شامل چند محصول است لیستی از محصولات داخل کلاس خود دارد و از آنجا که یک محصول قطعه متعلق به یک کتگوری است، یک آبجکت کتگوری در کلاس خود دارد.5) پس از پیاده سازی کامل انتیتی ها، نوبت به ایجاد کلاسContext  است. این کلاس، از DbContext که یک کلاس built int در انتیتی فریم ورک است، ارث بری میکند. این کلاس در واقع نقطه اتصال ما به پایگاه داده در زمان اجرای یک کوئری یا انجام مایگریشن ها است بنابراین از اهمیت خاصی برخوردار میباشد. به طور کلی در این کلاس موارد زیر قرار میگیرد:· DbSet نگاشت انتیتی به جداول پایگاه داده است. به طور مثال به کد زیر توجه کنید.public DbSet&lt;User&gt; Users { get; set; }قطعه کد فوق مشخص میکند که باید در پایگاه داده جدولی به نام Users وجود داشته باشد که فیلدهای آن مطابق با انتیتی User است.· بازنویسی(override) متد OnModelCreating که در این متد پیکربندی های خاصی از جداول پایگاه داده، رکوردها و فیلدهای آن مشخص میشود. پیکربندی های مختلفی در طول پروژه نیاز میشود که در متد میتوان مشخص نمود.(به طور مثال default value، computed column و موارد این چنینی...)· بازنویسی متد SaveChangeAsyncاین متد زمانی که یک رکورد با استفاده از انتیتی فریم ورک در دیتابیس insert یا update میشود فراخوانی میشود و از طریق آن میتوان برخی عملیات کاربردی و مفید را پیاده سازی کرد. به طور مثال در این پروژه، ما بر اساس اینکه یک رکورد در حال insert است یا update، فیلدهای CreatedDate یا LastModifiedDate را برای رکورد مقداردهی میکنیم.در مجموع، پیاده سازی کلاس Context با اجزای ذکر شده به شکل زیر خواهد بود. https://gist.github.com/mrabiee1375/d0f2d56a6320c1f1095e58021aec95b9 در متد OnModelCreating، باید روابط و کلید خارجی موجود در هر یک از روابط دقیقا مشخص شود. به طور مثال قطعه کد زیر یک رابطه مابین جداول Product و Category را مشخص میکند.modelBuilder.Entity&lt;Product&gt;().HasOne(d =&gt; d.Category)
.WithMany(p =&gt; p.Products)
.HasForeignKey(d =&gt; d.CategoryId);6) پس از ایجاد Context باید آن را در کلاس  Program(Startup در نسخه 5 به قبل Core) جهت Inject شدن در سایر کلاسهای پروژه و مشخص کردن ConnectionString پیکربندی کنیم. رشته اتصال دیتابیس را در فایل App Setting قرار میدهیم. این فایل باید به شکل زیر باشد:{&amp;quotLogging&amp;quot: {
&amp;quotLogLevel&amp;quot: {
&amp;quotDefault&amp;quot: &amp;quotInformation&amp;quot,
&amp;quotMicrosoft.AspNetCore&amp;quot: &amp;quotWarning&amp;quot
}
},
&amp;quotConnectionStrings&amp;quot: {
&amp;quotSellerConnectionString&amp;quot: &amp;quotServer=.;Database=Seller;User Id=sa;Password=123456;&amp;quot
},
&amp;quotAllowedHosts&amp;quot: &amp;quot*&amp;quot
}در اینجا رشته اتصال به دیتابیس لوکال متصل است و برای اتصال از یوزر sa با پسورد 123456 استفاده میکند. شما میتوانید مطابق پایگاه داده مد نظر خود این رشته را تغییر دهید. همچنین مشخص شده است که نام پایگاه داده هدف ما Seller خواهد بود(یعنی مایگریشن یک پایگاه داده به این نام را به صورت خودکار برای ما خواهد ساخت.)سپس در کلاس Program پیکربندی Context را مطابق قطعه کد زیر انجام میدهیم.builder.Services.AddDbContext&lt;Context&gt;(options =&gt;
options.UseSqlServer(builder.Configuration.GetConnectionString(&amp;quotSellerConnectionString&amp;quot)));در کد فوق مشخص شده است که کلاس Context، باید به پایگاه داده مربوط به رشته اتصالی که در AppSetting با عنوان SellerConnectionString مشخص شده است متصل شود.7) در حال حاضر پایگاه داده، جداول و هر آنچه که برای ایجاد پایگاه داده نمونه خود لازم داشتیم، مشخص شده است. هم اکنون نوبت به انجام عملیات مایگریشن میرسد.(برای مایگریشن حتما فریم ورک های ابتدای مقاله را نصب کنید.)مراحل مایگریشن1) ابتدا پنجره PackageManagerConsole را جهت نوشتن کامندهای مربوط به ماگریشن به در ویژوال استدیو باز کنید.(معمولا به صورت دیفالت قابل مشاهده است.)میتوانید از طریق مسیر زیر، پنجره کنسول را اضافه کنید.View/Other Windows/Package Manager Console2) ماگریشن اولیه را از طریق کامند زیر ایجاد کنید.add-migration initial_migبا اجرای کامند فوق، به طور خودکار پوشه ای بسیار مهم به نام Migrations ایجاد میشود که از این پس تمامی ماگریشن های شما در طول توسعه در این فولدر اضافه میشوند. بنابراین یک کلاس هم نام با عنوان مایگریشن در این فولدر ایجاد میشود که در آن بر اساس انیتی ها و Context، کدهایی جهت ایجاد دیتابیس در sql server ایجاد میشود. کلاسهای مایگریشن را به هیچ وجه حذف نکنید. (علت را در انتهای مقاله بیان میکنیم.)توجه داشته باشید که هر ماگریشن یک عنوان دلخواه خواهد داشت. به طور مثال در کامند فوق، نام ماگریشن را initial-migگذاشته ایم. معمولا در طول توسعه پروژه، بار ها و بارها از کامند add-migration استفاده خواهید کرد. عنوانی که برای مایگریشن در نظر میگیرید، باید حتما یکتا باشد و نباید نام تکراری استفاده کنید.3) همه چیز برای ایجاد پایگاه داده آماده است. بنابراین با کامند زیر گام نهایی را برداشته و پایگاه داده ساخته میشود.update-database4) اکنون اگر با نرم افزار ssms، پایگاه داده های روی سرور را مشاهده کنید، خواهید دید که یک پایگاه داده به نام Seller ایجاد شده است و در آن تمامی جداول مد نظر ما با ویژگی ها و روابط مشخص شده ایجاد شده است.5) پایگاه داده ایجاد شده و برای ادامه مراحل توسعه پروژه آماده است.6) از این پس قطعا شما نیاز خواهید داشت تا اصلاحاتی را در دیتابیس ایجاد کنید. به طور مثال فیلدی به یک انتیتی اضافه کنید و یا دیتاتایپ یک فیلد را تغییر دهید و یا حتی جداول جدیدی بسازید. تغییرات زیادی از این قبیل مورد نیاز خواهد بود که پس از ایجاد اولیه پایگاه داده اتفاق می افتد. در این مواقع نیز شما همانند موارد فوق عمل میکنید. ابتدا کامند add-migration را اجرا کنید و سپس کامند update-database را جهت اعمال اصلاحات در پایگاه داده اجرا کنید.(این کامندها هم برای ایجاد در اولین مرتبه و هم برای اعمال اصلاحات استفاده میشوند و به صورت هوشمند تغییرات در انتیتی ها و دیتابیس ها را میشناسند.)ملاحظات و نکات· ملاک شناسنایی تغییرات در هر بار اجرای کامند add-migration، کلاسهایی است که در اجرای کامندهای قبلی در فولدر Migrations ایجاد شده است، بنابراین حذف کردن یک کلاس از این فولدر میتواند مشکلات زیادی ایجاد کند.· در موارد خاصی که ماگریشن یک تغییر خاص را به درستی هندل نمیکند، میتوانید در کلاس ایجاد شده در فولدر Migrations، تغییر مورد نظر را یافته و اصلاحات جزئی انجام دهید. اما این کار مستلزم داشتن تجربه کافی در توسعه Code First است و باید با احتیاط عمل کرد.· در صورتی که یک ماگریشن اشتباه ایجاد کردید، میتوانید کلاس ماگریشن ایجاد شده را قبل از اجرای کوئری update-database حذف کنید و مجددا ماگریشن صحیح را ایجاد کنید. اما بعد از اجرای کوئری update-database و اعمال تغییرات در پایگاه داده از حذف مایگریشن خودداری کنید.· در مواردی که شما قصد دارید تا با معماری مشخصی به پیاده سازی کد بپردازید، ممکن است لایه ای که شامل کلاس Context است، با لایه اپلیکیشن (لایه ای که AppSetting و کلاس program یا startup در آن است) متفاوت باشد. لذا در این گونه موارد، لایه مربوط به اپلیکیشن را از طریق Solution Exploarer به عنوان پروژه دیفالت جهت اجرا مشخص کنید. و در پنجره کنسول، پروژه شامل Context را به عنوان دیفالت انتخاب کنید.در این مقاله به ایجاد یک پایگاه داده به صورت CodeFirst پرداختیم. قطعا این تمامی مطالب مربوط به CodeFirst نیست و موارد بسیاری وجود دارد که با کسب تجربه در آنها به مهارت خواهید رسید.سورس کد پروژه در گیت هاب(کلیک کنید)مقاله بعدی : پیاده سازی الگوی GenericRepository جهت ارتباط با پایگاه دادهشما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-3111برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Tue, 01 Mar 2022 15:48:27 +0330</pubDate>
            </item>
                    <item>
                <title>تجربیاتی در استفاده از پایگاه داده های رابطه ای</title>
                <link>https://virgool.io/@mrabiee1996/%D8%AA%D8%AC%D8%B1%D8%A8%DB%8C%D8%A7%D8%AA%DB%8C-%D8%AF%D8%B1-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%D9%BE%D8%A7%DB%8C%DA%AF%D8%A7%D9%87-%D8%AF%D8%A7%D8%AF%D9%87-%D9%87%D8%A7%DB%8C-%D8%B1%D8%A7%D8%A8%D8%B7%D9%87-%D8%A7%DB%8C-zsv8w6mp7zco</link>
                <description>تجربیاتی در استفاده از پایگاه داده های رابطه ایشاید شما هم مطالب زیادی در مورد پایگاه داده ها و مزایا و معایب هر یک شنیده باشید. با وجود رشد روزافزون پایگاه داده های غیر رابطه‌ای، هنوز هم استفاده از RDBMS ها، سهم عمده ای از نرم افزارهای توسعه یافته و یا در حال توسعه رو در اختیار داره. در این مقاله قصد دارم تا تجربیاتم از کار با پایگاه داده‌ها(به خصوص RDBMS ها) رو با شما عزیزان به اشتراک بگذارم. این تجربیات در عین اختصار، میتونه معجزه گر باشه و شما رو از گلوگاه های خطرناک در توسعه و پشتیبانی نرم افزار نجات بده. پس با دقت و تفکر ویژه ای به مطالعه بپردازید.1) از پایگاه داده ها انتظار معجزه نداشته باشید.با وجود قدرت بسیار زیاد پایگاه داده ها و پیشرفت های چشم گیری که در سالهای اخیر داشته اند، هنوز باید در استفاده و طراحی دیتابیس، نهایت دقت و ریزبینی را به کار بگیرید. پایگاه داده، در نهایت قدرت، معجزه نخواهد کرد بنابراین با تکیه به قدرت پایگاه داده، جانب احتیاط را کنار نگذارید.2) تمام انواع پایگاه داده کاربردی هستند، از تعصب دوری کنید.شاید در طول سالهای کاری خود، با نگاه های متعصبانه ای نسبت به پایگاه داده ها روبرو شوید. هر پایگاه داده در صورت استفاده در جایگاه مناسب خود، میتواند بهترین کارایی را داشته باشد.3) پرفورمنس در زمان تست را با زمان استفاده عملیاتی اشتباه نگیرید.در موارد بسیاری، افراد با توجه به اینکه در زمان تست حجم داده های کمی در دیتابیس قرار دارد، متوجه ناکارآمد بودن کوئری ها و طراحی ها نخواهند شد و در زمان استفاده عملیات و انتشار عمومی محصول، با مشکلات زیادی مواجه میشوند. در هر زمان باید تمام تلاش خود را برای رسیدن به بهترین پرفورمنس به کار گیرید.4) از هارد SSD استفاده کنید.با توجه به اینکه ماهیت پایگاه داده، ذخیره داده روی حافظه های دائمی است، استفاده از هاردهای پرسرعت تاثیر معجزه آسایی در افزایش سرعت پایگاه داده در کلیه عملیات دارد.5) در خواندن داده ها از پایگاه داده، برای واکشی لیست داده ها از Lazy Load استفاده کنید.6) کوئری های بهینه(optimized) بنویسید.کوئری های طراحی شده توسط شما، باید دقیقا خواسته مسئله را ارائه کنند نه فراتر از آن. معمولا در تب و تاب رسیدن به خواسته مسئله، رعایت بهینه بودن کوئری به فراموشی سپرده میشود.گاهی برای رسیدن به یک پاسخ، چندین کوئری و روش مختلف قابل استفاده است. سعی کنید تا کم هزینه ترین کوئری را انتخاب کنید.مثال:· مثال: عدم محدود کردن تعداد داده های خروجی برای یافتن یک رکورد خاص.Wrong: Select * from User where UserName =&#039;...&#039;
Correct:  Select top(1) * from User where UserName=&#039;...&#039;در این مثال، با توجه به Unique بودن Username، خروجی دو کوئری مشابه خواهد بود، اما کوئری غلط نسبت به کوئری صحیح هزینه چندین برابری خواهد داشت.· مثال: محدود نکردن داده ها در کوئری های پیچیده ترWrong: select * from Products inner join Categories on Products.CategoryId=Categories.Id order by Products.Id
OFFSET 10 rows FETCH NEXT 10 ROWS ONLY
Correct:  select * from (
select * from Products order by Products.Id
OFFSET 10 rows fetch next 10 rows ONLY) TempProducts
inner join Categories on TempProducts.CategoryId=Categories.Idدر کوئری های فوق قصد داریم اطلاعات تعدادی از کالا ها را به صورت Lazy Load(ده رکورد بعد از دهمین رکورد) در کنار اطلاعات دسته بندی آنها قرار دهیم. دو روش غلط و صحیح ارائه شده خروجی مشابهی خواهند داشت، اما مورد صحیح به مراتب هزینه کمتری ایجاد خواهد کرد.· مثال: گاهی برای کار با پایگاه داده از ORM ها استفاده میکنیم. بسیاری از افراد به جای استخراج داده‌های هدف از پایگاه داده، تعداد بسیار زیادی از رکوردها را به حافظه Ram واکشی میکنند و سپس، از این حجم داده ها تعداد بسیار کمی که هدف اصلی عملیات است را انتخاب میکنند. با توجه به اینکه ORM ها جهت سهولت کدنویسی، شما را با بسیاری از ملاحظات درگیر نمیکنند و در مراحل تست اولیه، بار سنگین این نوع خروجی ها احساس نمیشود، معمولا چنین اشتباهاتی رخ میدهد.اشتباهات رایج بیشماری وجود دارد که با کمی تفکر و دقت میتوان به کوئری دقیق و صحیح دست یافت.7) مفهوم Lock دیتا در پایگاه داده را نادیده نگیرید.زمانی که یک کوئری اجرا میشود، به طور معمول تا مشخص نشدن نتیجه آن، داده های مرتبط با خروجی کوئری لاک(Lock) میشوند. در این زمان، سایر کوئری های مرتبط با لاک، در انتظار اتمام آن باقی میمانند و سپس اجرا شده و خود باعث لاک جدیدی میشوند. اگر چه در صورت طراحی صحیح پایگاه داده و کوئری ها، زمان لاک بسیار کم خواهد بود؛ اما در صورت زیاد شدن درخواست ها به پایگاه داده و بروز موارد، ممکن است پایگاه داده در نتیجه بسیاری از درخواست ها با کندی بسیار زیاد، Block ها  و Deadlock ها مواجه شود. این اتفاق زمانی که تعداد رکوردها در تعدادی از جداول بسیار زیاد است و روابط زیادی برای پایگاه داده در نظر گرفته شده است بیشتر به وقوع میپیوندد.(به زبان ساده در جدولی که تنها 10 رکورد دارد، معمولا Lock چشم گیری نداریم؛ اما در جدولی که تعداد داده ها به چند میلیون میرسید خطر بیشتری وجود دارد.)بنابراین به دلایل ذکر شده، حتی المقدور در کوئری هایی که مطمئنا نیازی به لاک شدن داده ها ندارند، از no lock استفاده کنیم تا از لاک بیهوده جلوگیری شود.8) در استفاده از Transaction احتیاط کنید.با توجه به اینکه Transaction ها از خاصیت ACID برخوردارند، در زمان اجرای یک Transaction جداول مرتبط با آن Lock میشود. با توجه به ذات Transaction ها و منطق استفاده از آنها، ممکن است تعداد زیادی از جداول را با خود درگیر و در واقع Lock کند. در صورت زیاد شدن تعداد لاک ها و زمانبر بودن فرآیند یک Transaction، بروز Block و Deadlock ها و کندی بسیار زیاد دور از انتظار نیست.9) روابط را منطقا حفظ کنید.بسیاری از پایگاه داده های رابطه ای این امکان را به شما میدهند تا روابط میان جداول را به آنها معرفی کنید و سپس در زمان اینزرت، اپدیت یا حذف داده ها، به صورت خودکار بر اساس این روابط Checking هایی برای جلوگیری از تناقض، به عملیات اضافه میکنند. در صورت بالا بودن حجم داده ها، این چکینگ ها میتواند پرفورمنس را با کاهش چشم گیر و خطرناکی مواجه کند. بنابراین بهتر است در فرآیندهای نرم افزار خود روابط را به دقت در نظر بگیرید(تا منطقا تناقضی اتفاق نیفتد) و پایگاه داده را از این بررسی های پر هزینه رها سازید.10) در استفاده از کوئری های پرهزینه احتیاط کنید.کوئری هایی همچون Union، Intersect، Except، Join، GroupBy، Distinct، In،  Not Inمعمولا هزینه زیادی در اجرا خواهند داشت. از استفاده بی رویه این کوئری ها خودداری کنید.11) در ایندکس گذاری تعادل را رعایت کنید.ایندکس گذاری موجب ایجاد الگوریتم هایی در پس زمینه عملیات پایگاه داده میشوند که معمولا در خواندن و واکشی اطلاعات باعث افزایش چشم گیر سرعت خواهند بود و در عین حال به دلیل اجرای همین الگوریتم ها، در زمان ایجاد یا ویرایش داده ها باعث کندی محسوسی میشوند.معمولا در ایندکس گذاری اشتباهات زیر رخ میدهد.· عدم استفاده از ایندکس: معمولا جداول بر حسب استفاده و حجم داده های خود، نیازمند ایندکس گذاری مناسب هستند. عدم استفاده از ایندکس ها موجب کندی در خواندن اطلاعات میشود.· عدم ایندکس گذاری دقیق: گاها عدم شناخت صحیح نسبت به کوئری ها موجب ایندکس گذاری هایی میشود که صرفا کندی زیاد در زمان آپدیت یا اینزرت را به همراه دارند و در عین حال تاثیری در سرعت واکشی اطلاعات ندارند.· ایندکس گذاری بیش از حد: گاها استفاده بی رویه در ایندکس گذاری، کندی بسیار زیادی در عملیات اینزرت و آپدیت به همراه دارد، اگر چه ممکن است سرعت واکشی اطلاعات را بسیار بالا ببرد.در مجموع با توجه به موارد گفته شده، بر حسب استفاده و اهمیت جداول، ایندکس گذاری صحیح و دقیقی انجام دهید.12) تنظیمات FileGroup را انجام دهید.وقتی که یک دیتابیس ایجاد میکنید، دو فایل جهت نگهداری داده های پایگاه داده با پسوندهای MDF و LDF ایجاد میشود  که به ترتیب داده ها و اطلاعات لاگ در این دو فایل ذخیره میشود. شما میتوانید با استفاده از FileGroup ها پایگاه داده را به گونه ای پیکربندی کنید که داده ها در چند فایل در مکان های مختلفی از HardDisk ذخیره شود. به طور مثال میتوانید مشخص کنید که داده های هر جدول در کدام FileGroup قرار گیرد. این عملیات میتواند تاثیر بسیار زیادی در Performance داشته باشد.13) به ORM ها به هیچ وجه اعتماد نکنید(بسیار مهم).در تمامی سیستم های نرم افزاری، نقاطی وجود دارد که حساسیت بسیار بالایی در اجرای صحیح کوئری ها وجود دارد. به طور مثال عملیات رزرو و کنترل تعداد محصولات در انبار را در نظر بگیرید. در صورت عدم کنترل دقیق تعداد و موجودی کالاها، امکان برور فاجعه وجود خواهد داشت. در مواردی که دارای حساسیت های این چنینی هستند، به جای ORM، از Procedure ها استفاده کنید.شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-3110برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Thu, 24 Feb 2022 18:46:33 +0330</pubDate>
            </item>
                    <item>
                <title>پروتکل HTTP چیست؟</title>
                <link>https://virgool.io/@mrabiee1996/%D9%BE%D8%B1%D9%88%D8%AA%DA%A9%D9%84-http-%DA%86%DB%8C%D8%B3%D8%AA-f6xrtn2pnz5i</link>
                <description>با صرف نظر از توضیحات پروتکل http در شبکه، به نحوه عملکرد این پروتکل میپردازیم. پروتکل http روشی برای برقراری ارتباط و تبادل اطلاعات میان دو ماشین در شبکه با استفاده از ip است؛ چرا که تمامی ماشین‌های موجود در شبکه (محلی، اینترنت یا اینترانت و ...) دارای آدرس ip بوده و در واقع ip را میتوان آدرس ماشین در شبکه در نظر گرفت. این پروتکل مبتنی بر ریکوئست است، به این صورت که مبدا در ابتدا یک درخواست (request) برای مقصد ارسال نموده و سپس مقصد یک پاسخ(response) به مبدا ارسال میکند و سپس ارتباط قطع میشود. همانطور که مشخص است ارتباط میان مبدا و مقصد دائمی نیست و در نهایت با دریافت ریسپانس تکمیل شده و پایان می یابد.نکته قابل توجه آن است که وب‌سرویس‌های RESTful از پروتکل http جهت ارتباط در شبکه استفاده میکنند، از این رو تمامی سایت‌های اینترنتی مبتنی بر پروتکل http هستند. به زبان ساده‌تر تصور کنید در یک صفحه اینترنتی با ورود به صفحه یک متن یا تصویر نمایش داده میشود. در واقع در این زمان با ورود به صفحه یک request از دستگاه شما که دارای ip مشخصی است به سرور مقصد که آن هم دارای ip است ارسال میشود. در صورت عدم وجود مشکل در شبکه و دستگاه‌ها، سرور همان متن قابل مشاهده یا تصویر در صفحه را در response به دستگاه شما بازگردانده و این متن توسط اپلیکیشن(مرورگر یا سایر نرم افزار های مفسر) به تصاویر و سایر عناصر صفحه تبدیل میشود و روی دستگاه شما به نمایش گذاشته میشود.نکته قابل توجه آن است که این پروتکل برای ارسال و دریافت داده ها از متون استفاده میکند. حتی داده هایی مانند عکس یا ویدئو نیز در نهایت به لیستی از بایت ها تبدیل میشوند و میتوانند به صورت متن به دستگاه دیگر ارسال شده و سپس مجددا این بایت ها به فایل اصلی تبدیل شوند. بنابراین فایل ها نیز در صورت کم حجم بودن از طریق این پروتکل قابل ارسال هستند.پس از فراخوانی یک وب سرویس از مبدا، ممکن است حالات مختلفی به وقوع بپیوندد. در حالت عادی با ارسال درخواست توسط مبدا، پاسخ مناسب در مقصد دریافت میشود؛ اما این تمام ماجرا نیست.ممکن است ارتباط شبکه برقرار نشود.ممکن است مقصد در اجرای عملیات خود دچار خطا شود.ممکن است آدرس وب سرویس در مبدا اشتباه تنظیم شده باشد و هیچ گاه درخواست به مقصد نرسد.ممکن است مبدا اجازه دسترسی به سرویس در مقصد را نداشته باشد و با خطای عدم دسترسی یا عدم احراز هویت مواجه شود.حالات متفاوت دیگری وجود دارد که ممکن است به وقوع بپیوندد. برای مشخص شدن هر یک از مشکلات فوق در یک ریکوئست، کد وضعیتی به مبدا ارسال میشود که بر اساس آن میتوان تشخیص داد که عملیات ارسال و دریافت بدون نقص انجام شده است یا خطایی روی داده و در صورت وقوع خطا، نوع آن را میتوان با این کد وضعیت تشخیص داد.کد های وضعیت در پروتکل HTTPNot Found Error (404)زمانی که آدرس مقصد request به دلایل مختلف توسط مبدا قابل دسترسی نباشد.Internal Server Error (500)زمانی که در مقصد یک request خطای مدیریت نشده ای به وقوع بپیوندد و عملیات ناموفق شود.Success (200)زمانی که پس از ارسال repuest عملیات در مقصد با موفقیت انجام شود و response به مبدا ارسال شود.Unauthorized (401)زمانی که ارسال کننده request از نظر مقصد یک متقاضی غیرمجاز باشد.Bad Request (400)زمانی که در ارسال requestداده های ارسالی صحیح نبوده و برای مقصد غیرقابل فهم باشد.شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-34برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Sun, 20 Feb 2022 23:16:31 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با پروتکل https و نسخه های TLS؟</title>
                <link>https://virgool.io/@mrabiee1996/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D9%BE%D8%B1%D9%88%D8%AA%DA%A9%D9%84-https-%D9%88-%D9%86%D8%B3%D8%AE%D9%87-%D9%87%D8%A7%DB%8C-tls-n3skrav1bz5e</link>
                <description>همانطور که در مقاله آشنایی با پروتکل HTTP، توضیحاتی در مورد این پروتکل ارائه شد، در یک سناریوی عادی و نمونه ابتدا کلاینت یک درخواست به سرور ارسال میکند و سپس متناسب درخواست ارسالی، پاسخی به کلاینت بازگردانده میشود. در این سناریو هیچ گونه رمزنگاری (Encryption) خاصی بر روی داده ها رخ نمیدهد و صرفا داده ها به شکل قابل انتقال در پروتکل HTTP کدگذاری میشود(Encoding) و سپس تبادل رخ میدهد. اما در این سناریو از امنیت اطلاعات خبری نیست!!! در صورتی که داده های انتقالی به هر طریقی در مسیر انتقال در اختیار افراد غیرمجاز قرار بگیرد، به راحتی میتوانند عملیات Decoding را انجام داده و به اطلاعات دسترسی کامل بیابند.اما چگونه میتوان امنیت درخواست ها را افزایش داد؟اگر چه میتوان در سطح اپلیکیشن، برنامه نویسان داده های حساس را جهت ارسال، با الگوریتم های مختلفی رمزنگاری کنند؛ اما فرآیند رمزنگاری داده ها هزینه عملیاتی و پیاده سازی سنگینی را بر پروژه تحمیل میکند و در اکثر موارد مقرون به صرفه نیست. بنابراین ایده قوی تر، راه اندازی یک پروتکل امنیتی خارج از اپلیکیشن است. یعنی استفاده از پروتکل HTTPS برای انتقال ریکوئست ها بر بستر HTTPS نیاز به تهیه گواهی SSL از سازمانهای ارائه دهنده این گواهی که جهانی هستند وجود دارد. در مقالات بعدی که شیوه عملیاتی انتقال از HTTP به HTTPS را آموزش میدهیم، به نحوه تهیه گواهی SSL خواهیم پرداخت.HTTPS چگونه کار میکند؟بر اساس نسخه TLS یا SSL استفاده شده در انتقال داده میان طرفین، روش ها کمی متفاوت خواهد بود. به طور کلی در استفاده از پروتکل HTTPS قبل از آنکه داده های اصلی تبادل شوند، تعدادی کنش و واکنش که از آنها به عنوان HandShake یاد میشود میان سرور و کلاینت رخ میدهد. در واقع ابتدا در فرآیند Handshake؛ سرور و کلاینت بر سر کلید قابل استفاده جهت رمزنگاری داده ها، اصالت سنجی گواهی SSL و سایر موارد به توافقاتی با یکدیگر میرسند و پس از اینکه Handshake با موفقیت به پایان رسید و کلید مشترک در طول این فرآیند مشخص شد، تمامی داده های دریافتی و خروجی از طریق نرم افزار بر اساس این کلید مشترک رمزنگاری و رمزگشایی میشوند. شخص توسعه دهنده نرم افزار در این فرآیند دخالتی ندارد و صرفا انتقال اپلیکیشن بر بستر HTTPS، این پروتکل را در تمامی ریکوئست ها به صورت خود به خود اعمال میکند. در واقعا تمامی عملیات مذکور، در وبسایت ها توسط مرورگر و در نرم افزارها(خواه سمت سرور و خواه سمت کاربر، همانند اپلیکیشن های تلفن هوشمند) به واسطه فریم ورک های توسعه یافته در زبان برنامه نویسی، بدون دخالتی از جانب برنامه نویس اتفاق می‌افتد. اگر قصد دارید با فرآیند دقیق این عملیات آشنا شوید، میتوانید متن زیر را مطالعه نمایید. (توجه: در پروتکل HTTPS از الگوریتم های SSL یا TLS استفاده میشود. با توجه به جدیدتر بودن TLS و اینکه الگوریتم SSL قدیمی و ضعیف تر از TLS است،صرفا به توضیح TLS میپردازیم.)نحوه HandShake در TLS نسخه 1.2 و نسخه های قبل ترکلاینت ابتدا یک پیام (Hello) به سرور ارسال میکند و در پیام خود لیستی از گزینه های امنیتی که میتواند پشتیبانی کند را جهت انتخاب به سرور میفرستد.سرور پس از دریافت پیام از جانب کلاینت، اطلاعات گواهی SSL خود را به همراه یک کلید عمومی Public Key)) به کلاینت میفرستد.کلاینت اطلاعات گواهی SSL را بررسی نموده و در صورت تایید اصالت آن، یک کلید مشترک (Shared Key) را با استفاده از کلید عمومی که از سرور دریافت کرده به صورت رمزگذاری شده به سرور میفرستد.سرور پیام کلاینت را دریافت میکند و این به معنی آمادگی کلاینت برای ارسال داده هاست. بنابراین با کلید خصوصی خود کلید مشترک را رمزگشایی میکند و در نهایت یک پیام موفقیت به کلاینت میفرستد.همانطور که مشخص است با عملیات فوق هر دو طرف یک کلید مشترک دارند و با استفاده از یک روش رمزنگاری متقارن، عملیات رمزگذاری روی داده های درخواست و پاسخ درخواست را انجام میدهند و از این طریق حتی در صورت دسترسی غیر مجاز به داده های انتقالی، امکان رمزگشایی آنها وجود ندارد. البته کلید مشترک از اهمیت ویژه ای برخوردار است و نباید به هیچ وجه آشکار شود. برای این منظور خود کلید مشترک توسط الگوریتم دیگری و با استفاده از کلید عمومی، یک بار در مرحله دوم از مراحل فوق توسط کلاینت رمزگذاری شد. برای هر بار که ریکوئستی ارسال میشود، یک دور تمام این مراحل باید انجام شود!!! طبیعتا سربار قابل توجهی خواهد داشت و کندی ملموسی نسبت به نسخه بدون Https ایجاد میشود.نحوه HandShake در TLS1.3در این نسخه تفاوت چشم گیر و قابل توجهی نسبت به نسخه قبل تر وجود دارد. فرآیند HandShake که شامل 4 مرحله فوق بود در دو مرحله خلاصه تر میشود. همچنین الگوریتم های ناایمن رمزنگاری که در نسخه های قبل وجود داشت حذف شده و الگوریتم های قوی تر و به روزتری جایگزین شده اند. مراحل Handshake در این نسخه به صورت ذیل است:کلاینت با آگاهی قبلی از این که سرور چه الگوریتمی را انتخاب خواهد کرد، یک پیام(Hello) همراه با تعدادی از گزینه های امنیتی و کلید مشترک به سرور میفرستد.سرور اطلاعات را دریافت نموده و مطابق آگاهی قبلی کلاینت، یک گزینه را انتخاب میکند و اطلاعات SSL را به همراه پیام موفقیت به کلاینت میفرستد و HandShake با موفقیت به پایان میرسد.شاید برای شما سوال باشد که چرا در TLS1.2 این اتفاق نیفتاد؟ یک نکته قابل توجه این است که در TLS1.3 از قبل کلاینت از انتخابی که سرور خواهد کرد اطلاع دارد. همچنین کلید مشترک در همان اولین گام ارسال میشود. همین دو موضوع باعث کم شدن گام ها خواهد شد.نکته مبهم دیگر این است که چرا در نسخه 1.2 در همان گام اول کلید مشترک ارسال نمیشد؟باید بگوییم از آنجا که TLS1.2 قدیمی تر است، روشی برای جلوگیری از لو رفتن کلید مشترک در آن بدون وجود کلید عمومی که سرور ان را مشخص میکند و رمزنگاری کلید مشترک با استفاده از کلید عمومی وجود ندارد. اما در TLS1.3 با پیشرفتی که در زمینه رمزنگاری رخ داده است، میتوان بدون نگرانی از لو رفتن کلید مشترک، در همان مرحله ابتدایی آن را ارسال نمود و با استفاده از الگوریتم های ریاضی و ویژه تری این امنیت را تضمین نمود.چرا تمامی سازمانهای مرتبط با امنیت اطلاعات و در راس آنها گوکل، به سمت حذف HTTP پیش میروند؟همانطور که از توضیحات بالا مشخص است، بدون HTTPS امنیت اطلاعات کاربران در خطر بزرگی قرار میگیرد. لذا امروزه بیش از پیش این موضوع مورد توجه قرار گرفته و نرم افزارهایی که از HTTPS استفاده میکنند از ارزش بالاتری برخوردار هستند. در مقالات بعدی شما را با نحوه انتقال وبسایت از HTTP به HTTPS و تهیه گواهی SSL آشنا خواهیم کرد.شما میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-39برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Sun, 20 Feb 2022 23:09:46 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با محبوب‌ترین الگوریتم‌های Hashing</title>
                <link>https://virgool.io/@mrabiee1996/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D9%85%D8%AD%D8%A8%D9%88%D8%A8-%D8%AA%D8%B1%DB%8C%D9%86-%D8%A7%D9%84%DA%AF%D9%88%D8%B1%DB%8C%D8%AA%D9%85-%D9%87%D8%A7%DB%8C-hashing-v5nioad0lley</link>
                <description>در مقاله ی گذشته که درباره ی انواع روش های مختلف رمزنگاری اطلاعات صحبت کردیم با الگوریتم های برگشت ناپذیر آشنا شدیم وآموختیم که داده های ما اصطلاً Hash میشوند و به هیچ عنوان قبل بازگشت به متن اصلی نیستند.از جمله الگوریتم های Hashing که در رمزنگاری از آنها استفاده میشود میتوان به عناوین زیر اشاره نمود که در این مقاله به بررسی آنها میپردازیم.✓ SHA1 ✓ SHA256✓ MD5  الگوریتم SHA یکی از الگوریتم های Hashing است. SHA دارای انواع مختلف از قبیل SHA1 و SHA256 است.SHA1اثبات شده است که الگوریتم SHA1 به ازای رشته های ورودی های متفاوت ممکن است خروجی مشابهی داشته باشد. همانطور که گفته شد الگوریتم های Hashing رشته هایی برگشت ناپذیر ایجاد میکنند و صرفا قابل تطبیق با رشته اصلی هستند؛ اگر یک الگوریتم از دو رشته ورودی مختلف Hash های مشابهی تولید کند آن گاه طبیعتا هر دو رشته  اصلی با Hash مطابق خواهد بود و قابل تایید میباشد و این نقص میتواند خطراتی به همراه داشته باشد. از این رو این الگوریتم به پایان نقش خود در اکثر سیستم های اطلاعاتی رسیده است.الگوریتم SHA256یکی از پرکاربردترین و ایمن ترین الگوریتم های Hashing است. قطعه کد #C عملیات Hashing و Verify این الگوریتم در ذیل آورده شده است. https://gist.github.com/rabieedev1996/c71536e0462ca85ecd310c5a270a81de قطعه کد فوق با وجود استفاده از الگوریتم SHA256 از نهایت اطمینان برخوردار نیست. از این رو در اکثر موارد ابتدا داده اصلی را Hash و سپس آن را با استفاده از الگوریتم RSA، و کلید خصوصی Sign میکنند تا در هنگام تبادل اطلاعات و یا دسترسی افراد غیر مجاز از امنیت بالاتری برخوردار باشد. پس از توضیحات الگوریتم RSA در مقاله ی بعد به این مورد باز خواهیم گشت.الگوریتم MD5این الگوریتم نیز یکی دیگر از الگوریتم های Hashing است. از آنجایی که سابقه شکستن MD5 وجود دارد، استفاده از آن توصیه نمیشود و جزو الگوریتم های رو به منسوخ شدن است. قطعه کد سیشارپ این الگوریتم مشابه با SHA256 است و به جای کلاسهای مربوط به SHA از کلاسهای MD5 استفاده میشود.در این مقاله با الگوریتم هایی که با استفاده از عملیات Hashing اطلاعات ما را رمزنگاری می کنند آشنا شدیم. در مقاله بعد به معرفی الگوریتم هایی خواهیم پرداخت که با استفاده از روش های رمزنگاری متقارن و نامتقارن داده های ما را Encryption میکنند.در ادامه مباحث رمزنگاری میتوانید به مقالات ذیل مراجعه نمایید.بررسی محبوب ترین الگوریتم های رمزنگاری متقارن و نامتقارنهمچنین میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-97برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Sat, 19 Feb 2022 22:47:46 +0330</pubDate>
            </item>
                    <item>
                <title>بررسی محبوب ترین الگوریتم های رمزنگاری متقارن و نامتقارن</title>
                <link>https://virgool.io/Solidity/%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C-%D9%85%D8%AD%D8%A8%D9%88%D8%A8-%D8%AA%D8%B1%DB%8C%D9%86-%D8%A7%D9%84%DA%AF%D9%88%D8%B1%DB%8C%D8%AA%D9%85-%D9%87%D8%A7%DB%8C-%D9%85%D8%AA%D9%82%D8%A7%D8%B1%D9%86-%D9%88-%D9%86%D8%A7%D9%85%D8%AA%D9%82%D8%A7%D8%B1%D9%86-vasot8gemrhf</link>
                <description>در مقاله ی روش های مختلف رمزنگاری، با الگوریتم های متقارن و نامتقارن آشنا شدیم و به بررسی تفاوت های آن ها پرداختیم، در این مقاله با الگوریتم های AES و RSA آشنا خواهیم شد و همچنین به قطعه کدهایی که با استفاده از آن ها میتوان اطلاعات خود را رمزگزاری (Encryption) و رمزگشایی (Decryption) کرد، خواهیم پرداخت.الگوریتم AESیکی از الگوریتم های رمزنگاری متقارن و پرکاربرد میباشد. زمانی که از رمزنگاری صحبت میکنیم به معنای ایجاد یک رشته معادل(ciphertext) قابل بازگشت است. در این الگوریتم یک کلید کاملا محرمانه در نظر گرفته میشود که در الگوریتم رمزنگاری از این کلید برای Encrypt و Decrypt داده ها استفاده میشود، یا به عبارت دیگر عبارت رمز شده فقط با این کلید قابل بازگشت خواهد بود؛ طبیعتا با لو رفتن این کلید، تمام ciphertext های تولید شده با الگوریتم AES را میتوان به رشته اصلی بازگرداند.  متدهای مربوط به Encrypt و Decrypt متن ورودی در زبان #C به صورت ذیل میباشد.                                                                                                                    Encrypt https://gist.github.com/rabieedev1996/159b2939f69cbd4699bb02c2be5c07ba                                                                                                                     Decrypt https://gist.github.com/rabieedev1996/570652f2603382edad867b0d434f6e09 در قطعه کدهای بالا دو متغیر با عنوان keyString و IVString وجود دارد. در واقع KeyString همان کلید محرمانه ای است که داده های رمزنگاری شده فقط با این کلید میتوانند به رشته اصلی بازگردانده شوند، لذا باید برای نگهداری محرمانه این کلید اهمیت بسیار زیادی قائل شد. در زبان سیشارپ میتوان این دو متغیر را از طریق قطعه کد زیر ایجاد نمود. قاعدتا یک بار نیاز به ایجاد کلید خواهید داشت و این قطعه کد تنها یک بار استفاده میشود، مگر زمانی که بخواهید کلید را تغییر دهید. https://gist.github.com/mrabiee1375/4214b4911bbf64b14ac1b4549bd36dca الگوریتم RSAکی از پرکاربردترین و ایمن ترین الگوریتم های رمزنگاری نامتقارن که در طیف گسترده ای از سامانه های نرم افزاری و در لایه های مختلف مورد استفاده قرار میگیرد. همانطور که در ابتدای مقاله گفته شد، در الگوریتم های نامتقارن از یک کلید برای Encrypt و از کلید دیگری برای Decrypt استفاده میشود که به این زوج کلید عمومی (public key) و کلید خصوصی (private key) گفته میشود. از الگوریتم RSA علاوه بر رمزگذاری، براس Sign کردن اطلاعات نیز استفاده میشود که به توضیح آن خواهیم پرداخت.کلید عمومی در عملیات رمزنگاری برای Encrypt داده ها و کلید خصوصی برای Decrypt استفاده میشود. لازم به ذکر است که این دو کلید به هم وابسته هستند و باید با هر دو با ابزارهای موجودی به صورت همزمان و مرتبط با هم تولید شوند.  برای درک بهتر به سناریویی که مطرح میکنیم توجه نمایید.فرض کنید شما و یک سازمان دیگر قصد دارید متونی را با یکدیگر تبادل کنید و نیاز است تا داده هایی که آن سازمان به شما ارسال میکنید کاملا رمز شده باشد. در این سناریو از الگوریتم رمزنگاری متقارن نباید استفاده نمود چرا که کلید میان شما و سازمان مقابل شما مشترک و مشابه است و اگر در هر یک از سازمان ها کلید در اختیار افراد غیرمجاز قرار گیرد، امنیت تبادل اطلاعات با خطرات جدی مواجه میشود. در مقابل زمانی که شما از الگوریتم نامتقارن استفاده میکنید، کلید خصوصی را در نهایت امنیت و محرمانگی سمت خودتان نگهداری میکنید و تنها کلید عمومی را در اختیار سازمان مقابل قرار میدهید. آن سازمان میتواند با استفاده از کلید عمومی که دریافت کرده است اطلاعات را کاملا رمزنگاری کند و پس از ارسال ، شما میتوانید با کلید خصوصی رمزگشایی را انجام دهید. طبیعتا کلید عمومی حتی اگر در اختیار افراد غیر مجاز قرار گیرد، هیچ گونه خطری تبادل اطلاعات را تهدید نخواهد کرد، چرا که تنها برای Encrypt داده ها قابل استفاده است؛ این در حالیست که کلید خصوصی را در نهایت امنیت، نزد خودتان نگهداری میکنید.متدهای  مربوط به Encrypt و Decrypt داده ها در الگوریتم Rsa در ذیل آورده شده است.Encrypt  https://gist.github.com/rabieedev1996/196a92c50ffa7342ec32b55fa0d3d5e5 Decrypt https://gist.github.com/rabieedev1996/51c3a2a0f66d724bcc12b4ebca6a9dfa در الگوریتم فوق طول کلید ها 2048 بایت است. طول کلید را میتوان مقادیر مختلفی در نظر گرفت. عملیات Encrypt و Decrypt در RSA میتواند باعث ایجاد سربار و کندی محسوسی شود، بنابراین باید در جای صحیح و درست مورد استفاده قرار گیرد. هر چه طول کلید بیشتر باشد امنیت بالاتر و در عین حال سربار بیشتر است.همانطور که گفتیم از RSA برای sign کردن داده ها نیز استفاده میشود. وقتی داده ای را sign میکنیم، عملیاتی مشابه با Hashing صورت میگیرد و غیر قابل بازگشت است؛ با این تفاوت که حتی برای تطبیق نیاز به کلید است و از همین طریق امنیت افزایش میابد. بنابراین حتی اگر رشته sign شده در اختیار افراد غیرمجاز قرار گیرد، در صورت نداشتن کلید sign نمیتوانند تطبیق را انجام دهند.از این روش برای تبادل داده هش میان دو سامانه  و برای افزایش امنیت استفاده میشود. به عبارت دیگر ابتدا رشته اصلی هش و سپس داده هش شده sign و سپس داده sign شده به سامانه دیگر ارسال میشود. در عملیات Sign کردن داده ها از الگوریتم RSA با همان کلیدهای خصوصی و عمومی استفاده میشود. از کلید خصوصی برای Sign کردن داده و از کلید عمومی برای تطبیق استفاده میشود.Sign https://gist.github.com/rabieedev1996/a9b08e1f36bd3db83ac8e706e79b002b Verify https://gist.github.com/rabieedev1996/e6e1783a6a19b0ded358c79e053cbdf7 همانطور که از قطعه کد فوق قابل تشخیص است برای Sign  از RSA و برای هشینگ از SHA256 استفاده شده است.به طور کلی در این مقاله سعی ما بر آن بود که شما را با الگوریتم های پرکاربرد و نام آشنایی در عرصه توسعه نرم افزار آشنا کنیم و نگاه وسیعی در این زمینه برای شما ایجاد کنیم. دنیای نرم افزار و امنیت پیوسته در حال پیشرفت است و الگوریتم های جدید تری با هدف افزایش امنیت و بهینه سازی در حال توسعه میباشد، لذا این تمام ماجرا نیست و ظهور الگوریتم های جدید با قابلیت های بهتر دور از انتظار نخواهد بود.در ادامه مباحث رمزنگاری میتوانید به مقالات ذیل مراجعه نمایید.آشنایی با الگوریتم های Hashingهمچنین میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-101برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996</description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Sat, 19 Feb 2022 21:41:52 +0330</pubDate>
            </item>
                    <item>
                <title>انواع روش های مختلف رمزنگاری</title>
                <link>https://virgool.io/@mrabiee1996/%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%D8%B1%D9%88%D8%B4-%D9%87%D8%A7%DB%8C-%D9%85%D8%AE%D8%AA%D9%84%D9%81-%D8%B1%D9%85%D8%B2%D9%86%DA%AF%D8%A7%D8%B1%DB%8C-y46rvriipe60</link>
                <description> آشنایی با الگوریتم های رمزنگاری(Encryption) داده هادر هر سامانه نرم افزاری داده هایی وجود دارد که نگهداری از آنها مستلزم رعایت اصول امنیتی مختلفی است. فرض کنید در یک سامانه نرم افزاری قصد دارید رمز عبور کاربران خود را نگهداری کنید. همانطور که مشخص است رمز عبور یکی از قسمت های با اهمیت است که قطعا در صورت عدم نگهداری ایمن از آن، میتواند به سادگی در اختیار افراد غیرمجاز قرار گیرد و امنیت کاربران به خطر بیفتد. داده ها و اطلاعات مختلفی وجود دارد که اهمیت بالایی دارند و برای نگهداری آنها باید نهایت تدابیر امنیتی را اندیشید. با توجه به این موضوع رمزنگاری داده ها از اهمیت بالایی برخوردار میشود. در این مقاله به بررسی مطالبی پیرامون این موضوع با اهمیت و معرفی تعدادی از الگوریتم های رمزنگاری میپردازیم.الگوریتم های برگشت پذیر و پرگشت ناپذیرفرض کنید قصد دارید رشته &quot;Salam&quot; را رمزنگاری کنید. متناسب با صورت مساله باید یکی از الگوریتم های برگشت پذیر و برگشت ناپذیر را انتخاب کنید. اما تفاوت این دو نوع در چیست؟الگوریتم های برگشت پذیر: به طور کلی به الگوریتم هایی گفته میشود که پس از رمزنگاری داده اصلی و تبدیل به یک رشته معادل(ciphertext)، این رشته با استفاده از همان الگوریتم یا الگوریتم دیگری قابل بازگشت به رشته اصلی باشد.الگوریتم های برگشت ناپذیر: در این الگوریتم رشته اصلی اصطلاحا Hash میشود و به این عملیات Hashing میگویند.  هیچ گاه رشته هش قابل بازگشت به متن اصلی نخواهد بود. اما این رشته بازگشت ناپذیر به چه کار می‌آید؟ متن هش، با الگوریتم‎‌های مشخصی قابل تطبیق با سایر متن هاست. برای فهم بهتر این موضوع یک بار دیگر به مثال رمز عبور بازمیگردیم. زمانی که شما رمز عبور را به صورت هش ذخیره میکنید، هر بار که کاربر قصد لاگین به سیستم را داشته باشد، رمزی که وارد میکند با هش ذخیره شده صرفا تطبیق داده میشود. در صورت مطابق بودن، رمز وارد شده تایید و در غیر این صورت رد میشود.هر یک از الگوریتم های فوق بسته به نیازمندی شما کاربرد دارد. به طور مثال نمیتوان برای ذخیره سازی اطلاعاتی مثل شماره ملی کاربر از الگوریتم برگشت ناپذیر استفاده نمود، چرا که نیاز داریم تا مجددا اصل شماره ملی را به دست اوریم، اما برای مواردی مانند رمز عبور، باید از الگوریتم های برگشت ناپذیر استفاده نمود.الگوریتم های متقارن و نامتقارندر الگوریتم های مختلف برای رمزنگاری داده ها از یک کلید متنی استفاده میشود؛ به زبان دیگر به طور مثال وقتی میگوییم با استفاده از الگوریتم RSA داده ها رمزنگاری شده است، از یک الگوریتم استاندارد و جهانی صحبت میکنیم که روش کدگذاری و جزئیات الگوریتم تا حد زیادی مشخص است. بنابراین نیاز به وجود یک فاکتور محرمانه در این الگوریتم است تا افراد مختلف نتوانند صرفا با اطلاع از الگوریتم رمزنگاری، عملیات رمزگشایی را به راحتی انجام دهند. در واقع این کلید محرمانه از اهمیت بسیاری برخوردار است و نباید آشکار گردد. الگوریتم های رمزنگاری به دو دسته متقارن و نامتقارن تقسیم میشود. الگوریتم های متقارن: به الگوریتم هایی که کلید رمزگذاری و رمزگشایی آنها کاملا یکسان است، الگوریتم متقارن گویند. الگوریتم های نامتقارن: به الگوریتم هایی که کلید رمزگذاری و رمزگشایی آنها متفاوت است الگوریتم نامتقارن گویند. به طور مثال با کلید A تنها رمزگذاری صورت میگیرد و با کلید B تنها رمزگشایی.در ادامه مباحث رمزنگاری میتوانید به مقالات ذیل مراجعه نمایید.بررسی محبوب ترین الگوریتم های رمزنگاری متقارن و نامتقارنآشنایی با الگوریتم های Hashingهمچنین میتوانید این مقاله را در وبسایت آموزشی من به آدرس زیر مشاهده نمایید.https://classicode.org/B-52برای پیگیری آموزش ها و مقالات بیشتر، به صفحه لینکدین و وبسایت من سر بزنید.www.classicode.orgwww.linkedin.com/in/mrabiee1996   https://www.google.com/ </description>
                <category>Mohammad Rabiee</category>
                <author>Mohammad Rabiee</author>
                <pubDate>Sat, 19 Feb 2022 21:26:43 +0330</pubDate>
            </item>
            </channel>
</rss>