مطالب
پلاگین DataTables کتابخانه jQuery - قسمت دوم
در قسمت قبلی شما را با DataTables آشنا کردم. به طور خلاصه نحوه اعمال کردن DataTables به یک جدول ساده html را گفتیم که با این کار به صورت پیش فرض، امکاناتی مثل فیلتر کردن داده ها، صفحه بندی و مرتب سازی آنها و نیز اعمال شدن استایل‌های css به همین جدول html خام اضافه می‌شود. نکته مهم در مثال قبلی این بود که داده‌های درون این جدول با کدنویسی خام html فراهم شدند، اما این را در نظر داشته باشید که اکثریت مواقع باید داده‌ها از یک بانک اطلاعاتی دریافت شوند و سپس درون جدول قرار بگیرند.

در این قسمت سعی خواهیم کرد تا منبع داده جدول را یک آرایه جاوا اسکریپتی و سپس کالکشنی از آبجکتهای جاوا اسکریپتی (json) در نظر بگیریم و نیز برخی ویژگی‌های پیش فرض پلاگین را غیر فعال نمائیم.

فرض کنید می‌خواهید لیستی از اطلاعات دانشجویان شامل نام (FirstName)، نام خانوادگی (LastName)، و سن (Age) را نمایش دهید. اطلاعات قرار است در جدول زیر قرار بگیرند:
<table id="std-grid">
      <thead>
           <th>نام</th>
           <th>نام خانوادگی</th>
           <th>سن</th>
     </thead>
     <tbody>
                
     </tbody>
</table>


مشاهده می‌کنید که این جدول فقط شامل قسمت header است و در بدنه آن هیچ سطری قرار نگرفته است. در این مثال اطلاعات از یک آرایه جاوا اسکریپتی باید خوانده شوند و تبدیل به html شده و در نهایت درون قسمت <tbody></tbody> آن تزریق شوند. خوشبختانه DataTables برای این کار امکانات آماده ای را در اختیار قرار می‌دهد. این کار بدین صورت قابل انجام است:
<script>        
        $(document).ready(function() {
            $('#std-grid').dataTable({
                "aaData": [
                        ["پژمان", "پارسائی", "24"],
                        ["سعید", "الیاسی", "25"],
                        ["محمد رضا", "گلزار", "20"],
                        ["آرش", "ایرانی", "19"],
                        ["مرتضی", "فرمانی", "22"],
                        ["سعید", "حمیدیان", "23"],
                        ["امین", "پارسانیا", "23"],
                        ["محمد امین", "فقیهی", "24"],
                        ["محمد", "خرمی", "25"],
                        ["سینا", "امیریان", "20"],
                        ["آرش", "ایرانی", "19"],
                        ["وحید", "فرزانه", "22"],
                        ["امیر علی", "فرمانی", "23"],
                        ["امین", "حسینی", "23"],
            });
        });
        
    </script>

شرح کد:
aaData : یک آرایه دو بعدی (که به آن ماتریس یا آرایه ای از آرایه‌ها هم گفته می‌شود) است که مقادیر سلول هایی را نشان می‌دهد که در جدول قرار خواهند گرفت. تعداد ستون‌ها در این آرایه دو بعدی باید با تعداد ستون‌های جدول html متناظر یکسان باشند.

در مثال بالا از یک ماتریس به عنوان منبع داده استفاده شد. منبع داده می‌تواند به فرمت json نیز باشد. البته در این صورت باید ستون‌های جدول html را هم به پلاگین معرفی کنید، بدین صورت:
$(document).ready(function() {            
            $('#std-grid').dataTable({
                "aaData": [
                    {"FirstName" : "پژمان", "LastName" : "پارسائی", "Age" : "24"},
                    { "FirstName": "سعید", "LastName": "الیاسی", "Age": "25" },
                    { "FirstName": "محمد رضا", "LastName": "گلزار", "Age": "24" },
                    { "FirstName": "آرش", "LastName": "ایرانی", "Age": "24" },
                    { "FirstName": "مرتضی", "LastName": "فرمانی", "Age": "24" },
                    { "FirstName": "سعید", "LastName": "حمیدیان", "Age": "24" },
                    { "FirstName": "امین", "LastName": "پارسانیا", "Age": "24" },
                    { "FirstName": "محمد امین", "LastName": "فقیهی", "Age": "24" },
                    { "FirstName": "محمد", "LastName": "خرمی", "Age": "24" },
                    { "FirstName": "سینا", "LastName": "امیریان", "Age": "24" },
                    { "FirstName": "آرش", "LastName": "ایرانی", "Age": "24" },
                    { "FirstName": "وحید", "LastName": "فرزانه", "Age": "24" },
                    { "FirstName": "امیر علی", "LastName": "فرمانی", "Age": "24" },
                    { "FirstName": "امین", "LastName": "حسینی", "Age": "24" },
                ],
                "aoColumns": [
                      { "mDataProp": "FirstName" },
                      { "mDataProp": "LastName" },
                      { "mDataProp": "Age" }
                ]
            });
        });

aaData : همان طور که گفته شد در این قسمت دیتاهای درون جدول آورده می‌شوند و در این مثال آنها به فرمت json نوشته شده اند.
aoColumns : در این قسمت باید اسم ستون‌های جدول ذکر شوند.


غیرفعال کردن بعضی از ویژگی‌های پیش فرض DataTables

همان طور که گفته شد پلاگین DataTables به صورت پیش فرض ویژگی‌های مرتب سازی (sorting)، صفحه بندی (paging)، فیلتر کردن داده‌ها (filtering)، و غیره را به جدول مورد نظرش اعمال می‌کند. و بدین صورت قابل تغییر است:
$('#std-grid').dataTable({
          "bPaginate": false,
          "bLengthChange": false,
          "bFilter": false,
          "bSort": false,
          "bInfo": true,
          "bAutoWidth": false
});

bPaginate : بیان می‌کند آیا صفحه بندی سطرهای جدول فعال باشد یا نه.
bLengthChange : در صورتی که قابلیت صفحه بندی فعال باشد ، بیان می‌کند که کاربر بتواند اندازه صفحه را تغییر دهد یا نه.
bFilter : بیان می‌کند آیا قابلیت فیلتر کردن داده‌ها فعال باشد یا نه.
bSort : بیان می‌کند قابلیت مرتب سازی داده‌های جدول فعال باشد یا نه.
bInfo : بیان می‌کند که قسمت info زیر گرید نشان داده شود یا نه (در این قسمت اطلاعاتی راجع به تعداد کل رکوردهای بایند شده به جدول و نیز رکوردهای درون صفحه جاری نشان داده می‌شود)
bAutoWidth : در صورتی که این گزینه فعال باشد اندازه عرض هر ستون به صوتر خودکار توسط DataTables مقدار دهی خواهد شد.

مقدارهای قابل قبول برای هر کدام از این خصوصیات : true یا false

کدهای مربوط به این مثال را می‌توانید از لینک زیر دریافت کنید:
DataTables-DoteNetTips-Tutorial-02.zip 
اشتراک‌ها
معرفی ابزارهای مفید و رایگان fishcode
نرم افزارهای ارائه شده این تیم به صورت رایگان بوده و عموما بدون نیاز به نصب و با حجم بسیار کم میباشد که ابزارهای بسیار کارآمدی در اختیار برنامه نویسان قرار داده است.   
توضیحات تکمیلی در مورد نرم افزار‌ها در سایت این تیم قرار دارد ولی جهت آشنایی دوستان به صورت مختصر در مورد چند نرم افزار مفید این تیم توضحاتی خواهم داد. 

  • Convert.Net
یکی از مفیدترین و بهترین ابزارهای این تیم نرم افزار Convert.Net است که امکانات مفیدی در اختیار شما قرار میدهد از جمله :
  1. Regular Expression Tester : که جهت تست Regex‌های نوشته شده استفاده میشود.
  2. Encoding & Decoding : جهت تبدیل انواع رشته‌های Encoded ویا Decoded به یکدیگر استفاده میشود و از html - url - EScape-js - Base64 - string و ... پشتیبانی میکند.
  3. Encryption & Decryption : جهت Encrypt و Decrypt انواع رشته استفاده میشود که از انکریپتورهای معروفی همچون  AES - Rijndael - DES - SHA - TripleDES پشتیبانی میکند.
  4. Language Translation : یک دیکشنری Multi Language آنلاین در اختیار شما برای ترجمه متون قرار میدهد.
  5. C# & VB.Net Convertor : برای تبدیل کدهای C# به Vb و برعکس استفاده میشود و  طبق تست هایی که روش به شخصه انجام دادم در اکثر موارد بدون خطا تا حدود 90 درصد تبدیلات رو به صورت موفق انجام میده ولی مانند سایر Convertor‌ها با Lambda Expression کمی مشکل دارد.
  6.  Xml & Json Browser : برای مشاهده و تبدیل Xml به Json و برعکس بسیار مفید است .. 
  7. Linq Tester : برای تست کوئری‌های Linq استفاده میشود . (برای استفاده از این امکان باید Roslyne روی سیستم شما نصب باشد)
حجم برنامه 2 مگابایت : دانلود

  • Database.Net
نرم افزار کم حجم جهت اتصال و مدیریت انواع دیتابیس میباشد در عین سادگی و حجم کم ابزار مفیدی جهت اجرای Query‌ها ساخت جداول , مشاهده و ویرایش رکوردها و .... در اختیارتان قرار میدهد.
دیتابیس‌های پشتیابنی شده در این نرم افزار : 
SQL Server 2000/2005/2008/2012/2014/Express/LocalDB         
SQL Server Compact 3.1/3.5/4.0 (*.sdf;*.*)         
SQL Azure 10/11        
MS Access 97/2000/2002/2003 (*.mdb;*.mde;*.*), 2007/2010/2013 (*.accdb;*.accde;*.*)         
MS Excel 97/2000/2002/2003(*.xls;*.*), 2007/2010/2013 (*.xlsx;*.xlsm;*.xlsb;*.*)         
Firebird SuperServer/Embedded 1.5/2.0/2.1/2.5 (*.gdb;*.fdb;*.*)       
SQLite 3.x (*.db;*.db3;*.sqlite;*.*)       
MySQL 5.x, MariaDB 5.x/10.x         
PostgreSQL 8.x/9.x     
Oracle 10g/11g/12c       
IBM DB2 9.x/10.x         
IBM Informix 11.x/12.x         
Sybase ASE 15.x         
dBASE IV (*.dbf)   
Visual FoxPro (*.dbc)    
Data Sources (OleDB)(*.udl;*.*)     
ODBC DSN (Data Source Name)(*.dsn;*.*)       
OData (Open Data Protocol) v1/v2/v3/v4
حجم برنامه 9 مگابایت : دانلود

  • Resource.Net
این نرم افزار جهت ساخت , ویرایش و مدیریت انواع فایل Resource برنامه‌های دات نت بسیار مفید میباشد که از نسخه‌های مختلف دات نت پشتیبانی میکند.

سایر نرم افزار‌های این تیم هم مانند نرم افزارهای معرفی شده بین کاربران محبوبیت زیادی کسب کرده اند که میتوانید برای کسب اطلاعات بیشتر و دانلود این نرم افزار‌ها به وب سایت این تیم مراجعه فرمائید. 
معرفی ابزارهای مفید و رایگان fishcode
نظرات مطالب
آموزش LINQ بخش سوم
0001 معادل 4 کاراکتر هست و 00010 معادل 5 کاراکتر. اگر هر دو 5 کاراکتر بودند، می‌تونستید در شرط where از => && =< برای مقایسه‌ی رشته‌ها استفاده کنید (و پاسخ درستی هم دریافت کنید):
var list = db.Documents.Where(x => x.Code.CompareTo(Start) >= 0 && x.Code.CompareTo(End) <= 0);
الان که نیستند این‌ها را تبدیل به Int کنید بعد مقایسه کنید:
int minValue = 1;
int maxValue = 10;
var list = db.Documents.Where(x => (int)x.Code >= minValue && (int)x.Code <= maxValue);
نظرات مطالب
آشنایی با ساختار ViewBag
کلمه dynamic به کامپایلر اعلام میکنه که شی که تعریف کردیم میتونه تغییر کنه یعنی انواع مختلفی به خودش بگیره . شما وقتی یک شی رو با var تعریف میکنید و یک عدد صحیح به اون اختصاص میدید،  در دفعه بعد نمیتونید چیزی غیر از عدد صحیح به اون اختصاص بدین. اما با استفاده از dynamic این کار امکان پذیره.
var x = 12; //OK
x = "String" //خطای کامپایل

dynamic y = 12; //OK
y="String"; //OK
y=12.7; //OK

پاسخ به بازخورد‌های پروژه‌ها
ایجاد ستون چند داده ای
از فیلد محاسباتی استفاده کنید.
اینجا اگر نوع داده شما strongly typed بود، به نحو زیر دسترسی به کلیه فیلدهای ردیف جاری خواهید داشت:
 column.CalculatedField(true,
                         list =>
                         {
                             if (list == null) return string.Empty;
                             var name = list.GetSafeStringValueOf<User>(x => x.Name);
                             var lastName = list.GetSafeStringValueOf<User>(x => x.LastName);
                             return name + " - " + lastName;
                         });
و اگر strongly typed نبود، مثلا مستقیما کوئری SQL نوشتید، همین متدهای GetSafeStringValueOf و امثال آن (تعریف شده در فضای نام PdfRpt.Core.Helper)، ورودی رشته‌ای هم نام فیلد مدنظر شما را هم قبول می‌کنند.
نظرات مطالب
بررسی روش آپلود فایل‌ها از طریق یک برنامه‌ی Angular به یک برنامه‌ی ASP.NET Core
یک نکته‌ی تکمیلی: به روز رسانی مثال مطلب جاری جهت گزارش درصد پیشرفت آپلود فایل‌ها توسط HTTP Client جدید Angular

در اینجا می‌خواهیم بدون استفاده از هیچگونه کامپوننت ثالثی، صرفا بر اساس قابلیت‌های جدید ماژول HttpClient ارائه شده‌ی در Angular 4.3، درصد پیشرفت آپلود را نیز نمایش دهیم. تغییرات مورد نیاز برای این منظور به شرح زیر هستند:

1) تغییر سرویس برنامه جهت استفاده از HTTP Client و گزارش درصد پیشرفت

  postTicket(ticket: Ticket, filesList: FileList): Observable<HttpEvent<any>> {

    //… the same as before

    const headers = new HttpHeaders().set("Accept", "application/json");
    return this.http
      .post(`${this.baseUrl}/SaveTicket`, formData, {
        headers: headers,
        reportProgress: true,
        observe: "events"
      })
      .map(response => response || {})
      .catch((error: HttpErrorResponse) => {
        console.error("observable error: ", error);
        return Observable.throw(error.statusText);
      });
  }
در اینجا متد postTicket، به این صورت تغییر کرده‌است:
الف) خروجی متد آن یک Observable از نوع HttpEvent تعیین شده‌است. به این ترتیب مشترکین به آن قادر خواهند شد به رخ‌دادهای HTTP Client گوش فرا دهند:
 postTicket(ticket: Ticket, filesList: FileList): Observable<HttpEvent<any>> {

ب) به قسمت options متد post، گزینه‌ها‌ی "observe: "events و reportProgress: true اضافه شده‌اند:
{
  headers: headers,
  reportProgress: true,
  observe: "events"
}
به این ترتیب، رخ‌دادها به همراه گزارش درصد پیشرفت آپلود و دانلود، به مشترکین این متد ارسال خواهند شد.

2) تغییر متد submitForm کامپوننت جهت گزارش و اعمال تغییرات به قالب برنامه

  queueProgress: number;
  isUploading: boolean;
  uploadTimeRemaining: number;
  uploadTimeElapsed: number;
  uploadSpeed: number;

  submitForm(form: NgForm) {
    const fileInput: HTMLInputElement = this.screenshotInput.nativeElement;
    this.queueProgress = 0;
    this.isUploading = true;
    let startTime = Date.now();

    this.uploadService.postTicket(this.model, fileInput.files).subscribe(
      (event: HttpEvent<any>) => {
        switch (event.type) {
          case HttpEventType.Sent:
            startTime = Date.now();
            console.log("Request sent!");
            break;
          case HttpEventType.DownloadProgress:
          case HttpEventType.UploadProgress:
            if (event.total) {
              this.queueProgress = Math.round(event.loaded / event.total * 100);

              const timeElapsed = Date.now() - startTime;
              const uploadSpeed = event.loaded / (timeElapsed / 1000);
              this.uploadTimeRemaining = Math.ceil(
                (event.total - event.loaded) / uploadSpeed
              );
              this.uploadTimeElapsed = Math.ceil(timeElapsed / 1000);
              this.uploadSpeed = uploadSpeed / 1024 / 1024;
            }
            break;
          case HttpEventType.Response:
            this.queueProgress = 100;
            this.isUploading = false;
            console.log("Done! ResponseBody:", event.body);
            break;
        }
      },
      (error: HttpErrorResponse) => {
        this.isUploading = false;
        console.log(error);
      }
    );
  }
پس از اینکه خروجی متد سرویس ارسال فایل‌ها را از نوع <<Observable<HttpEvent<any تعیین کردیم، اکنون پس از subscribe به آن، اینبار event: HttpEvent را بجای data متداول دریافت می‌کنیم. سپس بر اساس event.type می‌توان در مورد رخ‌داد گزارش داده شده، تصمیم‌گیری کرد:
- HttpEventType.Sent شروع عملیات است. برای مثال از آن می‌توان جهت تعیین زمان شروع به آپلود استفاده کرد. سپس این زمان را با زمان جاری، در رخ‌داد آپلود به سرور مقایسه و گزارش سرعت آپلود، زمان‌های صرف شده و باقیمانده را محاسبه کرد.
- HttpEventType.DownloadProgress و HttpEventType.UploadProgress گزارش درصد آپلود را مشخص می‌کنند. در اینجا event.total حجم کلی است و event.loaded حجم ارسالی کلی به سمت سرور می‌باشد. به همین جهت از این اطلاعات می‌توان برای نمایش درصد کل آپلود استفاده کرد.
- HttpEventType.Response در پایان عملیات رخ‌خواهد داد. در اینجا event.body همان بدنه‌ی response دریافتی از سمت سرور است.

3) تغییر رابط کاربری برنامه (قالب کامپوننت) جهت گزارش درصد پیشرفت کلی آپلود
    <div *ngIf="queueProgress > 0">
      <table class="table">
        <thead>
          <tr>
            <th width="15%">Event</th>
            <th>Status</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td><strong>Elapsed time</strong></td>
            <td nowrap>{{uploadTimeElapsed | number:'.1'}} second(s)</td>
          </tr>
          <tr>
            <td><strong>Remaining time</strong></td>
            <td nowrap>{{uploadTimeRemaining | number:'.1'}} second(s)</td>
          </tr>
          <tr>
            <td><strong>Upload speed</strong></td>
            <td nowrap>{{uploadSpeed | number:'.3'}} MB/s</td>
          </tr>
          <tr>
            <td><strong>Queue progress</strong></td>
            <td>
              <div class="progress-bar progress-bar-info progress-bar-striped" role="progressbar"
                aria-valuemin="0" aria-valuemax="100" [attr.aria-valuenow]="queueProgress"
                [ngStyle]="{ 'width': queueProgress + '%' }">
                {{queueProgress}}%
              </div>
            </td>
          </tr>
        </tbody>
      </table>
    </div>

    <button class="btn btn-primary" [disabled]="form.invalid || isUploading" type="submit">Submit</button>
در اینجا کار نمایش زمان صرف شده، زمان باقیمانده، سرعت آپلود و همچنین درصد میزان پیشرفت آپلود انجام شده‌اند. درصد محاسبه شده به ngStyle متصل شده‌است تا سبب حرکت progressbar بوت استرپ شود.
همچنین در طی مدت آپلود، خاصیت isUploading به true تنظیم می‌شود تا دکمه‌ی ارسال را غیرفعال کند. این خاصیت در صورت بروز خطایی و یا تکمیل شدن عملیات، false می‌شود.



یک نکته: اگر می‌خواهید درصد پیشرفت آپلود را در حالت آزمایش local بهتر مشاهده کنید، دربرگه‌ی network، سرعت را بر روی 3G تنظیم کنید:



کدهای کامل این تغییرات را از اینجا می‌توانید دریافت کنید.
نظرات مطالب
مقدمه ای بر AutoMapper
از آنجا که این مقاله جز مقالاتی است که به دلیل عنوان مقدمه در آن ارجاع به آن اول صورت میگیرد، این نکته رو اضافه کنم که در نسخه‌های جدیدتر Automapper استفاده از حالت استاتیک مردود اعلام شده و نحوه نوشتن به شکل زیر میباشد:
var config = new MapperConfiguration(cfg => {
  cfg.CreateMap<Source, Dest>();
});

IMapper mapper = config.CreateMapper();
var source = new Source();
var dest = mapper.Map<Source, Dest>(source);
نظرات مطالب
ارسال عکس به stimulsoft و ایجاد گزارش
ممنون از پاسخ شما.
با استفاده از همین کد بالا عکس رو ارسال کردم، اما یه کار دیگه کردم توی خود گزارش که درست شد.
فقط با این تفاوت که این نیازی به این دو خط نیست:
StiImage stiImg = new StiImage();
                stiImg.Image = img;

من ستون Image رو در خود business Object ساخته بودم و همون رو در Data Band استفاده میکردم، اومدم یک باکس از نوع Image  اضافه کردم که تصویر اون رو Data Column  و همون ستون Image در business object انتخاب کردم و درست شد.
مطالب
پیاده سازی Option یا Maybe در #C

Options یا Maybe در یک زبان تابعی مثل #F، نشان دهنده‌ی این است که شیء (Object) ممکن است وجود نداشته باشد(Null Reference) که یکی از مهمترین ویژگی‌های یک زبان شیءگرا مثل #C و یا Java محسوب می‌شودما برنامه نویس‌ها (اغلب) از هرچیزی که باعث کرش برنامه می‌شود، بیزاریم و برای اینکه برنامه کرش نکند، مجبور میشویم تمام کد‌های خود  را از Null Reference محافظت کنیم. تمام این مشکلات توسط Tony Hoare مخترع ALOGL است که تنها دلیل وجود Null References را سادگی پیاده سازی آن می‌داند و او این مورد را یک «خطای  میلیون دلاری» نامیده‌است. 

به این مثال توجه بفرمایید: 

public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

public class UserService : IUserService
    {
        private IList<User> _userData;

        public UserService()
        {
            _userData = new List<User>
            {
                new User {Id = 1,Name = "ali"},
                new User {Id = 2,Name = "Karim"}
            };
        }

        public User GetById(int id)
        {
            return _userData.FirstOrDefault(x => x.Id == id);
        }
    }  

public class UserController : Controller
    {
        private readonly IUserService _userService;

        public UserController(IUserService  userService)
        {
            _userService = userService;
        }
        public ActionResult Details(int id)
        {
            var user=_userService.GetById(3); // این متد ممکن است مقداری برگرداند و یا مقدار نال برگرداند                           
            if( user == null)
                 return HttpNotFound();    
            return View(user);  
        }
    }

این کدی است که ما برنامه نویسان به صورت متداولی با آن سروکار داریم. اما چه چیزی درباره این کد اشکال دارد؟

مشکل از آن جایی هست که ما نمی‌دانیم متد GetById مقداری را برمیگرداند و یا Null را بر می‌گرداند. این متد هرگاه که امکان برگرداندن Null وجود داشته باشد، خطای  NullReferenceException را در زمان اجرا بر می‌گرداند و همان طور که میدانید، به ازای هر شرطی که به برنامه اضافه میکنیم، پیچیدگی برنامه هم افزایش می‌یابد و کد خوانایی خود را از دست می‌دهد. تصور کنید دنیایی بدون NullReferenceException چه دنیایی زیبایی می‌بود؛ ولی متاسفانه این مورد از ویژگی‌های زبان #C است. خوشبختانه راه‌حل‌های برای حل NRE ارائه شده‌اند که در ادامه به آن‌ها می‌پردازیم.

ما می‌خواهیم متد GetById همیشه چیزی غیر از نال را برگرداند و یکی از راه‌هایی که ما را به این هدف می‌رساند این است که این متد یک توالی را برگرداند.

به نگاری جدید کد توجه بفرمایید:
public class UserService : IUserService
    {
        private IList<User> _userData;

        public UserService()
        {
            _userData = new List<User>
            {
                new User {Id = 1,Name = "ali"},
                new User {Id = 2,Name = "Karim"}
            };
        }

        public IEnumerable<User> GetById(int id)
        {
            var user = _userData.FirstOrDefault(x => x.Id == id);
            if (user == null) return new User[0];
            return new[] { user };
        }
    } 

اگر به امضای متد GetById توجه کنید، به جای اینکه User را برگرداند، این متد یک توالی از User را بر می‌گرداند و اگر در اینجا کاربری یافت شد، این توالی دارای یک المان خواهد بود و در غیر این صورت اگر User یافت نشد، این متد یک توالی را بر می‌گرداند که دارای هیچ المانی نیست. در ادامه اگر کلاینت بخواهد از متد GetById استفاده کند، به صورت زیر خواهد بود:

 public ActionResult Details(int id)
        {
            var user = _userService
                            .GetById(3)
                            .DefaultIfEmpty(new User())
                            .Single();
            return View(user);
        }

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

 در اول مقاله هم اشاره کردیم که  Maybe یا Options، مجموعه‌ای است که دارای یک المان و یا هیچ المانی است. اگر به امضای متد GetById توجه کنید، متوجه خواهید شد که این متد می‌تواند مجموعه‌ای را برگرداند و نمی‌تواند گارانتی کند که حتما مجموعه‌ای را بر می‌گرداند که دارای یک المان و یا هیچ باشد. برای حل این مشکل می‌توانیم از کلاس Option استفاده کنیم:

public class Option<T> : IEnumerable<T>
    {
        private readonly T[] _data;

        private Option(T[] data)
        {
            _data = data;
        }

        public static Option<T> Create(T element) => new Option<T>(new[] { element });

        public static Option<T> CreateEmpty() => new Option<T>(new T[0]);

        public IEnumerator<T> GetEnumerator() => ((IEnumerable<T>) _data).GetEnumerator();

        IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
    }

تنها دلیل استفاده از متد‌های Create و CreateEmpty این است که به خوانایی برنامه کمک کنیم؛ نه بیشتر. در ادامه اگر بخواهیم از کلاس option استفاده کنیم، به صورت زیر خواهد بود:

 public class UserService : IUserService
    {
       ...
       ...
       public Option<User> GetById(int id)
        {
            var user = _userData.FirstOrDefault(x => x.Id == id);
            return user == null ? Option<User>.CreateEmpty() : Option<User>.Create(user);
        }
    }

 public class UserController : Controller
    {
       ...
       ...
       public ActionResult Details(int id)
        {
            var user = _userService
                            .GetById(3)
                            .DefaultIfEmpty(new User())
                            .Single();
            return View(user);
        }
    }


چکیده:

مدیریت کردن References کار بسیار پیچیده‌ای است. قبل از آن که تلاش کنیم مقداری را برگردانیم و یا عملیاتی را بر روی آن انجام دهیم، اول باید مطمئن شویم که این شیء به جایی اشاره می‌کند. نمونه‌های متفاوتی از Option و یا Maybe را می‌توانید در اینترنت پیدا کنید که هدف نهایی آن‌ها، حذف NullReferenceException است و آشنایی با این ایده، شما را به دنیای برنامه نویسی تابعی در#C هدایت می‌کند.

نظرات مطالب
ساخت DropDownList های مرتبط به کمک jQuery Ajax در MVC
سلام
من از دو فیلد از 2 دیتابیس رو با دو dropdown نمایش دادم به صورت زیر:
 public ActionResult Create()
        {
           Models.category cat = new Models.category();
            List<SelectListItem> list = cat.GetList().Select(p => new SelectListItem { Text = p.category1, Value = p.ID.ToString() }).ToList();

            list[0].Selected = true;
            ViewData["Category1"] = list;

            Models.subcategory subcat = new Models.subcategory();


            List<SelectListItem> list1 = subcat.GetList().Select(p => new SelectListItem { Text = p.subcategory1, Value = p.ID.ToString() }).ToList();

            list1[0].Selected = true;
            ViewData["Category2"] = list1;
         
            return View();
        }
-------------------------razor view-----------------------------------------------
  <div>
          @{ List<SelectListItem> lstCategories = (List<SelectListItem>)ViewData["category1"]; }
            @Html.DropDownList("dbcat", lstCategories, new { id="dbcat" })
        </div>
        <div>
            @{ List<SelectListItem> lstsubCategories = (List<SelectListItem>)ViewData["Category2"]; }
            @Html.DropDownList("dbsubcat", lstsubCategories, new { id="dbsubcat"})
قسمت کنترلر برای ارتباط دو dropdownlist
 public ActionResult SelectCategory(int id)
        {

          
           studentDataContext  db= new studentDataContext();
            var subcat = db.subcategories.Where(m => m.ID == id).Select(c => new
            {
                c.ID,
                c.subcategory1
            });
            return Json(subcat, JsonRequestBehavior.AllowGet);
        }
وقسمت کد جی کوئری:
  <script src="~/Scripts/jquery-1.7.1.min.js"></script> 
<script type="text/javascript"> $('#dbcat').change(function () { jQuery.getJSON('@Url.Action("SelectCategory")', { id: $(this).attr('value') }, function (data) { $('#dbsubcat').empty(); jQuery.each(data, function (i) { var option = $('<option></option>') .attr("value", data[i].Id).text(data[i].Title); $("#dbcat").append(option); }); }); }); </script>

قسمت کد جی کوئری من اجرا نمیشه.حتی alert داخل

$('#dbcat').change(function ()
گذاشتم اجرا نشد.لطفا راهنمایی کنید
با تشکر