مطالب
اگر نصب سرویس پک اس کیوال سرور Fail شد ...

همانطور که مطلع هستید سرویس پک سه SQL Server چند روزی است که منتشر شده. این به روز رسانی بر روی یک سرور بدون مشکل نصب شد؛ در سرور دیگر به علت داشتن یک سری برنامه امنیتی مزاحم (که مثلا دسترسی به رجیستری را مونیتور و سد می‌کنند) با شکست مواجه و در آخر پیغام Fail نمایش داده شد. مجددا آنرا اجرا کردم، سریع تمام مراحل را تمام کرد باز هم Fail را نمایش داد.
خوب؛ گفتم احتمالا مشکلی نیست. سعی کردم به سرور وصل شوم ... پیغام «این سرور دسترسی از راه دور را نمی‌پذیرد» و از این حرف‌های متداول ظاهر شد. به لاگ موجود در Event log ویندوز که مراجعه کردم پیغام خطای زیر نمایان بود:

Script level upgrade for database 'master' failed because upgrade step 'sqlagent100_msdb_upgrade.sql' encountered error 5597, state 1, severity 16. This is a serious error condition which might interfere with regular operation and the database will be taken offline. If the error happened during upgrade of the 'master' database, it will prevent the entire SQL Server instance from starting. Examine the previous errorlog entries for errors, take the appropriate corrective actions and re-start the database so that the script upgrade steps run to completion.

اوه! اوه! اوه! در این لحظه‌ی عرفانی، دیتابیس master نابود شده! نمی‌شود وصل شد. سروری که داشت تا مدتی قبل بدون هیچ مشکلی کار می‌کرد، الان دیگر حتی نمی‌شود به آن وصل شد. به کنسول سرویس‌های ویندوز مراجعه کردم (services.msc)، سعی کردم سرویس اس کیوال را که از کار افتاده دستی اجرا کنم، پیغام زیر مجددا در event log ظاهر شد:

FILESTREAM feature could not be initialized. The Windows Administrator must enable FILESTREAM on the instance using Configuration Manager before enabling through sp_configure.

قابلیت FILESTREAM را نمی‌تواند آغاز کند. پس از مدتی جستجو مشخص شد که این مورد را می‌شود در رجیستری ویندوز غیرفعال کرد؛ به صورت زیر:

1) Open up Registry Editor
2) Go To HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.MSSQLServer\MSSQLSERVER\FileStream
3) Edit the value "EnableLevel" and set it to 0
4) Restart SQL Server.

پس از انجام اینکار، سرویس اس کیوال استارت شد (از طریق کنسول سرویس‌های ویندوز). در ادامه، امکان اتصال به آن نبود (حتی با اکانت sa):

Login failed for user 'sa'. Reason: Server is in script upgrade mode. Only administrator can connect at this time. (Microsoft SQL Server, Error: 18401)


باز هم پس از مدتی جستجو معلوم گردید که «کمی باید صبر کرد». آن پیغام اول کار مبتنی بر تخریب دیتابیس master هم بی‌مورد است. پس از fail شدن نصب سرویس پک، هنوز برنامه نصاب آن در پشت صحنه مشغول به کار است. این مورد به وضوح در task manager ویندوز مشخص است. سرور به مدت 15 دقیقه به حال خود رها شد. پس از آن بدون مشکل اتصال برقرار گردید و همه چیز مجددا شروع به کار کرد.

بنابراین اگر در حین نصب سرویس پک SQL Server مشکلی پیش آمد، نگران نباشید. باید به نصاب آن زمان داد (برنامه mscorsw.exe در پشت صحنه مشغول به کار است). برنامه نصاب آن هم هیچ نوع خطای مفهومی را گزارش نمی‌دهد. تمام مراحل، بجای نمایش در برنامه تمام صفحه نصاب آن، در event log ویندوز ثبت می‌شود. این برنامه تمام صفحه فقط کارش نمایش یک progress bar است!


اگر ... هیچکدام از این موارد جواب نداد، امکان بازسازی دیتابیس master نیز وجود دارد: [^ , ^]
ولی دست نگه دارید و سریع اقدام نکنید. ابتدا به task manager مراجعه کنید. آیا برنامه mscorsw.exe در حال اجرا است؟ اگر بله، یعنی هنوز کار نصب تمام نشده. حداقل یک ربع باید صبر کنید.

اشتراک‌ها
ابزار Autorest : کد جنریتوری برای OpenAPI Specification

OpenAPI (f.k.a Swagger) Specification code generator. Supports C#, Go, Java, Node.js, TypeScript, Python, Ruby and PHP. 

AutoRest is an open source tool that generates client libraries for accessing RESTful web services. 

Video Tutorial : https://azure.microsoft.com/en-us/resources/videos/inside-autorest-with-david-justice/ 

ابزار Autorest : کد جنریتوری برای OpenAPI Specification
مطالب
روش محاسبه‌ی لحظه‌ی سال تحویل
سال قبل نتیجه‌ی جستجوی من برای یافتن فرمول محاسبه‌ی زمان سال تحویل، برای ارسال ایمیل‌های خودکار تبریک آن، در سایت‌های ایرانی حاصلی نداشت. اما واژه‌ی انگلیسی Equinox سرآغازی شد برای یافتن این الگوریتم.
نام علمی لحظه‌ی سال تحویل، Vernal Equinox است. Equinox به معنای نقطه‌ای است که یک فصل، به فصلی دیگر تبدیل می‌شود:


Equinox واژه‌ای است لاتین به معنای «شب‌های مساوی» و به این نکته اشاره دارد که در Equinox، طول شب و روز یکی می‌شوند. هر سال دارای دو Equinox است: vernal equinox و autumnal equinox (بهاری و پائیزی). البته باید درنظر داشت که Equinox بهاری در نیم کره‌ی شمالی بیشتر معنا پیدا می‌کند؛ زیرا در نیم کره‌ی جنوبی در همین زمان، پائیز شروع می‌شود.
بنابراین می‌توان enum زیر را برای تعریف این چهار ثابت رخدادهای خورشیدی تعریف کرد:
public enum SunEvent
{
    /// <summary>
    /// march equinox
    /// </summary>
    VernalEquinox,
 
    /// <summary>
    /// june solstice
    /// </summary>
    SummerSolstice,
 
    /// <summary>
    /// september equinox
    /// </summary>
    AutumnalEquinox,
 
    /// <summary>
    /// december solstice
    /// </summary>
    WinterSolstice
}

در ادامه برای محاسبه‌ی زمان equinox از فصل 27 کتاب Astronomical Algorithms کمک گرفته شده و تمام اعداد و ارقام و جداولی را که ملاحظه می‌کنید از این کتاب استخراج شده‌اند.
/// <summary>
/// Based on Jean Meeus book _Astronomical Algorithms_
/// </summary>
public static class EquinoxCalculator
{
    /// <summary>
    /// Degrees to Radians conversion factor.
    /// </summary>
    public static readonly double Deg2Radian = Math.PI / 180.0;
 
    public static bool ApproxEquals(double d1, double d2)
    {
        const double epsilon = 2.2204460492503131E-16;
        if (d1 == d2)
            return true;
        var tolerance = ((Math.Abs(d1) + Math.Abs(d2)) + 10.0) * epsilon;
        var difference = d1 - d2;
        return (-tolerance < difference && tolerance > difference);
    }
 
    /// <summary>
    /// Calculates time of the Equinox and Solstice.
    /// </summary>
    /// <param name="year">Year to calculate for.</param>
    /// <param name="sunEvent">Event to calculate.</param>
    /// <returns>Date and time event occurs as a fractional Julian Day.</returns>
    public static DateTime GetSunEventUtc(this int year, SunEvent sunEvent)
    {
        double y;
        double julianEphemerisDay;
 
        if (year >= 1000)
        {
            y = (Math.Floor((double)year) - 2000) / 1000;
 
            switch (sunEvent)
            {
                case SunEvent.VernalEquinox:
                    julianEphemerisDay = 2451623.80984 + 365242.37404 * y + 0.05169 * (y * y) - 0.00411 * (y * y * y) - 0.00057 * (y * y * y * y);
                    break;
                case SunEvent.SummerSolstice:
                    julianEphemerisDay = 2451716.56767 + 365241.62603 * y + 0.00325 * (y * y) - 0.00888 * (y * y * y) - 0.00030 * (y * y * y * y);
                    break;
                case SunEvent.AutumnalEquinox:
                    julianEphemerisDay = 2451810.21715 + 365242.01767 * y + 0.11575 * (y * y) - 0.00337 * (y * y * y) - 0.00078 * (y * y * y * y);
                    break;
                case SunEvent.WinterSolstice:
                    julianEphemerisDay = 2451900.05952 + 365242.74049 * y + 0.06223 * (y * y) - 0.00823 * (y * y * y) - 0.00032 * (y * y * y * y);
                    break;
                default:
                    throw new NotSupportedException();
            }
        }
        else
        {
            y = Math.Floor((double)year) / 1000;
 
            switch (sunEvent)
            {
                case SunEvent.VernalEquinox:
                    julianEphemerisDay = 1721139.29189 + 365242.13740 * y + 0.06134 * (y * y) - 0.00111 * (y * y * y) - 0.00071 * (y * y * y * y);
                    break;
                case SunEvent.SummerSolstice:
                    julianEphemerisDay = 1721233.25401 + 365241.72562 * y + 0.05323 * (y * y) - 0.00907 * (y * y * y) - 0.00025 * (y * y * y * y);
                    break;
                case SunEvent.AutumnalEquinox:
                    julianEphemerisDay = 1721325.70455 + 365242.49558 * y + 0.11677 * (y * y) - 0.00297 * (y * y * y) - 0.00074 * (y * y * y * y);
                    break;
                case SunEvent.WinterSolstice:
                    julianEphemerisDay = 1721414.39987 + 365242.88257 * y + 0.00769 * (y * y) - 0.00933 * (y * y * y) - 0.00006 * (y * y * y * y);
                    break;
                default:
                    throw new NotSupportedException();
            }
        }
 
        var julianCenturies = (julianEphemerisDay - 2451545.0) / 36525;
 
        var w = 35999.373 * julianCenturies - 2.47;
 
        var lambda = 1 + 0.0334 * Math.Cos(w * Deg2Radian) + 0.0007 * Math.Cos(2 * w * Deg2Radian);
 
        var sumOfPeriodicTerms = getSumOfPeriodicTerms(julianCenturies);
 
        return JulianToUtcDate(julianEphemerisDay + (0.00001 * sumOfPeriodicTerms / lambda));
    }
 
    /// <summary>
    /// Converts a fractional Julian Day to a .NET DateTime.
    /// </summary>
    /// <param name="julianDay">Fractional Julian Day to convert.</param>
    /// <returns>Date and Time in .NET DateTime format.</returns>
    public static DateTime JulianToUtcDate(double julianDay)
    {
        double a;
        int month, year;
 
        var j = julianDay + 0.5;
        var z = Math.Floor(j);
        var f = j - z;
 
        if (z >= 2299161)
        {
            var alpha = Math.Floor((z - 1867216.25) / 36524.25);
            a = z + 1 + alpha - Math.Floor(alpha / 4);
        }
        else
            a = z;
 
        var b = a + 1524;
 
        var c = Math.Floor((b - 122.1) / 365.25);
 
        var d = Math.Floor(365.25 * c);
 
        var e = Math.Floor((b - d) / 30.6001);
 
        var day = b - d - Math.Floor(30.6001 * e) + f;
 
        if (e < 14)
            month = (int)(e - 1.0);
        else if (ApproxEquals(e, 14) || ApproxEquals(e, 15))
            month = (int)(e - 13.0);
        else
            throw new NotSupportedException("Illegal month calculated.");
 
        if (month > 2)
            year = (int)(c - 4716.0);
        else if (month == 1 || month == 2)
            year = (int)(c - 4715.0);
        else
            throw new NotSupportedException("Illegal year calculated.");
 
        var span = TimeSpan.FromDays(day);
 
        return new DateTime(year, month, (int)day, span.Hours, span.Minutes,
            span.Seconds, span.Milliseconds, new GregorianCalendar(), DateTimeKind.Utc);
    }
 
    /// <summary>
    /// These values are from Table 27.C
    /// </summary>
    private static double getSumOfPeriodicTerms(double julianCenturies)
    {
        return 485 * Math.Cos(Deg2Radian * 324.96 + Deg2Radian * (1934.136 * julianCenturies))
               + 203 * Math.Cos(Deg2Radian * 337.23 + Deg2Radian * (32964.467 * julianCenturies))
               + 199 * Math.Cos(Deg2Radian * 342.08 + Deg2Radian * (20.186 * julianCenturies))
               + 182 * Math.Cos(Deg2Radian * 27.85 + Deg2Radian * (445267.112 * julianCenturies))
               + 156 * Math.Cos(Deg2Radian * 73.14 + Deg2Radian * (45036.886 * julianCenturies))
               + 136 * Math.Cos(Deg2Radian * 171.52 + Deg2Radian * (22518.443 * julianCenturies))
               + 77 * Math.Cos(Deg2Radian * 222.54 + Deg2Radian * (65928.934 * julianCenturies))
               + 74 * Math.Cos(Deg2Radian * 296.72 + Deg2Radian * (3034.906 * julianCenturies))
               + 70 * Math.Cos(Deg2Radian * 243.58 + Deg2Radian * (9037.513 * julianCenturies))
               + 58 * Math.Cos(Deg2Radian * 119.81 + Deg2Radian * (33718.147 * julianCenturies))
               + 52 * Math.Cos(Deg2Radian * 297.17 + Deg2Radian * (150.678 * julianCenturies))
               + 50 * Math.Cos(Deg2Radian * 21.02 + Deg2Radian * (2281.226 * julianCenturies))
               + 45 * Math.Cos(Deg2Radian * 247.54 + Deg2Radian * (29929.562 * julianCenturies))
               + 44 * Math.Cos(Deg2Radian * 325.15 + Deg2Radian * (31555.956 * julianCenturies))
               + 29 * Math.Cos(Deg2Radian * 60.93 + Deg2Radian * (4443.417 * julianCenturies))
               + 28 * Math.Cos(Deg2Radian * 155.12 + Deg2Radian * (67555.328 * julianCenturies))
               + 17 * Math.Cos(Deg2Radian * 288.79 + Deg2Radian * (4562.452 * julianCenturies))
               + 16 * Math.Cos(Deg2Radian * 198.04 + Deg2Radian * (62894.029 * julianCenturies))
               + 14 * Math.Cos(Deg2Radian * 199.76 + Deg2Radian * (31436.921 * julianCenturies))
               + 12 * Math.Cos(Deg2Radian * 95.39 + Deg2Radian * (14577.848 * julianCenturies))
               + 12 * Math.Cos(Deg2Radian * 287.11 + Deg2Radian * (31931.756 * julianCenturies))
               + 12 * Math.Cos(Deg2Radian * 320.81 + Deg2Radian * (34777.259 * julianCenturies))
               + 9 * Math.Cos(Deg2Radian * 227.73 + Deg2Radian * (1222.114 * julianCenturies))
               + 8 * Math.Cos(Deg2Radian * 15.45 + Deg2Radian * (16859.074 * julianCenturies));
    }
}
خروجی‌های زمانی ستاره شناسی، عموما بر اساس فرمت Julian Date است که آغاز آن  4713BCE January 1, 12 hours GMT است. به همین جهت در انتهای این مباحث، تبدیل Julian Date به DateTime دات نت را نیز ملاحظه می‌کنید. همچنین باید دقت داشت که خروجی نهایی بر اساس UTC است و برای زمان ایران، باید 3.5 ساعت به آن اضافه شود.

خروجی این الگوریتم را برای سال‌های 2014 تا 2022 به صورت ذیل مشاهده می‌کنید:
2014 -> 1392/12/29 20:28:08
2015 -> 1394/01/01 02:16:29
2016 -> 1395/01/01 08:01:21
2017 -> 1395/12/30 14:00:00
2018 -> 1396/12/29 19:46:10
2019 -> 1398/01/01 01:29:29
2020 -> 1399/01/01 07:21:03
2021 -> 1399/12/30 13:08:41
2022 -> 1400/12/29 19:04:37
برای نمونه زمان محاسبه شده‌ی 1394/01/01 02:16:29 با زمان رسمی اعلام شده‌ی ساعت 2 و 15 دقیقه و 10 ثانیه روز شنبه 1 فروردین 1394 و یا برای سال 93 زمان محاسبه شده‌ی 1392/12/29 20:28:08 با زمان رسمی ساعت ۲۰ و ۲۷ دقیقه و ۷ ثانیه پنجشنبه ۲۹ اسفند ۱۳۹۲، تقریبا برابری می‌کند.

کدهای کامل این پروژه را از اینجا می‌توانید دریافت کنید
 Equinox.zip
اشتراک‌ها
از C# 9 چه خبر؟

The proposed C# 9 features could make C# more functional and practical. Read this article to be prepared for the Inevitable Challenges. 

از C# 9 چه خبر؟
اشتراک‌ها
کتابخانه weather-icons
Weather Icons is the only icon font and CSS with 222 weather themed icons, ready to be dropped right into Bootstrap, or any project that needs high quality weather, maritime, and meteorological based icons!  Demo
کتابخانه weather-icons