اشتراک‌ها
مصاحبه کامل با خالق ++C

Full Interview With the Creator of C++

By popular demand, and a request from the man himself, we’ve decided to release the full interview with esteemed computer scientist Bjarne Stroustrup (aka the creator of C++). We cover a bunch of topics so check the chapters to find what interests you the most! Filmed last year. Enjoy and happy trails!

00:00-02:42 Getting into programming
02:42-03:26 Programming being versatile
03:26-06:07 Industry changes
06:07-10:20 Inventing and maintaining C++
10:20-12:02 Key to making a successful language
12:02-16:04 Greatest lessons
16:14-20:06 Moving to the US
20:06-23:20 Advice to devs 

مصاحبه کامل با خالق ++C
مطالب
مدیریت درخواست‌های شرطی در ASP.NET MVC
فرض کنید کنید هدرهای کش کردن عناصر پویا و یا ثابت سایت را برای مدتی مشخص تنظیم کرده‌اید.
سؤال: مرورگر چه زمانی از کش محلی خودش استفاده خواهد کرد (بدون ارسال درخواستی به سرور) و چه زمانی مجددا از سرور درخواست دریافت مجدد این عنصر کش شده را می‌کند؟
برای پاسخ دادن به این سؤال نیاز است با مفهومی به نام Conditional Requests (درخواست‌های شرطی) آشنا شد که در ادامه به بررسی آن خواهیم پرداخت.


درخواست‌های شرطی

مرورگرهای وب دو نوع درخواست شرطی و غیر شرطی را توسط پروتکل HTTP و HTTPS ارسال می‌کنند. دراینجا، زمانی یک درخواست غیرشرطی ارسال می‌شود که نسخه‌ی ذخیره شده‌ی محلی منبع مورد نظر، مهیا نباشد. در این حالت، اگر منبع درخواستی در سرور موجود باشد، در پاسخ ارسالی خود وضعیت 200 یا HTTP/200 OK را باز می‌گرداند. اگر هدرهای دیگری نیز مانند کش کردن منبع در اینجا تنظیم شده باشند، مرورگر نتیجه‌ی دریافتی را برای استفاده‌ی بعدی ذخیره خواهد کرد.
در بار دومی که منبع مفروضی درخواست می‌گردد، مرورگر ابتدا به کش محلی خود نگاه خواهد کرد. همچنین در این حالت نیاز دارد که بداند این کش معتبر است یا خیر؟ برای بررسی این مورد ابتدا هدرهای ذخیره شده به همراه منبع، بررسی می‌شوند. پس از این بررسی اگر مرورگر به این نتیجه برسد که کش محلی معتبر است، دیگر درخواستی را به سرور ارسال نخواهد کرد.
اما در آینده اگر مدت زمان کش شدن تنظیم شده توسط هدرهای مرتبط، منقضی شده باشد (برای مثال با توجه به max-age هدر کش شدن منبع)، مرورگر هنوز هم درخواست کاملی را برای دریافت نسخه‌ی جدید منبع مورد نیاز، به سرور ارسال نمی‌کند. در اینجا ابتدا یک conditional request را به وب سرور ارسال می‌کند (یک درخواست شرطی). این درخواست شرطی تنها دارای هدرهای If-Modified-Since و یا If-None-Match است و هدف از آن سؤال پرسیدن از وب سرور است که آیا این منبع خاص، در سمت سرور اخیرا تغییر کرده‌است یا خیر؟ اگر پاسخ سرور خیر باشد، باز هم از همان کش محلی استفاده خواهد شد و مجددا درخواست کاملی برای دریافت نمونه‌ی جدیدتر منبع مورد نیاز، به سرور ارسال نمی‌گردد.
پاسخی که سرور جهت مشخص سازی عدم تغییر منابع خود ارسال می‌کند، با هدر HTTP/304 Not Modified مشخص می‌گردد (این پاسخ هیچ body خاصی نداشته و فقط یک سری هدر است). اما اگر منبع درخواستی اخیرا تغییر کرده باشد، پاسخ HTTP/200 OK را در هدر بازگشت داده شده، به مرورگر بازخواهد گرداند (یعنی محتوا را مجددا دریافت کن).


چه زمانی مرورگر درخواست‌های شرطی If-Modified-Since را به سرور ارسال می‌کند؟

اگر یکی از شرایط ذیل برقرار باشد، مرورگر حتی اگر تاریخ کش شدن منبع ویژه‌ای به 10 سال بعد تنظیم شده باشد، مجددا یک درخواست شرطی را برای بررسی اعتبار کش محلی خود به سرور ارسال می‌کند:
الف) کش شدن بر اساس هدر خاصی به نام vary صورت گرفته‌است (برای مثال بر اساس id یا نام یک فایل).
ب) اگر نحوه‌ی هدایت به صفحه‌ی جاری از طریق META REFRESH باشد.
ج) اگر از طریق کدهای جاوا اسکریپتی، دستور reload صفحه صادر شود.
د) اگر کاربر دکمه‌ی refresh را فشار دهد.
ه) اگر قسمتی از صفحه توسط پروتکل HTTP و قسمتی دیگر از آن توسط پروتکل HTTPS ارائه شود.
و ... اگر بر اساس هدر تاریخ مدت زمان کش شدن منبع، زمان منقضی شدن آن فرا رسیده باشد.


مدیریت درخواست‌های شرطی در ASP.NET MVC

تا اینجا به این نکته رسیدیم که قرار دادن ویژگی Output cache بر روی یک اکشن متد، الزاما به معنای کش شدن آن تا مدت زمان تعیین شده نخواهد بود و مرورگر ممکن است (در یکی از 6 حالت ذکر شده فوق) توسط ارسال هدر If-Modified-Since ، سعی در تعیین اعتبار کش محلی خود کند و اگر پاسخ 304 را از سرور دریافت نکند، حتما نسبت به دریافت مجدد و کامل آن منبع اقدام خواهد کرد.
سؤال: چگونه می‌توان هدر If-Modified-Since را در ASP.NET MVC مدیریت کرد؟
پاسخ: اگر از فیلتر OutputCache استفاده می‌کنید، به صورت خودکار هدر Last-Modified را اضافه می‌کند؛ اما این مورد کافی نیست.
در ادامه یک کنترلر و اکشن متد GetImage آن‌را ملاحظه می‌کنید که تصویری را از مسیر app_data/images خوانده و بازگشت می‌دهد. همچنین این تصویر بازگشت داده شده را نیز با توجه به OutputCache آن به مدت یک ماه کش می‌کند.
using System.IO;
using System.Web.Mvc;

namespace MVC4Basic.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        const int AMonth = 30 * 86400;

        [OutputCache(Duration = AMonth, VaryByParam = "name")]
        public ActionResult GetImage(string name)
        {
            name = Path.GetFileName(name);
            var path = Server.MapPath(string.Format("~/app_data/images/{0}", name));
            var content = System.IO.File.ReadAllBytes(path);
            return File(content, "image/png", name);
        }
    }
}
با این View که تصویر خود را توسط اکشن متد GetImage تهیه می‌کند:
 <img src="@Url.Action("GetImage","Home", new { name = "test.png"})"/>
در سطر اول متد GetImage، یک break point قرار دهید و سپس برنامه را توسط VS.NET اجرا کنید.
بار اول که صفحه‌ی اول برنامه درخواست می‌شود، یک چنین هدرهایی رد و بدل خواهند شد (توسط ابزار‌های توکار مرورگر وب کروم تهیه شده‌‌است؛ همان دکمه‌ی F12 معروف):
 Remote Address:127.0.0.1:5656
Request URL:http://localhost:10419/Home/GetImage?name=test.png
Request Method:GET
Status Code:200 OK

Response Headers
Cache-Control:public, max-age=2591916
Expires:Sat, 31 May 2014 12:45:55 GMT
Last-Modified:Thu, 01 May 2014 12:45:55 GMT
چون status code آن مساوی 200 است، بنابراین دریافت کامل فایل صورت خواهد گرفت. فیلتر OutputCache نیز مواردی مانند Cache-Control، Expires و Last-Modified را اضافه کرده‌است.

در همین حال اگر صفحه را ریفرش کنیم (فشردن دکمه‌ی F5)، اینبار هدرهای حاصل چنین شکلی را پیدا می‌کنند:
 Remote Address:127.0.0.1:5656
Request URL:http://localhost:10419/Home/GetImage?name=test.png
Request Method:GET
Status Code:304 Not Modified

Request Headers
If-Modified-Since:Thu, 01 May 2014 12:45:55 GMT
در اینجا چون یکی از حالات صدور درخواست‌های شرطی (ریفرش صفحه) رخداده است، هدر If-Modified-Since نیز در درخواست حضور دارد. پاسخ آن از طرف وب سرور (و نه برنامه؛ چون اصلا متد کش شده‌ی GetImage دیگر اجرا نخواهد شد و به break point داخل آن نخواهیم رسید)، 304 یا تغییر نکرده‌است. بنابراین مرورگر مجددا درخواست دریافت کامل فایل را نخواهد داد.

در ادامه بجای اینکه صفحه را ریفرش کنیم، یکبار دیگر در نوار آدرس آن، دکمه‌ی Enter را فشار خواهیم داد تا آدرس موجود در آن (ریشه سایت) مجددا در حالت معمولی دریافت شود.
 Remote Address:127.0.0.1:5656
Request URL:http://localhost:10419/Home/GetImage?name=test.png
Request Method:GET
Status Code:200 OK (from cache)
همانطور که ملاحظه می‌کنید اینبار پاسخ نمایش داده شده 200 است اما در ادامه‌ی آن ذکر شده‌است from cache. یعنی درخواستی را به سرور برای دریافت فایل ارسال نکرده است. عدم رسیدن به break point داخل متد GetImage نیز مؤید آن است.

مشکل! مرورگر را ببندید، تا کار دیباگ برنامه خاتمه یابد. مجددا برنامه را اجرا کنید. مشاهده خواهید کرد که ... اجرای برنامه در Break point قرار گرفته در سطر اول متد GetImage متوقف می‌شود. چرا؟! مگر قرار نبود تا یک ماه دیگر کش شود؟! هدر رد و بدل شده نیز Status Code:200 OK کامل است (که سبب دریافت کامل فایل می‌شود).
 Remote Address:127.0.0.1:5656
Request URL:http://localhost:10419/Home/GetImage?name=test.png
Request Method:GET
Status Code:200 OK

Request Headers
If-Modified-Since:Thu, 01 May 2014 12:45:55 GMT
راه حل: هدر If-Modified-Since را باید برای اولین بار فراخوانی اکشن متدی که حاصل آن نیاز است کش شود، خودمان و به صورت دستی مدیریت کنیم (فیلتر OutputCache این‌کار را انجام نمی‌دهد). به نحو ذیل:
using System;
using System.IO;
using System.Net;
using System.Web.Mvc;

namespace MVC4Basic.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        const int AMonth = 30 * 86400;

        [OutputCache(Duration = AMonth, VaryByParam = "name")]
        public ActionResult GetImage(string name)
        {
            name = Path.GetFileName(name);
            var path = Server.MapPath(string.Format("~/app_data/images/{0}", name));

            var lastWriteTime = System.IO.File.GetLastWriteTime(path);
            this.Response.Cache.SetLastModified(lastWriteTime.ToUniversalTime());

            var header = this.Request.Headers["If-Modified-Since"];
            if (!string.IsNullOrWhiteSpace(header))
            {
                DateTime isModifiedSince;
                if (DateTime.TryParse(header, out isModifiedSince) && isModifiedSince > lastWriteTime)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.NotModified);
                }
            }

            var content = System.IO.File.ReadAllBytes(path);
            return File(content, "image/png", name);
        }
    }
}
در این حالت اگر مرورگر هدر If-Modified-Since را ارسال کرد، یعنی آدرس درخواستی هم اکنون در کش آن موجود است؛ فقط نیاز دارد تا شما پاسخ دهید که آیا آخرین تاریخ تغییر فایل درخواستی، از زمان آخرین درخواست صورت گرفته از سایت شما، تغییری کرده‌است یا خیر؟ اگر خیر، فقط کافی است 304 یا HttpStatusCode.NotModified را بازگشت دهید (بدون نیاز به بازگشت اصل فایل).
برای امتحان آن همانطور که عنوان شد فقط کافی است یکبار مرورگر خود را کاملا بسته و مجددا برنامه را اجرا کنید.
 Remote Address:127.0.0.1:5656
Request URL:http://localhost:10419/Home/GetImage?name=test.png
Request Method:GET
Status Code:304 Not Modified

Request Headers
If-Modified-Since:Thu, 01 May 2014 13:43:32 GMT

موارد کاربرد
اکثر فید خوان‌های معروف نیز ابتدا هدر If-Modified-Since  را ارسال می‌کنند و سپس (اگر چیزی تغییر کرده بود) محتوای فید شما را دریافت خواهند کرد. بنابراین برای کاهش بار برنامه و هچنین کاهش میزان انتقال دیتای سایت، مدیریت آن در حین ارائه محتوای پویای فیدها نیز بهتر است صورت گیرد. همچنین هر جایی که قرار است فایلی به صورت پویا به کاربران ارائه شود؛ مانند مثال فوق.


تبدیل این کدها به روش سازگار با ASP.NET MVC

ما در اینجا رسیدیم به یک سری کد تکراری if و else که باید در هر اکشن متدی که OutputCache دارد، تکرار شود. روش AOP وار آن در ASP.NET MVC، تبدیل این کدها به یک فیلتر با قابلیت استفاده‌ی مجدد است:
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public sealed class SetIfModifiedSinceAttribute : ActionFilterAttribute
    {
        public string Parameter { set; get; }
        public string BasePath { set; get; }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var response = filterContext.RequestContext.HttpContext.Response;
            var request = filterContext.RequestContext.HttpContext.Request;

            var path = getPath(filterContext);
            if (string.IsNullOrWhiteSpace(path))
            {
                response.StatusCode = (int)HttpStatusCode.NotFound;
                filterContext.Result = new EmptyResult();
                return;
            }

            var lastWriteTime = File.GetLastWriteTime(path);
            response.Cache.SetLastModified(lastWriteTime.ToUniversalTime());

            var header = request.Headers["If-Modified-Since"];
            if (string.IsNullOrWhiteSpace(header)) return;
            DateTime isModifiedSince;
            if (DateTime.TryParse(header, out isModifiedSince) && isModifiedSince > lastWriteTime)
            {
                response.StatusCode = (int)HttpStatusCode.NotModified;
                response.SuppressContent = true;
                filterContext.Result = new EmptyResult();
            }
        }

        string getPath(ActionExecutingContext filterContext)
        {
            if (!filterContext.ActionParameters.ContainsKey(Parameter)) return string.Empty;
            var name = filterContext.ActionParameters[Parameter] as string;
            if (string.IsNullOrWhiteSpace(name)) return string.Empty;

            var path = Path.GetFileName(name);
            path = filterContext.HttpContext.Server.MapPath(string.Format("{0}/{1}", BasePath, path));
            return !File.Exists(path) ? string.Empty : path;
        }
    }
در اینجا توسط filterContext، می‌توان به مقادیر پارامترهای ارسالی به یک اکشن متد، توسط filterContext.ActionParameters دسترسی پیدا کرد. بر این اساس می‌توان مقدار پارامتر نام فایل درخواستی را یافت. سپس مسیر کامل آن‌را بازگشت داد. اگر فایل موجود باشد، هدر If-Modified-Since درخواست، استخراج می‌شود. اگر این هدر تنظیم شده باشد، آنگاه بررسی خواهد شد که تاریخ تغییر فایل درخواستی جدیدتر است یا قدیمی‌تر از آخرین بار مرور سایت توسط مرورگر.

و برای استفاده از آن خواهیم داشت:
        [SetIfModifiedSince(Parameter = "name", BasePath = "~/app_data/images/")]
        [OutputCache(Duration = AMonth, VaryByParam = "name")]
        public ActionResult GetImage(string name)
        {
            name = Path.GetFileName(name);
            var path = Server.MapPath(string.Format("~/app_data/images/{0}", name));
            var content = System.IO.File.ReadAllBytes(path);
            return File(content, "image/png", name);
        }
البته بدیهی است اگر منطق ارسال 304 بر اساس تاریخ تغییر فایل باشد، روش فوق جواب خواهد داد. برای مثال اگر این منطق بر اساس تاریخ ثبت شده در دیتابیس است، قسمت محاسبه‌ی lastWriteTime را باید مطابق روش مطلوب خود تغییر دهید.


خلاصه‌ی بحث
چون فیلتر OutputCache در ASP.NET MVC، هدر If-Modified-Since را پردازش نمی‌کند (از این جهت که پردازش آن برای نمونه در مثال فوق وابسته به منطق خاصی است و عمومی نیست)، اگر با هر بار گشودن سایت خود مشاهده کردید، تصاویر پویایی که قرار بوده یک ماه کش شوند، دوباره از سرور درخواست می‌شوند (البته به ازای هرباری که مرورگر از نو اجرا می‌شود و نه در دفعات بعدی که صفحات سایت با همان وهله‌ی ابتدایی مرور خواهند شد)، نیاز است خودتان دسترسی کار پردازش هدر If-Modified-Since را انجام داده و سپس status code 304 را در صورت نیاز، ارسال کنید.
و در حالت عمومی، طراحی سیستم caching محتوای پویای شما بدون پردازش هدر If-Modified-Since ناقص است (تفاوتی نمی‌کند که از کدام فناوری سمت سرور استفاده می‌کنید).
 

برای مطالعه بیشتر
Understanding Conditional Requests and Refresh
Use If-Modified-Since header in ASP.NET 
Make your browser cache the output of an HttpHandler
304 Your images from a database
Conditional GET
Website Performance with ASP.NET - Part4 - Use Cache Headers
ASP.NET MVC 304 Not Modified Filter for Syndication Content
اشتراک‌ها
Visual Studio 2019 version 16.6.0 منتشر شد

Top Issues Fixed in Visual Studio 2019 version 16.6.0

  • When New Git experience feature flag is enabled, a message will appear in Team Explorer guiding users to the new Git tool window.
  • Fix for intermittent UI delay while closing VS when WinForms .NET Core designer is in open state.
  • Fixed issues creating projects using type providers, throwing missing method exception at runtime.
  • Fixed project creation for .NET framework projects.
  • New find in files experience respects options in Tools-Options-Find and Replace pane.
  • Fixed a bug where Git repository does not change when closing a Folder and opening a Solution.
  • Fixed bug when building iOS app using full debug symbols.
  • Added back browing of Mac Distribution provisioning profiles and certificates from Windows.
  • Fixed a bug causing Visual Studio 2019 to stop responding when working with Xamarin projects on certain scenarios.
  • Added keyboard shortcut for "Copy with Headers" option in SQL Script Results Grid
  • SSDT users will now be able to set and view sensitivity properties for all version above SQL Server 2008
  • Improve Connection Properties dialog for accessibility users.
  • Fixed occasional crashes when using Tested By Code Lens indicator.
  • Ensure auto population of text in Find in files is as per legacy behavior.
  • Ensure left arrow key behavior in find in files is correct.
  • An issue blocking C++ users of the C++20 Ranges library from using algorithms. 
Visual Studio 2019 version 16.6.0 منتشر شد
نظرات مطالب
متدهای کمکی مفید در پروژه های asp.net mvc
چه خطایی می‌ده؟ چون من الان استفاده کردم و خطایی نداد.
اگر یک چنین خطایی دریافت کردید:
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
مربوط است به نال بودن یکی از مقادیر تاریخ ثبت شده در بانک اطلاعاتی. خاصیت را در سمت کدهای خود nullable تعریف کنید.
مطالب
انتخاب پویای فیلد ها در LINQ

LINQ یک DLS  بر مبنای .NET  می باشد که برای پرس و جو در منابع داده ای مانند پایگاه‌های داده ، فایل‌های XML و یا لیستی از اشیاء درون حافظه کاربرد دارد.

یکی از بزرگترین مزیت‌های آن Syntax  آسان و خوانا آن می‌باشد.

LINQ  از 2 نوع نمادگذاری پشتیبانی می‌کند:

  • Inline LINQ یا query expressions : 
var result = 
    from product in dbContext.Products
    where product.Category.Name == "Toys"
    where product.Price >= 2.50
    select product.Name;
  • Fluent Syntax : 
var result = dbContext.Products
    .Where(p => p.Category.Name == "Toys" && p.Price >= 250)
    .Select(p => p.Name);

در پرس و چو‌های بالا فیلد‌های مورد نیاز در قسمت Select در زمان Compile شناخته شده هستند . اما گاهی ممکن است فیلد‌های مورد نیاز در زمان اجرا مشخص شوند.

به عنوان مثال یک گزارش ساز پویا که کاربر مشخص می‌کند چه ستون هایی در خروجی نمایش داده شوند یا یک جستجوی پیشرفته که ستون‌های خروجی به اختیار کاربر در زمان اجرا مشخص می‌شوند. 

این مدل را در نظر داشته باشید :

    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Field1 { get; set; }
        public string Field2 { get; set; }
        public string Field3 { get; set; }


        public static IEnumerable<Student> GetStudentSource()
        {
            for (int i = 0; i < 10; i++)
            {
                yield return new Student
                                 {
                                     Id = i,
                                     Name = "Name " + i,
                                     Field1 = "Field1 " + i,
                                     Field2 = "Field2 " + i,
                                     Field3 = "Field3 " + i
                                 };
            }
        }
    }

ستون‌های کلاس Student  را در رابط کاربری برنامه جهت انتخاب به کاربر نمایش می‌دهیم. سپس کاربر یک یا چند ستون را انتخاب می‌کند که قسمت Select  کوئری برنامه باید  بر اساس فیلد‌های مورد نظر کاربر مشخص شود.

یکی از روش هایی که می‌توان از آن بهره برد استفاده از کتاب خانه Dynamic LINQ معرفی شده در اینجا می باشد.

این کتابخانه جهت سهولت در نصب به کمک NuGet در این آدرس قرار دارد.

فرض بر این است که فیلد‌های انتخاب شده توسط کاربر با "," از یکدیگر جدا شده اند. 

    public class Program
    {
        private static void Main(string[] args)
        {
            System.Console.WriteLine("Specify the desired fields : ");
            string fields = System.Console.ReadLine();
            IEnumerable<Student> students = Student.GetStudentSource();
            IQueryable output = students.AsQueryable().Select(string.Format("new({0})", fields));
            foreach (object item in output)
            {
                System.Console.WriteLine(item);
            }
          
            System.Console.ReadKey();
        }
  
    }

همانطور که در عکس ذیل مشاهده می‌کنید پس از اجرای برنامه ، فیلد‌های انتخاب شده توسط کاربر از منبع داده‌ی دریافت شده و در خروجی نمایش داده شده اند.

این روش مزایا و معایب خودش را دارد ، به عنوان مثال خروجی یک لیست از شیء Student  نیست یا این Select  فقط برای روی یک شیء IQueryable  قابل انجام است.

روش دیگری که می‌توان از آن بهره جست استفاده از یک متد کمکی جهت تولید پویای عبارت Lambda  ورودی Select  می باشد :  

    public  class SelectBuilder <T>
    {
        public static Func<T, T> CreateNewStatement(string fields)
        {
            // input parameter "o"
            var xParameter = Expression.Parameter(typeof(T), "o");


            // new statement "new T()"
            var xNew = Expression.New(typeof(T));

            // create initializers
            var bindings = fields.Split(',').Select(o => o.Trim())
                .Select(o =>
                {

                    // property "Field1"
                    var property = typeof(T).GetProperty(o);

                    // original value "o.Field1"
                    var xOriginal = Expression.Property(xParameter, property);

                    // set value "Field1 = o.Field1"
                    return Expression.Bind(property, xOriginal);
                }
            ).ToList();

            // initialization "new T { Field1 = o.Field1, Field2 = o.Field2 }"
            var xInit = Expression.MemberInit(xNew, bindings);

            // expression "o => new T { Field1 = o.Field1, Field2 = o.Field2 }"
            var lambda = Expression.Lambda<Func<T, T>>(xInit, xParameter);

            // compile to Func<T, T>
            return lambda.Compile();
        }
    }
برای استفاده از متد CreateNewStatement باید اینگونه عمل کرد :  
       IEnumerable<Student> result = students.Select(SelectBuilder<Student>.CreateNewStatement("Field1, Field2")).ToList();

            foreach (Student student in result)
            {
                System.Console.WriteLine(student.Field1);
            }
خروجی یک لیست از Student  می باشد.
 نحوه‌ی کارکرد CreateNewStatement :

ابتدا فیلد‌های انتخابی کاربر که با "," جدا شده اند به ورودی پاس داده می‌شود سپس یک statement  خالی ایجاد می‌شود

o=>new Student()
فیلد‌های ورودی از یکدیگر تفکیک می‌شوند و به کمک Reflection پراپرتی معادل فیلد رشته ای در کلاس Student پیدا می‌شود :  
var property = typeof(T).GetProperty(o);
سپس عبارت Select و تولید شیء جدید بر اساس فیلد‌های ورودی تولید می‌شود و برای استفاده Compile  به Func می‌شود. در نهایت Func  تولید شده به Select پاس داده می‌شود و لیستی از Student  بر مبنای فیلد‌های انتخابی تولید می‌شود. 

دریافت مثال : DynamicSelect.zip 
اشتراک‌ها
زبان Rust در حال از هم پاشیدن است!

While Rust has earned a dedicated following, it's not without its fair share of controversies and problems. In this video I'll talk about the negative response and backlash from the Rust community in the wake of the most recent controversy, its connections to past incidents, and give my personal thoughts.  

زبان Rust در حال از هم پاشیدن است!
اشتراک‌ها
بالاخره پیشنهاد یک المان <select> قابل سفارشی سازی با CSS
Request for developer feedback: customizable select

Styling form controls like the <select> element has been reported as a top developer pain point for years, and we've been working on a solution. While this work is complex and has taken a long time to get right, we're getting very close to landing this feature. A customizable version of the select element is officially in Stage 2 in the WHATWG, with strong cross-browser interest and a prototype for you to test out from Chrome Canary 130.
بالاخره پیشنهاد یک المان <select> قابل سفارشی سازی با CSS
اشتراک‌ها
کتابخانه combodate

Dropdown date and time picker.  Demo
This plugin converts <input type="text"> into dropdown elements to pick day, month, year, hour, minutes and seconds.

  • support of date, time, datetime
  • 12h / 24h format
  • based on moment.js  
کتابخانه combodate
مطالب
PersianDateTime جایگزینی برای System.DateTime
همانطور که در توضیح پروژه PersianDateTime آمده است، کلاس PersianDateTime جایگزینی است برای System.DateTime برای استفاده در پروژه‌هایی که احتیاج به تاریخ شمسی و ساعت رسمی ایران یا سایر کشورهای فارسی‌زبان، مستقل از Time Zone سیستم و در نظر گرفتن Daylight Saving Time، دارند. این کلاس شامل اکثر متدها، پراپرتی‌ها و عملگرهای متداول  System.DateTime است.

دسترسی به تاریخ و ساعت فعلی :
PersianDateTime now = PersianDateTime.Now;

string persianDateTime = now.ToString(); // 1392/03/09 23:37:57
string persianDate = now.ToString(PersianDateTimeFormat.Date); // 1392/03/09
string persianFullDateTime = now.ToString("dddd d MMMM yyyy ساعت hh:mm:ss tt"); // پنج شنبه 9 خرداد 1392 ساعت 11:37:57 ب.ظ

TimeSpan persianTime = now.TimeOfDay; // 23:37:57.4641984


نحوه محاسبه PersianDateTime.Now بر اساس فیلد استاتیک PersianDateTime.Mode است که مقدار پیش‌فرض آن PersianDateTimeMode.UtcOffset است.
PersianDateTime.Mode را می‌توان یکی از سه مقدار زیر قرار داد :
  • System : بر اساس تاریخ و زمان سیستم (Time Zone فعلی سیستم)
  • PersianTimeZoneInfo : بر اساس Time Zone تعیین شده در فیلد استاتیک PersianDateTime.PersianTimeZoneInfo (مستقل از Time Zone سیستم)
  • UtcOffset : بر اساس اختلاف ساعت با UTC، مشخص شده در فیلد استاتیک PersianDateTime.OffsetFromUtc (مستقل از Time Zone سیستم)

مقدار پیش‌فرض PersianDateTime.PersianTimeZoneInfo برابر Iran Standard Time Zone است. توجه داشته باشید که در این حالت از DaylightSavingTime تعیین شده در Time Zone استفاده خواهد شد که مثلا برای ایران با زمان واقعی آن اختلاف دارد و باید آنرا اصلاح کرد .

مقدار پیش‌فرض PersianDateTime.OffsetFromUtc برابر 3 ساعت و نیم است. در این حالت DaylightSavingTime با توجه به مقادیر سه فیلد استاتیک DaylightSavingTimeStart ،DaylightSavingTimeEnd و DaylightSavingTime تعیین می‌شود که به صورت پیش‌فرض برابر ساعت 24 اول فروردین، ساعت 24 سی‌ام شهریور و یک ساعت است.

تمام فیلدهای استاتیک ذکر شده به صورت public تعریف شده‌اند تا برنامه‌نویسان سایر کشورهای فارسی‌زبان بتوانند به دلخواه خود آنرا تغییر دهند.

نحوه کار با مقادیر رشته‌ای تاریخ شمسی هم اینگونه است :
PersianDateTime persianDate1 = PersianDateTime.Parse("1392/03/02");
PersianDateTime persianDate2 = PersianDateTime.Parse("1392/03/02", "23:32:56");

چند سازنده هم وجود دارد برای کسانی که تاریخ را به صورت int و ساعت را int یا short (بدون ثانیه) ذخیره می‌کنند :
PersianDateTime persianDate1 = new PersianDateTime(13920310);
PersianDateTime persianDate2 = new PersianDateTime(13920310, 233256);
PersianDateTime persianDate3 = new PersianDateTime(13920310, (short)2332);

تبدیل تاریخ میلادی به شمسی :
DateTime miladiDate = new DateTime(2013, 5, 31);
PersianDateTime persianDate = new PersianDateTime(miladiDate);

تبدیل تاریخ شمسی به میلادی :
PersianDateTime persianDate = PersianDateTime.Parse("1392/03/02");
DateTime miladiDate = persianDate.ToDateTime();


علاوه بر متد ToString معمولی، دو overload دیگر از این متد برای نمایش فرمت‌های مختلف PersianDateTime وجود دارد :

public string ToString(PersianDateTimeFormat format);

public string ToString(string format);
که اولی برای فرمت‌های معمول و دومی برای هر نوع فرمت دلخواه قابل استفاده است که چند نمونه آنرا در قسمت تعیین تاریخ و ساعت فعلی دیدید.

برخی از خصوصیات کلاس PersianDateTime :
  • Year : سال
  • Month : ماه
  • Day : روز
  • TimeOfDay : زمان سپری شده از ابتدای روز
  • TimeOfWeek :زمان سپری شده از ابتدای هفته
  • TimeOfMonth : زمان سپری شده از ابتدای ماه
  • TimeOfYear : زمان سپری شده از ابتدای سال
  • DaysInYear : تعداد روز سال
  • DaysInMonth : تعداد روز ماه
  • DayOfWeek : چندمین روز هفته
  • DayOfYear : چندمین روز سال
  • DayName : نام روز
  • MonthName : نام ماه
  • Date : تاریخ بدون زمان
  • FirstDayOfWeek : اولین روز هفته
  • LastDayOfWeek : آخرین روز هفته
  • FirstDayOfMonth : اولین روز ماه
  • LastDayOfMonth : آخرین روز ماه
  • FirstDayOfYear : اولین روز سال
  • LastDayOfYear : آخرین روز سال

برخی دیگر از متدهای کلاس PersianDateTime :

public PersianDateTime Add(TimeSpan value);
public PersianDateTime AddDays(double value);
public PersianDateTime AddMonths(int months);
public PersianDateTime AddYears(int value);
public PersianDateTime AddHours(double value);
public PersianDateTime AddMinutes(double value);
public PersianDateTime AddSeconds(double value);
همچنین تمام عملگرهای +، -، >، <، =>، =<، ==، و =! قابل استفاده هستند.
مطالب
امکان انجام محاسبات سمت کلاینت در EF Core
در دنیای NET. همواره دو نوع LINQ وجود داشته داشته است: LINQ to Objects و ... مابقی.  در حالت اول با <IEnumerable<T‌ها کار می‌کنیم که تمام عملیات در حافظه انجام می‌شود و در مابقی حالات یک <IQueryable<T وجود دارد که عبارت حاصل از آن جهت کاربردهای مختلفی به زبان‌های متفاوتی مانند SQL ترجمه می‌شوند. در هر دو حالت کلی، Syntax نهایی یکی است و تنها اگر به منبع داده‌ی آن‌ها دقت کنیم، می‌توانیم نوع آن‌ها را تشخیص دهیم. برای نمونه کوئری ذیل بر اساس منبع Blogs است که می‌تواند LINQ to Objects باشد و یا حالت <Queryable<Blog که قرار است به زبانی مشخص ترجمه شود:
var blogs = from blog in Blogs
   where blog.Name.Contains("Development")
   select blog;
اکنون فرض کنید که این عبارت قرار است به SQL ترجمه شده و سپس بر روی یک بانک اطلاعاتی اجرا شود. در این حالت مفسر LINQ باید بداند که متد Contains را چگونه به معادل SQL آن ترجمه کند و این ترجمه می‌تواند بر اساس بانک‌های اطلاعاتی مختلف، متفاوت نیز باشد. اما در حالت LINQ to Objects یک چنین مشکلی وجود ندارد و این ترجمه مستقیما بر روی متد Contains کلاس string انجام می‌شود.
اما اکنون چطور؟
var blogs = from blog in Blogs
   where blog.Name.ComputeHash() == 0
   select blog;
فرض کنید یک متد الحاقی را به نام ComputeHash به کلاس string اضافه کرده‌ایم. یک چنین کوئری را اگر بر روی EF 6.x اجرا کنیم، برنامه با یک استثناء متوقف خواهد شد؛ چون امکان ترجمه‌ی متد ComputeHash را به معادل SQL آن ندارد؛ اما EF Core برای انجام یک چنین کوئری‌هایی بهبود یافته‌است که به آن، محاسبات سمت کلاینت گفته می‌شود.


یک مثال: بررسی تاثیر ارزیابی‌های سمت کلاینت در EF Core

فرض کنید ساختار جدول بلاگ‌ها به صورت زیر است:
public class Blog
{
   public int BlogId { get; set; }
   public string Url { get; set; }  
}
همچنین یک متد الحاقی را به نام ComputeHash به صورت ذیل تعریف کرده‌ایم:
    public static class StringExtensions
    {
        public static int ComputeHash(this string str)
        {
            var hash = 0;
            foreach (var ch in str)
            {
                hash += (int)ch;
            }
            return hash;
        }
    }
اکنون می‌خواهیم بلاگ‌هایی را پیدا کنیم که Hash مربوط به Url آن‌ها بیشتر از 10 است (صرفا جهت نمایش این قابلیت جدید):
using (var context = new BloggingContext())
{
   var blogs = context.Blogs
     .Where(blog => blog.Url.ComputeHash() >= 10)
     .ToList();
   Console.WriteLine(blogs.First().Url);
}
اگر این کوئری را اجرا کنیم، یک چنین خروجی SQL ایی تولید خواهد شد و همچنین برنامه کرش هم نمی‌کند:
SELECT [blog].[BlogId], [blog].[Url]
   FROM [Blogs] AS [blog]
به این معنا که در ارزیابی‌های سمت کلاینت:
الف) مفسر LINQ در EF Core، شروع به ارزیابی کوئری نوشته شده می‌کند و هرجائیکه متدی را یافت و از درک آن عاجز بود (معادل SQL ایی را برای آن نیافت)، آن‌را از کوئری حذف می‌کند.
ب) کوئری SQL نهایی بدون متد ComputeHash بر روی بانک اطلاعاتی اجرا شده و نتیجه به سمت کلاینت بازگشت داده می‌شود. به همین جهت است که در خروجی SQL فوق خبری از متد ComputeHash نیست.
ج) اکنون که EF Core اطلاعات لازم را از سمت سرور دریافت کرده‌است، متد ComputeHash را در سمت کلاینت بر روی این نتیجه‌ی دریافتی اعمال می‌کند. یعنی مرحله‌ی آخر همان LINQ to Objects متداول خواهد بود.
به این ترتیب است که EF Core قابلیت اجرای هر نوع متدی را که معادل SQL ایی برای آن وجود ندارد، خواهد یافت.


چگونه متوجه شویم که ارزیابی سمت کلاینت رخ داده‌است؟

EF Core این قابلیت را دارد تا گزارش کاملی را از ارزیابی‌های سمت کلاینت صورت گرفته ارائه دهد. هرچند در مثال فوق متد الحاقی ComputeHash بسیار واضح است، اما برای نمونه متد string.Join نیز معادل SQL ایی ندارد:
var idUrls = context.Blogs
   .Select(b => new
   {
      IdUrlString = string.Join(", ", b.BlogId, b.Url),
   }).ToList();
این مثال بدون مشکل توسط EF Core و قابلیت جدید ارزیابی سمت کلاینت آن اجرا می‌شود، اما بهتر است از وقوع یک چنین رخ‌دادهایی مطلع شویم:
    public class BloggingContext : DbContext
    {
        public BloggingContext()
        { }

        public BloggingContext(DbContextOptions options)
            : base(options)
        { }

        public DbSet<Blog> Blogs { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Demo.ClientSideEvaluation;Trusted_Connection=True;");
                optionsBuilder.ConfigureWarnings(warnings =>
                {
                    warnings.Log(CoreEventId.IncludeIgnoredWarning);
                    warnings.Log(RelationalEventId.QueryClientEvaluationWarning);
                });
            }
        }
    }
برای این منظور تنها کافی است درخواست فعالسازی لاگ کردن QueryClientEvaluationWarning را در قسمت ConfigureWarnings آن ارائه دهیم. در این حالت اگر برنامه را مجددا اجرا کنیم، ابتدا یک چنین خروجی لاگ می‌شود:
 warn: Microsoft.EntityFrameworkCore.Query[200500]
The LINQ expression 'where ([blog].Url.ComputeHash() >= 10)' could not be translated and will be evaluated locally.
عنوان کرده‌است که قابلیت ترجمه‌ی ComputeHash را به SQL نداشته و آن‌را در نهایت به صورت محلی و در سمت کلاینت محاسبه می‌کند.

اگر می‌خواهید ارزیابی سمت کلاینت را ممنوع کنید، در تنظیمات فوق warnings.Log را به warnings.Throw تغییر دهید. این مورد سبب خواهد شد تا اگر برنامه به این نوع ارزیابی‌ها رسید، با یک استثناء متوقف شود (شبیه به حالت EF 6.x).


تاثیر ارزیابی‌های سمت کلاینت بر روی کارآیی برنامه

هرچند قابلیت ارزیابی‌های سمت کلاینت بسیار مفید است اما باید دقت داشت:
الف) در این حالت چون ابتدا متدهایی که قابلیت ارزیابی در سمت سرور را دارا نیستند، حذف خواهند شد، ممکن است تمام رکوردها به سمت کلاینت بازگشت داده شده و سپس فیلترینگ نهایی در سمت کلاینت صورت گیرد. مانند مثال محاسبه‌ی hash که در SQL تولیدی آن، خبری از قسمت where نیست و این شرط در انتهای کار، در سمت کلاینت و به صورت LINQ to Objects اعمال می‌شود.
ب) این قابلیت ممکن است برنامه نویس‌ها را از تفکر در مورد یافتن روش‌های محاسباتی سمت سرور دور کند. برای مثال هر چند مثال string.Join نوشته شده در سمت کلاینت محاسبه خواهد شد و این کوئری بدون مشکل اجرا می‌شود، اما اگر آن‌را به صورت ذیل جایگزین کنیم:
var idUrls2 = context.Blogs
   .Select(b => new
   {
     IdUrlString = b.BlogId + "," + b.Url
   }).ToList();
اینبار به یک خروجی SQL قابل محاسبه‌ی در سمت سرور، خواهیم رسید:
SELECT (CAST([b].[BlogId] AS nvarchar(max)) + N',') + [b].[Url] AS [IdUrlString]
FROM [Blogs] AS [b]
به همین جهت حداقل لاگ کردن ارزیابی‌های سمت کلاینت را روشن کنید تا از وقوع یک چنین مسایلی مطلع گردید.


کدهای کامل این مثال را از اینجا می‌توانید دریافت کنید: ClientSideEvaluation.zip