مطالب
آموزش LINQ بخش دوم
سبک‌های مختلف نوشتن Query در LINQ
تعریف Query:
عبارتی که اطلاعات را از منبع داده، بازیابی می‌کند، پرس و جو یا Query می‌گوییم. بطور کلی عملیات پرس و جو شامل سه بخش زیر می‌شود:
1- مشخص کردن منبع داده
2- ایجاد پرس و جو (Query)
3- اجرای پرس و جو
// The Three Parts of a LINQ Query:
//  1. منبع داده
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
// 2. ایجاد پرس و جو
// numQuery is an IEnumerable<int>
var numQuery =
    from num in numbers
    where (num % 2) == 0
    select num;
// 3. اجرای پرس و جو
foreach (int num in numQuery)
{
    Console.Write("{0,1} ", num);
}
شکل زیر توصیفی از کد‌های بالا می‌باشد :
 
دو سبک برای نوشتن عبارت‌های جستجو در LINQ وجود دارند :
 1- Fluent Style 
 2- Query Expression Style یا Query Syntax
سبک Fluent از متد‌های الحاقی برای عملیات پرس و جو استفاده می‌کند. در کلیه‌ی کدهای بخش اول این سری آموزشی از سبک Fluent استفاده شده است.
در کلاس‌های زیر متد‌های استاتیک مختلفی برای عملیات بر روی توالی‌ها ارائه شده‌اند:
 • System.Linq.Enumerable
 • System.Linq.Queryable
 • System.Linq.ParallelEnumarable
بطور کلی هر نمونه‌ای که اینترفیس <IEnumerable<Tsource را پیاده سازی کرده باشد می‌تواند از این متدهای الحاقی استفاده کند.
عملگرهای جستجو به دو صورت تکی و زنجیره‌ای برای ایجاد پرس و جو‌های پیچیده مورد استفاده قرار می‌گیرند.

پرس و جوی‌های زنجیره‌ای
در ابتدا کلاسی به نام Ingredient را به شکل زیر تعریف می‌کنیم (این کلاس نشان دهنده‌ی نام مواد غذایی و کالری آنهاست):
class Ingredient
{
    public string Name { get; set; }
    public int Calories { get; set; }
}
لیستی از مواد غذایی را ایجاد می‌کنیم:
Ingredient[] ingredients =
{
   new Ingredient {Name = "Suger", Calories = 500},
   new Ingredient {Name = "Egg", Calories = 100 },
   new Ingredient {Name = "Milk", Calories = 150 },
   new Ingredient {Name = "Flour", Calories = 50 },
   new Ingredient {Name = "Butter", Calories = 200 }
};
حال می‌خواهیم بصورت زنجیره‌ای از عملگر‌های پرس و جوی Where,OrderBy,Select استفاده کنیم:
Ingredient[] ingredients =
{
   new Ingredient {Name = "Suger", Calories = 500},
   new Ingredient {Name = "Egg", Calories = 100 },
   new Ingredient {Name = "Milk", Calories = 150 },
   new Ingredient {Name = "Flour", Calories = 50 },
   new Ingredient {Name = "Butter", Calories = 200 }
};

IEnumerable<string> highCalories =
ingredients.Where(x => x.Calories >= 150)
  .OrderBy(x => x.Name)
  .Select(x => x.Name);

foreach (var item in highCalories)
{
   Console.WriteLine(item);
}
خروجی کد بالا به شکل زیر است :
Butter
Milk
Suger
نمودار زیر نحوه‌ی عملکرد عملگرهای پرس و جو را نشان می‌دهد. هر عملگر بر روی توالی خروجی عملگر قبلی کار می‌کند. توجه کنید که توالی ورودی از نوع <IEnumerable<Ingredient می‌باشد و توالی خروجی تولید شده از نوع <IEnumerable<string است.
در این مثال عملگر‌های پرس و جو بر روی توالی ورودی عمل می‌کنند تا به دستور Select برسند. دستور Select هر عنصر را به یک رشته تبدیل می‌کند. این عملیات را Projection می‌گویند.











عبارت Lambda نوشته شده‌ی در بخش Select مشخص می‌کند که خروجی بر اساس چه خصوصیتی از توالی ورودی باشد. در اینجا نام عناصر به صورت رشته در خروجی ظاهر می‌شوند.


سبک Query Expression (عبارت‌های پرس و جو) 

Query Expression یک گرامر زیبا و روان برای نوشتن پرس و جو‌ها را ارائه می‌دهد. در مثال زیر از سبک Query Expression استفاده کرده‌ایم:

Ingredient[] ingredients =
{
    new Ingredient {Name = "Suger", Calories = 500},
    new Ingredient {Name = "Egg", Calories = 100},
    new Ingredient {Name = "Milk", Calories = 150},
    new Ingredient {Name = "Flour", Calories = 50},
    new Ingredient {Name = "Butter", Calories = 200}
};

IEnumerable<string> highCalories =
    from i in ingredients
    where i.Calories >= 150
    orderby i.Name
    select i.Name;

foreach (var item in highCalories)
{
    Console.WriteLine(item);
}

خروجی کد بالا با خروجی کد به سبک Fluent  یکسان است:

Butter
Milk
Suger

همانطور که می‌بینید ترتیب عملیات همانند روش قبل است. عبارت‌های پرس و جوی (from,where,orderby,select) به ترتیب با اصلاح توالی ورودی و تحویل آن به عبارت جستجوی بعدی کار را انجام می‌دهند.

عبارت جستجوی بالا با کلمه‌ی کلیدی from آغاز شده است. هدف from دو چیز است:

1- مشخص کردن توالی ورودی (منبع داده)

2- معرفی متغیر Range  (مشخص کردن عنصر مورد نظر در منبع داده)

متغیر Range همچون متغیر شمارنده در حلقه هاست. 


در ادامه این سری آموزشی درباره متغیر Range بصورت کاملتری بحث خواهیم کرد.   

مطالب
MongoDB #8
اجرای کوئری در سند MongoDB
متد ()find
برای اجرای یک کوئری نیاز دارید تا از متد ()find در MongoDB استفاه کنید.

گرامر:
گرامر پایه برای این متد به شکل زیر است:
>db.COLLECTION_NAME.find()
متد ()find تمام سندها را در یک حالت بدون ساختار نمایش می‌دهد.

متد ()Pretty
برای نمایش نتیجه، بصورت فرمت دهی شده و ساخت یافته می‌توانید از متد ()pretty استفاده کنید.
گرامر:
>db.mycol.find().pretty()
مثال:
>db.mycol.find().pretty()
{
   "_id": ObjectId(7df78ad8902c),
   "title": "MongoDB Overview", 
   "description": "MongoDB is no sql database",
   "by": "tutorials point",
   "url": "http://www.tutorialspoint.com",
   "tags": ["mongodb", "database", "NoSQL"],
   "likes": "100"
}
>
جدای از متد ()find، متد ()findOne نیز وجود دارد که فقط یک سند را برمی گرداند.

معادل‌های عبارت Where  در MongoDB
برای اجرای کوئری‌های بر اساس چندین شرط بر روی سندها می‌توانید از عملگرهای زیر استفاده کنید:
عملگر   گرامر  مثال  مشابه در پایگاه داده رابطه ای
Equality {<key>:<value>} ()db.mycol.find({"by":"tutorialspoint"}).pretty
' where by =  'tutorials point
 Less Than {<key>:{$lt:<value>}}  ()db.mycol.find({"likes":{$lt:50}}).pretty where likes < 50
Less Than  Equals
 {<key>:{$lte:<value>}} ()db.mycol.find({"likes":{$lte:50}}).pretty
where likes <= 50
 Greater Than  {<key>:{$gt:<value>}} ()db.mycol.find({"likes":{$gt:50}}).pretty
where likes > 50
Greater Than  Equals
 {<key>:{$gte:<value>}} ()db.mycol.find({"likes":{$gte:50}}).pretty
where likes >= 5 0
 Not Equals  {<key>:{$ne:<value>}} ()db.mycol.find({"likes":{$ne:50}}).pretty
where likes != 50

عبارت And در MongoDB
گرامر:
اگر چندین کلید را به متد ()find پاس دهید و آنها را با کاما (,) از هم جداکنید، MongoDB با آن‌ها مانند عبارت And رفتار می‌کند. گرامر پایه عبارت AND در جدول زیر نشان داده شده است:
>db.mycol.find({key1:value1, key2:value2}).pretty()
مثال:
در ادامه یک مثال آمده است که همه‌ی دوره‌های آموزشی که توسط 'tutorials point' ارائه شده‌اند و عنوان آنها 'MongoDB Overview’ است را نشان می‌دهد:
>db.mycol.find({"by":"tutorials point","title": "MongoDB Overview"}).pretty()
{
   "_id": ObjectId(7df78ad8902c),
   "title": "MongoDB Overview", 
   "description": "MongoDB is no sql database",
   "by": "tutorials point",
   "url": "http://www.tutorialspoint.com",
   "tags": ["mongodb", "database", "NoSQL"],
   "likes": "100"
}
>
برای مثال بالا، معادل عبارت Where آن ' where by='tutorials point' AND title='MongoDB Overview' خواهد بود. شما می‌توانید چندین جفت کلید-مقدار به عبارت find پاس دهید.

عبارت OR در MongoDB
گرامر:
برای اجرای کوئری‌های مبتنی بر عبارت OR روی سند نیاز دارید تا از کلمه‌ی کلیدی or$ استفاده کنید. گرامر پایه عبارت OR در زیر نشان داده شده است:
>db.mycol.find(
   {
      $or: [
     {key1: value1}, {key2:value2}
      ]
   }
).pretty()
مثال
در ادامه یک مثال آمده است که همه‌ی دوره‌های آموزشی را که توسط 'tutorials point' ارائه شده‌اند یا عنوان آنها 'MongoDB Overview’ است، نشان می‌دهد:
>db.mycol.find({$or:[{"by":"tutorials point"},{"title": "MongoDB Overview"}]}).pretty()
{
   "_id": ObjectId(7df78ad8902c),
   "title": "MongoDB Overview", 
   "description": "MongoDB is no sql database",
   "by": "tutorials point",
   "url": "http://www.tutorialspoint.com",
   "tags": ["mongodb", "database", "NoSQL"],
   "likes": "100"
}
>

استفاده از عبارات AND و OR باهم
مثال
در ادامه یک مثال آمده است که سندهایی را که مقدار فیلد likes آنها بیشتر از 100 و عنوان آنها برابر 'MongoDB Overview’ یا توسط 'tutorials point' ارائه شده‌اند، نشان خواهد داد. معادل عبارت Where آن برابر 'where likes>10 AND (by = 'tutorials point' OR title= 'MongoDB Overview’)’ است.
>db.mycol.find("likes": {$gt:10}, $or: [{"by": "tutorials point"}, {"title": "MongoDB Overview"}] }).pretty()
{
   "_id": ObjectId(7df78ad8902c),
   "title": "MongoDB Overview", 
   "description": "MongoDB is no sql database",
   "by": "tutorials point",
   "url": "http://www.tutorialspoint.com",
   "tags": ["mongodb", "database", "NoSQL"],
   "likes": "100"
}
>

مطالب
اعتبارسنجی در Entity framework Code first قسمت اول
در سری مباحث آموزشی EntityFramework وحیدی نصیری عزیز بصورت مختصر با اعتبار سنجی داده‌ها آشنا شدیم، در این آموزش سه قسمتی سعی می‌کنیم شناخت بیشتری از اعتبار سنجی داده در EF  بدست بیاریم. 
در EF CodeFirst بصورت پیش فرض پس از فراخوانی متد ()SaveChanges اعتبار سنجی داده‌ها انجام می‌پذیرد؛ در صورتیکه که اعتبار سنجی با موفقیت انجام نشود با استثنای DbEntityValidationException روبرو می‌شویم که در اینجا از خاصیت  EntityValidationErrors جهت اعلام خطاهای اعتبارسنجی استفاده می‌شود. EntityValidationErrors مجموعه‌ای از خطاهای مربوط به هر موجودیت می‌باشد  و هر EntityValidationErrors شامل یک خاصیت ValidationErrors که خود مجموعه‌ای از خطاهای مربوط به property‌ها می‌باشد. در تصویر زیر به خوبی می‌تونید این قضیه رو مشاهده کنید.


برای درک بهتر موضوع به ساختار کلاس‌های اعتبارسنجی در تصویر بعدی دقت کنید.

  • اعتبار سنجی در چه قسمت هایی اتفاق می‌افتد:
1.Property   
2.Entity
3.Context
الف - Property :
در بخش سوم آموزش EF Code First با متادیتای مورد استفاده در EF و طرز استفاده از آنها آشنا شدیم.
        [Required(ErrorMessage = "لطفا نام نویسنده را مشخص نمائید")]
        public string AuthorName { set; get; }

        [StringLength(100,MinimumLength=3,ErrorMessage="حداقل سه حرف و حداکثر 100 حرف وارد نمایید.")]
        public string AuthorName { set; get; }
همانطور که در ادامه می‌بینید برای اعتبار سنجی فقط به متادیتا‌های واقع در DataAnnotations.dll نیاز داریم. بقیه متادیتاها مربوط به نگاشت روابط موجودیتها و نحوه ذخیره اون در دیتابیس می‌باشد.
Validation Attributes
AssemblySystem.ComponentModel.DataAnnotations.dll
NamespaceSystem.ComponentModel.DataAnnotations
StringLength
RegularExpression
DataType
Required
Range
CustomValidation
Mapping Attributes
AssemblyEntityFramework.dll
NamespaceSystem.ComponentModel.DataAnnotations
Key
Column,Table
ComplexType
ConCurrency
TimeStamp
DatabaseGenerated
ForeignKey
InverseProperty
MaxLength
MinLength
NotMapped
ب- Entity  :
برای اعتبار سنجی یک موجودیت باید اینترفیس  IValidatableObject پیاده سازی شود:
public class Blog : IValidatableObject
    {
       
        public int blogID { set; get; }

        [Required(ErrorMessage = "لطفا عنوان وبلاگ را مشخص نمائید")]
        public string Title { set; get; }
        [Required(ErrorMessage = "لطفا نام نویسنده را مشخص نمائید")]
        [StringLength(100,MinimumLength=3,ErrorMessage="حداقل سه حرف و حداکثر 100 حرف وارد نمایید.")]
        public string AuthorName { set; get; }
    

        public IEnumerable<ValidationResult> Validate(ValidationContext ValidationContext)
        {
             if (this.AuthorName =="بدون نام")
                yield return new ValidationResult
                    ("این نام برای نام نویسنده مجاز نمی‌باشد.", new[] { "AuthorName"});

            if (this.AuthorName == this.Title)
                yield return new ValidationResult
                    (" نام نویسنده وبلاگ و عنوان وبلاگ نمی‌تواند همسان باشد.!", new[] { "AuthorName", "Title" });
        }
    }

نکته: در بررسی هم نام بودن نام نویسنده و  نام وبلاگ هردو خاصیت  ("AuthorName", "Title") رو درج کردیم اینکار باعث ایجاد دو خطای اعتبارسنجی می‌شود.

پ- Context  :
برای اعتبار سنجی در سطح Context  باید متد ()ValidateEntity واقع در کلاس DbContext را تحریف کنیم. این قسمت در بخش دوم مقاله کامل شرح داده خواهد شد.
  protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, System.Collections.Generic.IDictionary<object, object> items)
        {
            return base.ValidateEntity(entityEntry, items);
        }

نحوه فراخوانی اعتبار سنجی ها:
// اعتبار سنجی یک خاصیت
ICollection<DbValidationError> ValidationProperty = Context.Entry(Blog).Property(p => p.AuthorName).GetValidationErrors();

// اعتبار سنجی یک موجودیت
DbEntityValidationResult ValidationEntity = Context.Entry(Blog).GetValidationResult();

// اعتبار سنجی همه موجودیت‌ها
 IEnumerable<DbEntityValidationResult> ValidationContext = Context.GetValidationErrors();

نکته 
: در اعتبار  سنجی Context  بصورت پیش فرض فقط موجودیت‌های جدید و یا تغییر یافته اعتبار سنجی می‌شوند. 
EntityState.Added ||  EntityState.Modified

ترتیب فراخوانی اعتبار سنجی‌ها :
ابتدا اعتبار سنجی روی Property انجام می‌گیرد در صورتی که خطایی وجود نداشته باشد اعتبار سنجی مرحله بعد یعنی موجودیت‌ها بررسی می‌شود. اگر در مرحله اعتبار سنجی خاصیت‌ها خطایی وجود داشته باشد اعتبار سنجی موجودیت انجام نمی‌گیرد. ترتیب اعتبار سنجی در مرحله Context  بستگی به نحوه پیاده سازی ما دارد که در بخش دوم آموزش شرح داده خواهد شد.

سوال:
  1. اعتبار سنجی چند زبانی رو چگونه تعریف کنیم؟
  2. متد GetValidationErrors() رو در الگوی Repository , UOW  چگونه پیاده سازی کنیم؟
  3. آیا اعتبار سنجی در کنار موجودیت‌ها از نظر معماری چند لایه کار درستی می‌باشد؟ 
با پاسخ دادن به سوالات بالا در قالب نظر و یا مقاله به تکمیل موضوع کمک کنید و فضای آموزشی سایت رو رونق ببخشید.
مسیرراه‌ها
WPF
          نظرات اشتراک‌ها
          دوراهی انتخاب NHibernate و Entityframework
          استفاده از NH در مقابل EF Code first سورس باز اشتباه است؛ به دلایل زیر:
          - توهم پشتیبانی از بانک‌های اطلاعاتی مختلف توسط NH . به شخصه با حداقل یک مورد نیم بند آن سروکار داشتم: SQL-CE. تقریبا بیشتر از نیمی از توانایی‌های این بانک اطلاعاتی در NH لحاظ نشده و حتی یک کوئری ساده از تاریخ تا تاریخ را توسط آن نمی‌توانید تهیه کنید. این مورد برعکس EF Code first است. کامل و بی‌نقص کار می‌کند. کلا تمام محصولات مایکروسافت به همین نحو هستند. اگر عنوان می‌کنند این محصول دو قابلیت دارد، واقعا این دو قابلیت، درست کار می‌کنند. نه اینکه عنوان کنند 100 قابلیت را ارائه می‌دهیم و فقط 10 تای آن کامل پیاده سازی شده باشند.
          - تیم مدیریتی به شدت مغرور و ناراحت NH. باز هم برای این تیم ناراحت، جهت تکمیل نقایص کار با SQL-CE بیشتر از یکسال قبل وصله‌ای رو ارسال کردم. تا به امروز حتی یک پاسخ که آیا خوبه، بده ... ارسال نشده. با اکثر همکاری‌ها هم به همین نحو رفتار می‌کنند.
          خلاصه حال و هوای یک پروژه سالم سورس باز را ندارد.
          - پس از ارائه EF Code first این پروژه تقریبا غیرفعال شده: (^)
          - نیم بند بودن پشتیبانی از LINQ. باز هم اگر تصور می‌کنید که راحت می‌تونید مثل EF از کوئری‌های LINQ در اینجا استفاده کنید، سخت در اشتباه هستید.
          - دیر به روز شدن کتابخانه‌های جانبی آن. این مساله هم به مدیریت بد پروژه NH بر می‌گردد. شاید بیشتر از 10 مورد افزونه برای NH هست، مانند کش و اعتبار سنجی و غیره. اما ... صاحبان آن مشخص نیستند! امروز NH3 ارائه می‌شود، سه ماه بعد کتابخانه اعتبارسنجی متناظر با آن. تیم NH هم حاضر نشده تمام این‌ها رو کنار هم قرار بده و یک کار یکپارچه رو ارائه کنه. NH اعتبار خودش رو از این افزونه‌های موجود در NH Contrib کسب می‌کنه، اما حاضر نیستند مدیریت و نگهداری یکپارچه آن‌ها را قبول کنند.
          - ناسازگاری با اکوسیستم دات نت. اگر از NH استفاده کنید مدام در حال جنگ با دات نت هستید. مثلا سیستم اعتبار سنجی EF با سیستم اعتبار سنجی سمت کلاینت و سرور MVC یکپارچه است. با NH اینطور نیست و از این نوع مثال‌ها زیاد است. همین مساله حجم کاری شما را چندبرابر می‌کند.
          - طراحی زمخت NH در مقابل طراحی روان EF. برای مثال در EF Code first شما به ندرت نیاز خواهید داشت که نگاشت‌ها را تعریف یا حتی سفارشی سازی کنید. یک سری پیش فرض بسیار عالی در آن به صورت توکار (و نه به شکل افزونه) وجود دارد که حجم کاری شما را به شدت کاهش می‌دهند. در NH کتابخانه fluent nh سعی کرده که اینکار را انجام دهد اما جالب اینجا است که این کتابخانه از طرف تیم اصلی NH اصلا تحویل گرفته نشده و ... دست آخر هم یک روش دیگر را برای نوشتن نگاشت‌ها با کد تهیه کردند.
          - مستندات NH کامل نیست. برای مثال شاید یک سری بلاگ‌های متفرقه را پیدا کنید که در مورد روش تهیه نگاشت‌ها با کد مطلب نوشته باشند ... نه توسط کسانی که این کتابخانه را تهیه کرده‌اند! این روند رو مقایسه کنید با وبلاگ EF مثلا : (^) این بلاگ تا این حد کامل است که مرجع بسیاری از مطالب آموزشی و کتاب‌های مرتبط با EF می‌باشد.
          - سیستم migration موجود در EF Code first نسبت به نمونه NH بسیار کاملتر است؛ با قابلیت سفارشی سازی، مقایسه هش مدل‌ها با جداول جهت جلوگیری از تداخلات و اشتباهات، تولید اسکریپت آپدیت بانک اطلاعاتی و غیره.

          یک زمانی بود دات نت ORM قابل ملاحظه‌ای نداشت. زمان دات نت2. در آن موقع NH حرف برای گفتن داشت اما ... نه الان.
          اشتراک‌ها
          پلتفرم خودکار یک پلتفرم رایگان و متن باز (Open Source) برای تولید نرم افزار تحت وب با تکنولوژی مایکروسافت
          پلتفرم خودکار یه پروژه متن بازه و ایده اصلی اش تولید یک نرم افزار تحت وب از صفر تا صد به صورت آنلاین و بدون نیاز به ابزار هایی مثل ویژوال استدیو Sql Management Studio و TFS  و غیره و تنها با یک مرورگر ساده مثل Chrome .


          پلتفرم خودکار  همانند ویژوال استدیو دو حالت Release و دیباگ دارد که این امکان را به برنامه نویسان می‌دهد که کدهای اجرایی در سمت سرور و کلاینت در دو حالت دیباگ و Release کاملا مختلف و مجزا باشند.

          یعنی شما برای ساخت یک وب سایت می‌تونید تمام کدهای سمت سرور و کلاینت و دیتابیس رو از طریق یک مرورگر وب بنویسید و اگه نیاز به کامپایل باشه , خود پلتفرم این کار رو انجام میده.
          تعدادی از این کدها : C# VB.Net SQL CSS JavaScript SASS LESS Coffee و غیره

          اما غیر از اینها پلتفرم خودکار شامل یه سورس کنترل و مدیریت ورژن و Build System و Load Module  اختصاصی هم میشه .یعتی عملا شما نیازی به سورس کنترل‌های آنلاین
          مثل GitHub , ... را ندارید و می‌تونید دسترسی ویرایش و یا Build و یا Test و یا اجرا رو در سطح یک خط کد تا یک پروژه به طور کامل به سایر برنامه نویسان بدهید.

          برای طراحی و ساخت دیتابیس تون و مدیریت Migration‌‌ها هم یک ابزار انلاین داره که پشت صحنه از Entity FrameWork استفاده می‌کنه و تمامی امکانات Entity FrameWork   برای ساخت و پشتیبانی دیتابیس رو به صورت آنلاین در اختیار شما می‌زاره.

          وابسته به فریم ورک خاصی در سمت کلاینت نیست .ولی پیش فرض اش JQUERY و بوت استرپ استفاده می‌کنه. شما می‌تونید N تا فریم ورک و قالب متفاوت تعریف کنید , به طوری که برای مثال یه صفحه وبسایتتون با React و صفحه دیگه با انگولار باشه .

          برای دیباگ تحت وب هم امکاناتی در اختیار برنامه نویس قرار می‌ده مثل ریموت دیباگ و یا دیباگ در ویژوال استدیو.این‌ها بخشی از امکانات پلتفرم خودکاره برای آشنایی بیشتر با امکانات پلتفرم از لینک‌های زیر استفاده کنید.

          حدود 70 ساعت آموزش در آپارات  :


          خودم تا حالا دو تا وبسایت باهاش نوشتم و البته چند تا دیگه هم در دست توسعه است. وبسایت های کارشناسان.نت با قالب بوت استرپ و jquery  نوشته شده و داستان موفقیت با قالب Material و jquer نوشته شده است.

          دوستان عزیز قصد دارم ورژن core پلتفرم خودکار  رو بنویسم و یه سری امکانات جدید مثل کامپایلر و BuildSystem ری اکت رو اضافه کنم و هوش مصنوعی IDE رو هم افزایش بدم. اگر علاقه مند به همکاری هستید برام پیام بذارید.

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

          پلتفرم خودکار یک پلتفرم رایگان و متن باز (Open Source) برای تولید نرم افزار تحت وب با تکنولوژی مایکروسافت
          نظرات مطالب
          توسعه برنامه های Cross Platform با Xamarin Forms & Bit Framework - قسمت سوم
          صحبت شما درسته. در اکثر آموزش‌های Xamarin اعم از زبان اصلی یا فارسی نیز همین روش استفاده شده. ولی تجربه ای که من داشتم این بوده، فرد مطلب رو که دقیقا و به درستی Step by step بوده رو می‌خونه، بعد می‌ره و

          ۱- موقع نصب به مشکل بر می‌خوره.
          ۲- اولین پروژه رو حتی نمی‌تونه بیلد کنه!
          ۳- نصب می‌کنه، بیلد هم می‌کنه، بعد هر بار که کد رو تغییر می‌ده می‌بینه که چقدر کنده و کلی طول می‌کشه نتیجه تغییرش رو ببینه.
          ۴- به زحمت فرمی رو توسعه می‌ده و بعد پابلیش می‌کنه و بعد می‌بینه حجم Apk شده ۳۰ مگ!
          در هر یک از این چهار مورد ما ریزش افرادی رو داریم که می‌خوان با Xamarin کار کنن، چون CSharp کار هستن و دوست دارن CSharp رو. ولی با این مشکلات فراری می‌شن.
          من تو آموزش ام صریحا می‌گم که مثلا "در مورد Xaml نیز بعد از راه اندازی این مثال در Windows-Android-iOS صحبت خواهیم کرد."
          چرا که می‌خوام اول ببینه نصب اش احتیاج به ۲۵ گیگ دانلود نداره، و اگه داره بیش از ۵ گیگ می‌گیره اشکال داره تنظیمات نصب اش. می‌خوام ببینه که اولین پروژه رو می‌تونه به راحتی بیلد کنه. می‌خوام ببینه که Edit & continue داره و ارزش داره کارش روی UWP، حتی اگه مشتری اش فقط ازش درخواست نسخه Android / iOS کرده. تو قسمت بعدی هم می‌خوام ببینه که با ۷ مگ هم می‌تونه خروجی Apk داشته باشه. و بعد ببینه که روی iOS هم می‌تونه تست کنه. از این مرحله به بعد شاید به آموزش‌های من هم احتیاج نداشته باشه، کلی آموزش خوب برای Xaml و Prism و MVVM و CSharp هست.
          من انتظارم اینه که فرد مبتدی بتونه فقط Text اون دکمه رو از + به - تغییر بده و دستور CSharp رو هم در حد یه خط عوض کنه. همین!
          مثال ام رو هم دقیقا از صفحه اول Flutter کپی کردم. Flutter هم در صفحه اول اش نمی‌گه که Widget چیه و BuildContent چیه و Scaffold چیه. فقط می‌خواد نشون بده خیلی راحت می‌شه باهاش کد زد و یه جورایی بگه خیالت راحت.
          من تو آموزش نگفتم که کد رو به Template پیش فرض Xamarin اضافه کنید، بلکه یه پروژه آماده به اجرا رو از GitHub درخواست کردم که Clone کنید و دو خط اش رو تغییر بدید. وگرنه حتی درک Template پیش فرض خود Xamarin forms هم احتیاج به توضیح داره برای فرد مبتندی و ساختار ساده ای نداره.
          بعد از راه اندازی Android / iOS به آموزشی که شما گفتید بر می‌گردم و شروع می‌کنم می‌گم Layout‌ها چی هستن، Control‌‌ها چی هستن، View Model چیه، به سرور چجوری وصل بشیم، Entity framework core رو چجوری استفاده کنیم و از کنترل‌های Syncfusion چجوری استفاده کنیم و ... Step by step، ولی می‌دونیم که دیگه همه می‌تونن تست کنن و ته دلشون نمی‌لرزه و شاکی نیستن از این که چرا اون کنده و چرا اون سایزش زیاده و ...
          ممنون از این که این دوره رو پیگیری می‌کنید. من واقعا بابت نقد مودبانه تون ممنونم (: الآن هم اگه مشکلی تو اجرا دیدید بگید که من نکته اش رو اضافه کنم. این موردی که توضیح دادم رو سعی کردم در متن آموزش کمی Bold کنم.
          نظرات مطالب
          Ajax.BeginForm و ارسال فایل به سرور در ASP.NET MVC
          با سلام
          ما مطابق آموزشی که در این مقاله داده شده  از یک اکشن متد برای ذخیره عکس ارسالی تو یک پوشه و سپس برگشت دادن مسیر عکس و از یک اکشن متد دیگه برای ذخیره اطلاعاتی که قراره همراه با فرم ارسال بشن (به همراه مسیر عکس برگشت داده شده)، استفاده میکنیم
          مشکلی که ما موقع استفاده از این افزونه باهاش برخوردیم اینه که گاهی اوقات و همونطور که انتظار میره اکشن متد (AddAvatars) که وظیفه ذخیره عکس رو داره اول اجرا میشه و اکشن متد (Add) که وظیفه ذخیره اطلاعات رو داره دوم، ولی گاهی اوقات این ترتیب به هم میریزه و ابتدا اطلاعات ارسالی ذخیره میشه و بعد اکشن متد ذخیره عکس اجرا میشه.
          سناریوی ما هم تا حدی شبیه به سناریویی هست که آقای احمدی مطرح کردند، ولی همونطور که گفتیم مشکل اصلی اینه که اکشن متدها هر بار با ترتیب‌های متفاوت فراخوانی میشن
          <div class="container-fluid">
              @using (Ajax.BeginForm("Add", "Authors", new AjaxOptions { UpdateTargetId = "result", InsertionMode = InsertionMode.Replace, HttpMethod = "POST" }, new { @class = "form-horizontal", id = "UploadFile" }))
              {
                  @Html.AntiForgeryToken()
                          
                  <div class="control-group">
                      <label class="control-label" for="AuhtorFirstNameAndLastName">نام نویسنده</label>
                      <div class="controls">
                          @Html.TextBoxFor(author => author.AuhtorFirstNameAndLastName, new { placeholder = "نام نویسنده" })
                      </div>
                      @Html.ValidationMessageFor(author => author.AuhtorFirstNameAndLastName)
                  </div>
                
                  <div class="control-group">
                      <label class="control-label" for="Status">ارسال عکس</label>
                      <div class="controls">
                          <input type="file" name="avatarFile" id="avatarFile" />
                      </div>
                      <div>
                          @*<input type="submit" name="btn-submit" value="ارسال" class="btn btn-success" />*@
                          <img id="loading" alt="1" src="Images/loading83.gif" style="display: none;" />
                      </div>
                  </div>
                 
                  <div id="result"></div>
                  <input type="submit" name="btn-submit" value="افزودن نویسنده" class="btn btn-success" />
                  <input type="button" name="btn-colose" id="btn-close" value="انصراف" class="btn btn-danger" onclick="$dialog.dialog('close');" />
              }
          </div>
          
          <script type="text/javascript">
                  $('#UploadFile').submit(function () {
                      $("#loading").show();
                      $.ajaxFileUpload({
                          url: "@Url.Action("AddAvatar","Authors")",
                           secureuri: false,
                           fileElementId: 'avatarFile',
                           dataType: 'json',
                           data: {}, 
                           success: function (data, status) {
                               $("#loading").hide();
                           },
                           error: function (data, status, e) {
                               $("#loading").hide();
                           }
                       });
                   });
          </script>
          نظرات مطالب
          آناتومی یک گزارش خطای خوب
          سلام،
          برای دوستانی که انگلیسیشون زیاد خوب نیست (مثل خودم) و کلا با انگلیسی مشکل دارن، جهت سرچ در گوگل روش زیر پیشنهاد می‌گردد.
          معمولا بهتره توی گوگل مشکلتون رو اینطوری سرچ کنین :
          how to <doing problem>   in <your programming language>
          مثال:
          how to convert int to string in c#
          این روش هم خوبه :
          <programming language> how <problem>
          دو روش فوق معمولا در 90% موارد جواب میده.

          نکته دوم اینه که اگر توی نتیجه سرچ لینکی از سایت StackOverFlow دیدین ، اول بهتره اون لینک رو باز کنین.
          چون معمولا این سایت بصورت سوال و جوابه و سریع با دیدن کد‌های نمونه ای که در پاسخ‌ها موجوده مشکلتون حل میشه و معمولا اصلا نیاز نیست متون انگلیسی رو بخونین.
          مخصوصا که برای هر پاسخ یک امتیاز وجود داره که با بررسی امتیاز هر پاسخ می‌توان تا حدودی به درست بودن و بهینه بودن راه حل پی برد (این مورد حدودی است)

          البته سایت codeProject هم خوب است ولی تا جایی که من می‌دونم بصورت مقاله ای است و باید کلی توضیح و مثال و ... رو بررسی کنین تا به جواب سوالتون برسین که یکم وقت گیر تره ...

          نکته بعدی: بد نیست برخی مشکلات رو بصورت فارسی هم سرچ بگیرین ، در برخی موارد مطلب فارسی هم در مورد برخی خطاها پیدا میشه (معمولا فارسی زبونا زیاد مقاله درباره خطاها نمی‌نویسن و بیشتر تکنولوژی رو آموزش میدن ...)

          {البته همه دوستان حرفه ای هستند ، به جهت دوستانی که مثل خودم زیاد با انگلیسی میونه خوبی ندارند عرض کردم}  

          ضمنا در تکمیل مقاله آقای نصیری باید ذکر کنم که :
          *همیشه به خاطر داشته باشید که هیچکس علمشو مجانی بدست نیاورده که مجانی در اختیار شما قرار بده !
          پس اگر کسی داره مقاله منتشر می‌کنه یا جواب سوالتونو میده ، داره به شما لطف می‌کنه...
          پس سعی کنین همیشه ازش تشکر کنین و بهش احترام بذارین تا بیشتر تشویق بشه که مطالب بیشتری بذاره ... (به نظر من دست کسی که مجانی داره بهت چیز یاد میده ، باید بوسید؛ چون در حقیقت وقت و انرژی و علمشو داره به شما هدیه می‌کنه که خیلی ارزشمنده)

          *نوشتن کامنت هایی که دانش نفر رو زیر سوال ببره ، مثلا "این روش که دیگه خدا بیامرز شده ، الان هر برنامه نویس حرفه ای از فلان روش استفاده می‌کنه" خیلی بده و نفر رو نا امید می‌کنه.

          *لحن گفتن یک سوال یا بیان یک کامنت خیلی خیلی مهمه.
          مثلا همین مقال بالا رو میشه بدین صورت هم گفت : "در تکمیل مقاله جناب X باید ذکر نمایم که روش Y نیز بسیار جالب می‌باشد و دارای کد نویسی بهتری است" و حتی یک لینک آموزشی خوب هم درباره روش جدید ارائه دهیم.
          (اینطوری هر دو طرف سود میکنن)

          همین!
          موفق باشید.
          نظرات مطالب
          Senior Developer به چه کسی گفته می شود؟
          توضیح خوبی بود، ولی از بین تمام این مطالب این قسمت از نظر شما به دلم نشست:
          در ضمن هنگام تهیه و مطالعه رزومه باید به عناوین تسلط و آشنایی و آگاهی دقت لازم را داشته باشیم. 
          خیلی از افراد کفر آدم رو در می‌آرن، ردیف کرده کلی تخصص حتی بدون تفکیک و شاخه بندی. جالب اینه که در همه زمینه‌ها هم اصطلاح تسلط رو به کار برده. من خودم به شخصه تسلط بر یک مبحث رو خیلی اصطلاح سنگین و دشواری میبینم. چون واقعا برای شایسته این اصطلاح بودن باید در سطح آگاهی و آشنایی نباشیم، باید در سطحی باشیم که چندین و چند بار از این اطلاعات و آگاهی‌ها در عمل استفاده کرده باشیم. به نظر من کلاس‌های آموزشی و مطالعه کتاب و بسیاری از موارد دیگر تنها ما رو به سطح آشنایی می‌رسانند ولی بدون استفاده عملی و کاربردی از اطلاعات در همین سطح باقی میمونیم و به تسلط بر آن موضوع دست پیدا نمی‌کنیم.
          با این تفاسیر متاسفانه کارفرمایان بین این واژه‌ها تفاوت چندانی قائل نمیشوند و بیشتر به اصطلاحات دهن پر کن توجه میکنند که البته در طولانی مدت هم با مشکل مواجه خواهند شد.
          بگذارید با یک مثال ملموس این قضیه رو روشن کنم:
          یادتون بیارید زمانی که تازه با کامپیوتر آشنا شدید، نصب نرم افزارهای کاربردی کوچک همیشه برای شما سورپرایزی داشته اند یعنی ممکنه برای نصب بعضی از نرم افزارها با مشکل مواجه شده باشید، شما در اینترنت و یا کتاب به دنبال راه حلی برای نصب آن نرم افزار بودید، تا اینجا در مرحله آگاهی قرار دارید، یعنی می‌دانید که نصب نرم افزار فرایندی بدون خطا نیست، شاید یه جاهایی با مشکل مواجه بشید که به راحتی نتونید حل کنید.
          بعد از مدتی که این روند تکرار میشه آگاهی‌های شما تعمیم پیدا میکنه و به سطح آشنایی میرسه، دیگه نصب نرم افزار‌ها برای شما استرس و مشکلات پیش بینی نشده ای نداره. شما اکنون در مرحله آشنایی هستید.
          الان در چه مرحله ای هستید؟ یقینا در سطح تسلط هستید، امکان نداره نصب مشکلترین نرم افزارها الان برای شما در بدترین حالت بیشتر از 1 ساعت طول بکشه. دیگه حتی به حدی رسیدید که دکمه Next‌و پذیرفتن لایسنز و محل نصب نرم افزار و ... جز روتین کار شده و مکثی روی این موارد ندارید.
          شما الان می‌تونید بگید که من به نصب نرم افزارها تسلط کامل دارم.
          آیا در زمینه Design pattern‌ها هم به همین صورت هستید؟ آیا در زمینه آزمایش واحد هم به همین صورت هستید؟ آیا استفاده از فلان الگوی طراحی به اندازه استفاده از حلقه For و کاربردش در ذهنتون قرار گرفته؟ آیا به اندازه با الگوی‌های طراحی کار کردید که در موقعیت‌های خاص ناخوداگاه به یاد استفاده از فلان الگوی طراحی بیفتید؟
          اگر پاسخ این سولات مثبته شما واقعا به الگوی‌های طراحی مسلط هستید؟
          اگر نیاز به کمی مکث و آزمون و خطا دارید، شما به الگوی‌های طراحی آشنا هستید؟
          اگر فقط می‌دونید که برای فلان مسئله الگوی طراحی کاربرد داره و بتونید فلان کد رو که از الگوی طراحی استفاده کرده تا حدودی تحلیل کنید،‌شما به الگوی‌های طراحی آگاهی دارید.

          پس به قول آقای پاکدل بین این سه مفهوم لطفا تفاوت قائل بشید.