مطالب
سهولت کار با رشته‌ها‌ی پیچیده در C# 11 با معرفی Raw string literals
Raw String Literals، روشی ساده جهت تعریف یک قطعه‌ی متنی، بدون نیاز به escapeهای فراوان و یا تعریف ""‌های متعدد است؛ برای مثال نوشتن رشته‌های تشکیل شده‌ی از محتوای XML و یا JSON. به این صورت تعریف رشته‌های پیچیده، ساده‌تر شده و قابلیت نگهداری آن‌ها، بهبود خواهد یافت. Raw String Literal با حداقل سه عدد " متوالی، شروع شده و با حداقل سه عدد " متوالی، خاتمه پیدا می‌کنند:
string name = "Vahid", country = "Iran";
string jsonString =
    $$"""
    {
        "Name": {{name}},
        "Country": {{country}}
    }
    """;
Console.WriteLine(jsonString);
بدون وجود این قابلیت، معادل واقعی رشته‌ی فوق را باید به صورت زیر تشکیل داد:
"{\r\n \"Name\": Vahid,\r\n \"Country\": Iran\r\n}"

و یا امکان درج ساده‌تر عبارات XML، بدون نیاز به escape قسمتی از آن:
string html =
        """
        <body style="normal">
              <div class="book-content">
               This is information about the "C# 11" book.
           </body>
           <footer>
               This is information about the author of the "C# 11" book.
           </footer>
        </element>
        """;

سؤال: اگر در محتوای Raw String Literal تعریف شده، نیاز به سه عدد " متوالی وجود داشت، چه باید کرد؟

اگر به توضیحات فوق دقت کنید، عنوان شد که شروع و پایان Raw String Literals، با «حداقل» سه عدد " همراه است و به این صورت پیاده سازی می‌شود:
- اگر رشته‌ی شما نیاز به سه "" متوالی داشت، باید raw string literal را با حداقل چهار " شروع و خاتمه دهید.
- اگر رشته‌ی شما نیاز به چهار "" متوالی داشت، باید raw string literal را با حداقل پنج " شروع و خاتمه دهید.
و ... به همین ترتیب برای مابقی حالات.

var text1 = """" Hello World! """ """";
var text2 = """"" Hello World! """" """"";


کاهش فواصل سمت چپ رشته‌ها، با استفاده از Raw string literals

به مثال زیر که یک قطعه چند سطری SQL را به دو روش قدیم و جدید تعریف می‌کند، دقت کنید (فواصل سمت چپ در این مثال مهم هستند):
var sql1 =
        @"
        SELECT Name
        FROM Customers
        WHERE id = @id
        ";
Console.WriteLine(sql1);

var sql2 =
        """
        SELECT Name
        FROM Customers
        WHERE id = @id
        """;
Console.WriteLine(sql2);
آیا خروجی نمایشی این دو، یکی است؟
پاسخ: خیر! خروجی نمایشی این دو به صورت زیر است:
        SELECT Name
        FROM Customers
        WHERE id = @id
        
SELECT Name
FROM Customers
WHERE id = @id
در اینجا به فواصل سمت چپ رشته‌ها دقت کنید. همیشه فرمت کردن verbatim strings در زبان #C مشکل بوده‌است و در حین تعریف عبارات چند سطری، تنظیم فواصل سمت چپ، مساله ساز است. اما این مشکل با raw string literals وجود ندارد. در این حالت فقط کافی است رشته‌ی مدنظر را دقیقا ذیل جائیکه """ را تعریف کرده‌اید، شروع کنید (ستون شروع آن‌ها یکی باشد). به این ترتیب تمام فواصل سمت چپ آن، ندید گرفته می‌شوند.
خروجی واقعی رشته‌ی sql1 به صورت زیر است:
 "\r\n SELECT Name\r\n FROM Customers\r\n WHERE id = @id\r\n "
و رشته‌ی sql2 به این نحو تفسیر می‌شود (که حتی فواصل ابتدا و انتهای آن نیز Trim شده‌اند):
"SELECT Name\r\nFROM Customers\r\nWHERE id = @id"


استفاده  از string interpolation در raw string literals

همیشه عبارات ما از رشته‌های ثابت تشکیل نمی‌شوند. در این بین همواره نیاز به interpolation با مقادیر ثابت و یا متغیرها وجود خواهد داشت. انجام چنین کاری با raw string literals هم میسر است:
var name = "Vahid";
var text =
$"""
Hello {name1}!
Welcome to the Team!
""";

سؤال: اگر در این مثال نیاز بود تا از {} جهت مقاصد نمایشی استفاده شود، چه باید کرد؟ یعنی نیاز به درج {} صرفا متنی وجود داشت.
پاسخ: در اینجا تنها کاری را که باید انجام داد، استفاده از یک $ اضافه‌تر در ابتدای interpolated string است (مانند مثال ابتدای بحث):
var name1 = "Vahid";
var text =
$$"""
Hello {{{name1}}}!
Welcome to the Team!
""";
که در نهایت، معادل با رشته‌ی خروجی زیر است:
"Hello {Vahid}!\r\n\r\nWelcome to the Team!"

سؤال: اگر در این مثال نیاز بود تا از {{{}}} جهت مقاصد نمایشی استفاده شود، چه باید کرد؟
پاسخ: باید تعداد $‌های ابتدای رشته را افزایش داد. برای مثال اگر نیاز به درج سه { متوالی است، باید از 4 عدد $ در ابتدای رشته استفاده کرد:
var name4 = "Vahid";
var text4 =
$$$$"""
Hello {{{{{{{name4}}}}}}}!
Welcome to the Team!
""";
که خروجی آن، معادل رشته‌ی نهایی زیر است:
"Hello {{{Vahid}}}!\r\nWelcome to the Team!"
بنابراین تعداد $ مشخص می‌کند که چه تعداد از {{‌ها می‌توانند بدون اینکه عبارت interpolation را تشکیل دهند، در رشته حضور داشته باشند. برای مثال تمام ترکیب‌های زیر یک خروجی را دارند و آن هم همان name تعریف شده‌است:
string name = "Vahid";

var text1 = $"{name}";
var text2 = $"""{name}""";
var text3 = $$"""{{name}}""";
var text4 = $$$"""{{{name}}}""";
var text5 = $$$$"""{{{{name}}}}""";
در مثال فوق، تعداد $ها با تعداد جفت‌های {} یکی است. بنابراین تنها به عنوان یک interpolation expression delimiter تفسیر می‌شوند.
اما در مثال زیر، تعداد $ها با تعداد {}ها یکی نیست؛ برای مثال اگر از دو $ ابتدایی استفاده شود، ذکر یک جفت تکی {}، تنها به معنای وجود کاراکتری آن‌ها است و همینطور اگر از سه $ ابتدایی استفاده شود، ذکر یک جفت دو تایی {{}}، تنها به معنای وجود کاراکتری آن‌ها است و همینطور الی آخر. اما اگر معادل تعداد $ها، از جفت‌های {} استفاده شود، تمام آن‌ها با هم فقط یک interpolation expression delimiter را تشکیل می‌دهند.
string name = "Vahid";

var text6 = $$"""{name}"""; // = "{name}"
var text7 = $$"""{{{name}}}"""; // = "{Vahid}"

var text8 = $$$"""{{name}}"""; // = "{{name}}"
var text9 = $$$"""{{{{{name}}}}}"""; // = "{{Vahid}}"

var text10 = $$$$"""{{{name}}}"""; // = "{{{name}}}"
var text11 = $$$$"""{{{{{{{name}}}}}}}"""; // = "{{{Vahid}}}"
نظرات مطالب
نحوه کار با ftp - بخش اول
من فکر می‌کنم اگر ReSharper رو نصب کنید، پیش از ارائه یک مطلب یا پروژه خیلی از ایرادات رو با خط کشیدن زیر اون یا نمایش یک علامت زرد کنار صفحه گوشزد می‌کنه. مثلا می‌گه که این نوع نامگذاری درست نیست یا این شیء رو میشه با using محصور کرد. خلاصه از دستش ندید، حیفه!
نظرات مطالب
EF Code First #11
{شما باید بتوانید یک Repository بسازید که حتی به عنوان محل ذخیره سازی از یک فایل Text استفاده کند} کاملا موافقم. و این همون چیزیه که ازش بعنوان لایه سرویس یاد کردم. توضیحات کامل رو تو کامنت های پایین تر دادم.
فکر کنم اختلاف رو نامگذاری ها و برداشت متفاوتی که از تعاریف داریم، باشه.
نظرات مطالب
EF Code First #7
استفاده از View نکته خاص و اضافه‌تری نداره؛ از این لحاظ که عموما به Viewها به شکل یک جدول فقط خواندنی نگاه می‌شود. بنابراین یک کلاس تعریف کنید حاوی فیلدهای همان View. بعد هم یک data annotations  برای مثال Table را بالای این کلاس قرار دهید (اگر نیاز بود از نام خاصی که جزو اصول نامگذاری کلاس‌ها در سی شارپ نیست استفاده کند).
نظرات مطالب
MVVM و رویدادگردانی - قسمت دوم
ممنون

سوال اول:
این قسمت رو من درست متوجه نشدم
<>
رویداد کلیک رو که میشه مستقیم بایند کرد؟

سوال دوم:
فکر میکنید موارد ی که کار با این الگو رو راحت میکنن بصورت توکار برای WPF و SL اضافه بشه.
دقیقا چیزی که تو MVC داریم مثلا ساختار پروژه و نحوه نامگذاری (اضافه کردن controller به نام و...)
مطالب
استفاده از دکمه‌های CSS توئیتر در ASP.NET MVC - قسمت دوم
در قسمت اول  مشاهده کردیم که به چه صورت می‌توان از دکمه‌های CSS ایی بجای دکمه‌های معمولی در ASP.NET MVC استفاده کنیم. در این قسمت قصد داریم قابلیت مهم زیر را نیز به این تغییر اضافه نمائیم:

کاربر امکان دوبار کلیک کردن همزمان را بر روی دکمه ارسال، نداشته باشد

انجام اینکار با jQuery بسیار ساده است:
$(el).prop("onclick", null).attr("onclick", null);
به این ترتیب کاربر امکان کلیک مجدد را بر روی دکمه ارسال، از دست خواهد داد.
و اینکار ... یک مشکل را اضافه می‌کند:
اگر نتیجه اعتبار سنجی سمت کاربر فرم، تکمیل نشده باشد، کاربر پس از رفع مشکل دیگر نمی‌تواند فرم را ارسال کند. به همین جهت باید به نحوی اطمینان حاصل کرد که آیا اعتبارسنجی موفقیت آمیز بوده یا خیر؛ سپس دکمه را غیرفعال کنیم.
برای پیاده سازی این امر باید jQuery Validator همراه با ASP.NET MVC را به صورت دستی فراخوانی کرده و نتیجه آنرا ارزیابی کنیم:
function validateThisForm(formId) {
    var val = $(formId).validate();
    val.form();
    return val.valid();
}

function customSubmit(el, formId) {
    if (!validateThisForm(formId)) return;
    $(el).prop("onclick", null).attr("onclick", null);
    $(formId).submit();
}
در متد جاوا اسکریپتی validateThisForm، سیستم jQuery Validator  به صورت دستی فراخوانی شده و سپس نتیجه عملیات بازگشت داده می‌شود.
در متد customSubmit، ابتدا وضعیت اعتبار سنجی فرم بررسی شده و سپس بر این اساس تصمیم گرفته خواهد شد که آیا باید دکمه غیرفعال شود و سپس فرم ارسال گردد یا خیر.
یک مثال از استفاده آن:
@model MvcApplication27.Models.User
@{
    ViewBag.Title = "Index";
}
<h2>
    Index</h2>
@using (Html.BeginForm(Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "MyForm" })))
{
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>User</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        <span style="margin-top:7px;" onclick="customSubmit(this, '#MyForm')" class="btn btn-info">ارسال</span>
    </fieldset>
}
دریافت کدهای کامل این مثال:
MvcApplication27.7z
 
مطالب
معماری لایه بندی نرم افزار #1

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

ضد الگو (Antipattern) – رابط کاربری هوشمند (Smart UI)

با استفاده از Visual Studio یا به اختصار VS، می‌توانید برنامه‌های کاربردی را به راحتی تولید نمایید. طراحی رابط کاربری به آسانی عمل کشیدن و رها کردن (Drag & Drop) کنترل‌ها بر روی رابط کاربری قابل انجام است. همچنین در پشت رابط کاربری (Code Behind) تمامی عملیات مربوط به مدیریت رویدادها، دسترسی به داده ها، منطق تجاری و سایر نیازهای برنامه کاربردی، کد نویسی خواهند شد. مشکل این نوع کدنویسی بدین شرح است که تمامی نیازهای برنامه در پشت رابط کاربری قرار می‌گیرند و موجب تولید کدهای تکراری، غیر قابل تست، پیچیدگی کدنویسی و کاهش قابلیت استفاده مجدد از کد می‌گردد.

به این روش کد نویسی Smart UI می‌گویند که موجب تسهیل تولید برنامه‌های کاربردی می‌گردد. اما یکی از مشکلات عمده‌ی این روش، کاهش قابلیت نگهداری و پشتیبانی و عمر کوتاه برنامه‌های کاربردی می‌باشد که در برنامه‌های بزرگ به خوبی این مشکلات را حس خواهید کرد.

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

تفکیک و جدا سازی اجزای برنامه کاربردی (Separating Your Concern)

راه حل رفع مشکل Smart UI، لایه بندی یا تفکیک اجزای برنامه از یکدیگر می‌باشد. لایه بندی برنامه می‌تواند به شکل‌های مختلفی صورت بگیرد. این کار می‌تواند توسط تفکیک کدها از طریق فضای نام (Namespace)، پوشه بندی فایلهای حاوی کد و یا جداسازی کدها در پروژه‌های متفاوت انجام شود. در شکل زیر نمونه ای از معماری لایه بندی را برای یک برنامه کاربردی بزرگ می‌بینید.

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

1- Visual Studio را باز کنید و یک Solution خالی با نام SoCPatterns.Layered ایجاد نمایید.

· جهت ایجاد Solution خالی، پس از انتخاب New Project، از سمت چپ گزینه Other Project Types و سپس Visual Studio Solutions را انتخاب نمایید. از سمت راست گزینه Blank Solution را انتخاب کنید.

2- بر روی Solution کلیک راست نموده و از گزینه Add > New Project یک پروژه Class Library با نام SoCPatterns.Layered.Repository ایجاد کنید.

3- با استفاده از روش فوق سه پروژه Class Library دیگر با نامهای زیر را به Solution اضافه کنید:

  • SoCPatterns.Layered.Model
  • SoCPatterns.Layered.Service
  • SoCPatterns.Layered.Presentation

4- با توجه به نیاز خود یک پروژه دیگر را باید به Solution اضافه نمایید. نوع و نام پروژه در زیر لیست شده است که شما باید با توجه به نیاز خود یکی از پروژه‌های موجود در لیست را به Solution اضافه کنید.

  • Windows Forms Application (SoCPatterns.Layered.WinUI)
  • WPF Application (SoCPatterns.Layered.WpfUI)
  • ASP.NET Empty Web Application (SoCPatterns.Layered.WebUI)
  • ASP.NET MVC 4 Web Application (SoCPatterns.Layered.MvcUI)

5- بر روی پروژه SoCPatterns.Layered.Repository کلیک راست نمایید و با انتخاب گزینه Add Reference به پروژه‌ی SoCPatterns.Layered.Model ارجاع دهید.

6- بر روی پروژه SoCPatterns.Layered.Service کلیک راست نمایید و با انتخاب گزینه Add Reference به پروژه‌های SoCPatterns.Layered.Model و SoCPatterns.Layered.Repository ارجاع دهید.

7- بر روی پروژه SoCPatterns.Layered.Presentation کلیک راست نمایید و با انتخاب گزینه Add Reference به پروژه‌های SoCPatterns.Layered.Model و SoCPatterns.Layered.Service ارجاع دهید.

8- بر روی پروژه‌ی UI خود به عنوان مثال SoCPatterns.Layered.WebUI کلیک راست نمایید و با انتخاب گزینه Add Reference به پروژه‌های SoCPatterns.Layered.Model، SoCPatterns.Layered.Repository، SoCPatterns.Layered.Service و SoCPatterns.Layered.Presentation ارجاع دهید.

9- بر روی پروژه‌ی UI خود به عنوان مثال SoCPatterns.Layered.WebUI کلیک راست نمایید و با انتخاب گزینه Set as StartUp Project پروژه‌ی اجرایی را مشخص کنید.

10-  بر روی Solution کلیک راست نمایید و با انتخاب گزینه Add > New Solution Folder پوشه‌های زیر را اضافه نموده و پروژه‌های مرتبط را با عمل Drag & Drop در داخل پوشه‌ی مورد نظر قرار دهید.

  • 1. UI
    • § SoCPatterns.Layered.WebUI

  • 2. Presentation Layer
    • § SoCPatterns.Layered.Presentation

  • 3. Service Layer
    • § SoCPatterns.Layered.Service

  • 4. Domain Layer
    • § SoCPatterns.Layered.Model

  • 5. Data Layer
    • § SoCPatterns.Layered.Repository
  • توجه داشته باشید که پوشه بندی برای مرتب سازی لایه‌ها و دسترسی راحت‌تر به آنها می‌باشد.

پیاده سازی ساختار لایه بندی برنامه به صورت کامل انجام شد. حال به پیاده سازی کدهای مربوط به هر یک از لایه‌ها و بخش‌ها می‌پردازیم و از لایه Domain شروع خواهیم کرد. 

مطالب
پیاده سازی CQRS توسط MediatR - قسمت اول
در مطالب قبلی (1 , 2) الگوی CQRS معرفی شد. همانطور که می‌بینید، پیاده سازی این الگو هرچند با فریمورک آماده‌ای همچون SimpleCQRS، دارای پیچیدگی زیادی است و باعث نوشتن حجم زیادی کد می‌شود.

فریمورک MediatR توسط توسعه دهنده کتابخانه‌ی محبوب AutoMapper ایجاد شده‌است. این فریمورک پیاده سازی کاملی از الگوی طراحی Mediator در NET. است که داخل خود، تمام پیچیدگی‌های پیاده سازی CQRS را Abstract کرده و با حداقل کد ممکن، می‌توانید به‌راحتی CQRS را داخل پروژه‌ی خود پیاده سازی کنید.

در این سری مطالب به بررسی کامل الگوی CQRS و مزایا و معایب استفاده از آن می‌پردازیم و سپس با استفاده از کتابخانه‌ی Mediatr، این الگو را داخل یک پروژه پیاده سازی می‌کنیم.

CQRS

در CQRS متد‌های برنامه به 2 بخش Read و Write تقسیم می‌شوند. بخش‌هایی که State کلی برنامه ( شامل Database, Cookie, Session, LocalStorage, Memory و ... ) را تغییر می‌دهند، Command و بخش‌هایی که صرفا جنبه خواندنی دارند و وضعیت سیستم را تغییر نمی‌دهند مثل خواندن و نشان دادن اطلاعات از دیتابیس، Query می‌نامند.

* نکته : Naming Convention مورد استفاده برای Command‌‌ها به صورت دستوری است و کار Command در نام آن مشخص است؛ مثال : RegisterUser, SendForgottenPasswordEmail, PlaceOrder

مزایا:
1- شما می‌توانید تکنولوژی‌های مورد استفاده‌ی در بخش‌های Command و Query برنامه‌ی خود را به‌راحتی از هم جدا سازید. به‌عنوان مثال Apache Cassandra در ذخیره سازی داده‌ها ( Write Side ) به عنوان یک دیتابیس قابل اعتنا شناخته میشود و از طرفی دیگر ElasticSearch بدلیل سرعت فوق العاده‌ی خود، برای خواندن داده‌ها استفاده میشود. در این روش، دیتابیس‌ها باید Sync باشند تا داده‌های به‌روز به کاربر نمایش داده شود که این موضوع چالش‌های خود همچون Eventual Consistency و Strong Consistency را دارد که در مقالات بعدی آن‌ها را بررسی خواهیم کرد.

2- در برنامه‌های معمول، اکثرا بخش Read Side، بیشتر از Write Side استفاده می‌شود و کاربران معمولا اطلاعات را دریافت و می‌بینند تا اینکه در آن تغییری ایجاد کنند؛ در این صورت شما می‌توانید بخش Read برنامه‌ی خود را Scale کرده و تعداد سیستم یا منابع بیشتری را به این قسمت از برنامه‌ی خود اختصاص دهید ( Horizontal Scaling, Vertical Scaling ). 

3- این جداسازی باعث تمرکز بیشتر شما بر روی قسمت‌های مختلف برنامه می‌شود؛ بخش‌هایی که وضعیت سیستم را تغییر می‌دهند از بخش‌هایی که صرفا داده‌هایی را خوانده و نمایش می‌دهند، بطور کامل جدا شده‌اند و به‌راحتی قابلیت تغییر هرکدام از این بخش‌ها را خواهید داشت.

معایب : معمولا از معایب این الگو، از پیچیدگی پیاده سازی آن یاد می‌شود که در این آموزش با استفاده از Mediatr سعی بر از بین بردن این پیچیدگی را داریم.

Events

Event‌ها رویدادهایی هستند که خبر انجام کاری را که قبلا داخل سیستم انجامش به پایان رسیده است، به Consumer‌های خود می‌دهند. بعنوان مثال می‌خواهیم بعد از ثبت نام موفق یک کاربر داخل سیستم، Notification و یا ایمیلی را به او ارسال کنیم. بعد از ثبت نام کاربر میتوانیم Event ای به نام UserRegistered را که شامل Username و Email کاربر در بدنه خود است، Raise کنیم.

Event‌ها می‌توانند چندین Consumer داشته باشند؛ بنابراین می‌توانیم یک EventHandler را برای UserRegistered بنویسیم که Email ارسال کند و EventHandler دیگری ایجاد کنیم که Notification ای را برای کاربر بفرستد.

* نکته : Naming Convention مورد استفاده برای Event‌ها به صورت گذشته‌است و خبر یک کار، که قبلا انجام شده است را می‌دهد؛ مثال : UserRegistered, OrderPlaced

Event Sourcing

Event Sourcing به معنای ذخیره‌ی تمام Event‌های رخ داده در برنامه داخل یک دیتابیس Append-Only است. در این نوع دیتابیس‌ها فقط میتوانیم Event‌های جدیدی به آن اضافه کنیم و قادر به ویرایش و حذف Event‌ها نیستیم؛ چون منطق Event، کارهایی است که در گذشته اتفاق افتاده‌اند و ما قادر به تغییر چیزی که در گذشته رخ داده‌است، نیستیم.

مزیت Event Sourcing این است که State برنامه را در زمان‌های مختلفی نگه داشته‌ایم و می‌توانیم وضعیت سیستم را در تاریخی مشخص، پیدا کنیم و در صورت به‌وجود آمدن مشکلی در سیستم، وضعیت آن را تا قبل از به مشکل خوردن، بررسی کنیم.

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

روش دیگری وجود دارد که بجای به‌روزرسانی مداوم state جاری، تمام Event هایی که در آن تراکنشی داخل سیستم رخ داده و این تراکنش State برنامه را تحت تاثیر خود قرار داده‌است، داخل یک دیتابیس اضافه نماییم. در این صورت بدلیل داشتن تمام رویدادهای اتفاق افتاده‌ی در برنامه، می‌توان وضعیت جاری سیستم را شبیه سازی و متوجه شد.

* در این سری آموزشی از دیتابیس  Event Store برای پیاده سازی Event Sourcing استفاده خواهیم کرد.

در مقاله‌ی بعدی، امکانات فریمورک MediatR را بررسی خواهیم کرد.
نظرات مطالب
معرفی کتابخانه PdfReport
- هر ستون عددی که در تعریف آن AggregateFunction درج و مشخص شود، به صورت خودکار دارای فیلدهای ته جمع خواهد بود.
- برچسب‌ها هم فقط یکبار در هر ردیف مشخص می‌شوند به صورت خودکار (پیش فرض) یا حالت سفارشی که عنوان شد (مرسوم تمام گزارشات متداول به همین نحو است).
نظرات مطالب
چگونه یک ایمیل مفید خودکار را طراحی کنیم؟
مفید و به موقع بود. درست همین روزها من هم باید دست به کار ساختن یک سیستم ایمیل خودکار شوم. البته دوست داشتم کمی راجع به مسائل فنی و روش‌های جلوگیری از اسپم شناخته شدن ایمیل‌های خودکار هم می‌نوشتید.