افزودن یک DataType جدید برای نگه‌داری تاریخ خورشیدی - 3
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: یک دقیقه

در دو درس گذشته با DataType ای که با هم نوشتیم؛ می‌توانستیم این پرس‌وجوها را داشته باشیم:
Declare @MyDate JalaliDate = '1392/02/11 21:38:24'
Select @MyDate.ToString() as MyDateTime
           , @MyDate.GetDate() as MyDate
           , @MyDate.GetTime() as MyTime
           , @MyDate.Year as MyYear
           , @MyDate.Month as MyMonth
          , @MyDate.Day as MyDay
          , @MyDate.Hour as MyHour
          , @MyDate.Minute as MyMinute
          , @MyDate.Second as MySecond
          , @MyDate.JalaliDateAdd('Year',1) as NextYear
          , @MyDate.JalaliDateAdd('Month',1) as NextMonth
          , @MyDate.JalaliDateAdd('Day',1) as NextDay
          , @MyDate.JalaliDateAdd('Hour',1) as NextHour
          , @MyDate.JalaliDateAdd('Minute',1) as NextMinute
          , @MyDate.JalaliDateAdd('Second',1) as NextSecond
که در نهایت خروجی کار به شکل زیر خواهد بود:

با این همه، همان‌سان که در پرس‌وجوی بالا هم می‌بینید؛ ناگزیر شدم تاریخ و زمان را خودم وارد کنم و هرآینه در واقعیت شما جهت پرس‌وجو روی زمان کنونی، ناگزیر به استفاده از یک تابع برای تبدیل تقویم میلادی به خورشیدی هستیم. به نظر شما بهتر نیست دست به کار شویم و تابعی برای تبدیل تاریخ میلادی به خورشیدی بنویسیم؟

برای این‌کار پروژه‌ای را که در دو درس 1 ساختیم باز کنید و سپس روی نام پروژه در Solution Explorer راست‌کلیک کرده و Add New Item را انتخاب کنید.

 
محتویات فایل بازشده را حذف کنید و دستورهای زیر را جای‌گزین کنید:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static JalaliDate GetCurrentDateTime()
    {
        System.Globalization.PersianCalendar pers = new System.Globalization.PersianCalendar();
        DateTime CurrentDate = DateTime.Now;
        JalaliDate jl;
        jl.Year = (Int16)pers.GetYear(CurrentDate);
        jl.Month = (byte)pers.GetMonth(CurrentDate);
        jl.Day = (byte)pers.GetDayOfMonth(CurrentDate);
        jl.Hour = (byte)pers.GetHour(CurrentDate);
        jl.Minute = (byte)pers.GetMinute(CurrentDate);
        jl.Second = (byte)pers.GetSecond(CurrentDate);
        return jl;
    }
}
بار دیگر پروژه را به روشی که در درس یک آموزش داده شد؛ Publish کنید. اکنون می‌توانیم تاریخ و زمان کنونی را در متغیری از نوع JalaliDate وارد کنیم.
Declare @MyDate JalaliDate = dbo.GetCurrentDateTime()
یا به این شکل تاریخ و زمان جاری را مشاهده کنیم:
Select dbo.GetCurrentDateTime().ToString()

دنباله دارد...
  • #
    ‫۱۱ سال و ۵ ماه قبل، شنبه ۱۴ اردیبهشت ۱۳۹۲، ساعت ۱۵:۰۴
    از دوستان اگه کسی نحوه استفاده این تکنیک رو توی EF Code First  میدونه لطفا مطلب رو Share کنه تا امکان استفاده این دسته از عزیزان هم از زحمتی که آقای قنادی کشیدن باشه.
    با تشکر.
    • #
      ‫۱۱ سال و ۵ ماه قبل، شنبه ۱۴ اردیبهشت ۱۳۹۲، ساعت ۱۵:۱۲
      public DateTime AddDate { set; get; }  
      
      [NotMapped]  // فیلد محاسباتی سمت برنامه که در بانک اطلاعاتی قرار نخواهد گرفت
      public string PersianDate
      {  
          get { return MyDateConverter(AddDate); }  
      }

      در code first از ویژگی NotMapped استفاده کنید تا بتونید با استفاده از تابع کمکی تبدیل تاریخ خودتون راحت این تبدیلات رو انجام بدید. در بانک اطلاعاتی DateTime استاندارد رو ذخیره کنید، در سمت کدها برای مسایل نمایشی از خاصیت PersianDate که NotMapped تعریف شده، میشه استفاده کرد. به علاوه روی DateTime استاندارد راحت میشه کوئری‌های LINQ رو اجرا کرد بدون محدودیت. زمانیکه مثلا یک List تهیه شد، قسمت بعدی، کار نمایشی است که از خاصیت NotMapped میشه کمک گرفت. این روش با تمام بانک‌های اطلاعاتی کار می‌کنه.

    • #
      ‫۱۱ سال و ۵ ماه قبل، شنبه ۱۴ اردیبهشت ۱۳۹۲، ساعت ۱۶:۱۱
      [Column(TypeName = "xml")]  
      public string XmlValue { get; set; }  
        
      [NotMapped]  
      public XElement XmlValueWrapper  
      {  
          get { return XElement.Parse(XmlValue); }  
          set { XmlValue = value.ToString(); }  
      }

      روش عمومی کار با نوع‌های خاصی که در EF تعریف نشدن، استفاده از ویژگی Column و مشخص کردن Type آن است؛ مانند مثالی که در بالا ملاحظه می‌کنید. البته این نوع خاص، در سمت کدها باید به صورت رشته تعریف شود. مثلا از سال 2005 به این طرف فیلد XML به SQL Server اضافه شده. اما نمی‌شود ازش در EF به همون شکل XML استفاده کرد. باید تبدیلش کنی به String تا قابل استفاده بشه. یک نمونه دیگرش نوع خاص Spatial هست که در نگارش‌های اخیر SQL Server اضافه شده (geography و geometry). این مورد فقط از EF 5.0 به بعد پشتیبانی توکاری ازش ارائه شده. یا برای hierarchyID در EF معادلی وجود نداره. برای تعریف این مورد نیز در یک مدل باید از string استفاده کرد.

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

  • #
    ‫۱۰ سال و ۱۲ ماه قبل، دوشنبه ۲۲ مهر ۱۳۹۲، ساعت ۰۲:۴۶
    با سلام
    پروژه ای که شرح دادین رو ایجاد و در SQL server 2012 ، Publish کردم و در جدول هم مقادیر تستی درج کردم.
    زمانی که جدول را در Object Browser با Mode ویرایش باز می‌کنم هیج مشکلی وجود ندارد  و داده‌ها درست نمایش داده می‌شوند اما زمانی که با دستورات T-SQL کار میکنم مقادیر را به صورت یک رشته از کاراکترها نمایش می‌دهد که نامفهوم می‌باشد.
    تصویر اجرای کوئری‌ها را میذارم لطفا راهنمایی کنید.

     

    • #
      ‫۱۰ سال و ۱۲ ماه قبل، دوشنبه ۲۲ مهر ۱۳۹۲، ساعت ۰۳:۳۴
      SQLCLR types به صورت پیش فرض با فرمت serialized binary value بازگشت داده می‌شوند.
       SELECT id, TestDate.ToString() FROM TestTable;
      در ابزارهای کوئری گرفتن ad-hoc مثل SSMS باید یک متد ToString را هم به انتهای نام ستون اضافه کنید تا مقدار نمایشی واضحی حاصل شود.