بازخوردهای پروژه‌ها
Entity Framework
در مورد معماری entity framework اگر مطالب بیشتری ارائه کنید بسیار خوب و مناسب است
مطالب دوره‌ها
نگاهی به گزینه‌های مختلف مهیای جهت میزبانی SignalR
حداقل چهار گزینه برای Hosting سرویس‌های Hub برنامه‌های مبتنی بر SignalR وجود دارند که تا به اینجا، مورد دوم آن بیشتر بررسی گردید:
1) OWIN
2) ASP.NET Hosting
3) Self Hosting
4) Cloud و ویندوز Azure

1) OWIN
اگر به اسمبلی‌های همراه با SignalR دقت کنید، یکی از آن‌ها Microsoft.AspNet.SignalR.Owin.dll نام دارد. OWIN مخفف Open web server interface for .NET است و کار آن ایجاد لایه‌ای بین وب سرورها و برنامه‌های وب می‌باشد. یکی از اهداف مهم آن ترغیب دنیای سورس باز به تهیه ماژول‌های مختلف قابل استفاده در وب سرورهای دات نتی است. نکته‌ی مهمی که در SignalR و کلیه میزبان‌های آن وجود دارد، بنا شدن تمامی آن‌ها برفراز OWIN می‌باشد.

2) ASP.NET Hosting
بدون شک، میزبانی ASP.NET از هاب‌های SignalR، مرسوم‌ترین روش استفاده از این فناوری می‌باشد. این نوع میزبانی نیز برفراز OWIN بنا شده است. نصب آن توسط اجرای دستور پاور شل ذیل در یک پروژه وب صورت می‌گیرد:
 PM> Install-Package Microsoft.AspNet.SignalR

3) خود میزبانی یا Self hosting
خود میزبانی نیز برفراز OWIN تهیه شده است و برای پیاده سازی آن نیاز است وابستگی‌های مرتبط با آن، از طریق NuGet به کمک فرامین پاور شل ذیل دریافت شوند:
 PM> Install-Package Microsoft.AspNet.SignalR.Owin
PM> Install-Package Microsoft.Owin.Hosting -Pre
PM> Install-Package Microsoft.Owin.Host.HttpListener -Pre
مواردی که با پارامتر pre مشخص شده‌اند، در زمان نگارش این مطلب هنوز در مرحله بتا قرار دارند اما برای دموی برنامه کفایت می‌کنند.
مراحل تهیه یک برنامه ثالث (برای مثال خارج از IIS یا یک وب سرور آزمایشی) به عنوان میزبان Hubs مورد نیاز به این شرح هستند:
الف) کلاس آغازین میزبان باید با پیاده سازی اینترفیسی به نام IAppBuilder تهیه شود.
ب) مسیریابی‌های مورد نیاز تعریف گردند.
ج) وب سرور HTTP یا HTTPS توکار برای سرویس دهی آغاز گردد.

باید توجه داشت که در این حالت برخلاف روش ASP.NET Hosting، سایر اسمبلی‌های برنامه جهت یافتن Hubهای تعریف شده، اسکن نمی‌شوند. همچنین هنگام کار با jQuery مباحث عنوان شده در مورد تنظیم دسترسی‌های Cross domain نیز باید در اینجا اعمال گردند. به علاوه اجرای وب سرور توکار آن به دلایل امنیتی، نیاز به دسترسی مدیریتی دارد.

برای پیاده سازی یک نمونه، به برنامه‌ای که تاکنون تهیه کرده‌ایم، یک پروژه کنسول دیگر را به نام ConsoleHost اضافه کنید. البته باید درنظر داشت در دنیای واقعی این نوع برنامه‌ها را عموما از نوع سرویس‌های ویندوز NT تهیه می‌کنند.
در ادامه سه فرمان پاور شل یاد شده را برای افزودن وابستگی‌های مورد نیاز فراخوانی نمائید. همچنین باید دقت داشت که این دستور بر روی پروژه جدید اضافه شده باید اجرا گردد.
using System;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.Owin.Hosting;
using Owin;

namespace SignalR02.ConsoleHost
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapHubs(new HubConfiguration { EnableCrossDomain = true });
        }
    }

    [HubName("chat")]
    public class ChatHub : Hub
    {
        public void SendMessage(string message)
        {
            var msg = string.Format("{0}:{1}", Context.ConnectionId, message);
            Clients.All.hello(msg);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (WebApplication.Start<Startup>("http://localhost:1073/"))
            {
                Console.WriteLine("Press a key to terminate the server...");
                Console.Read();
            }
        }
    }
}
سپس یک کلاس Startup را با امضایی که مشاهده می‌کنید تهیه نمائید. در اینجا مسیریابی و تنظیمات دسترسی از سایر دومین‌ها مشخص شده‌اند. در ادامه یک Hub نمونه، تعریف و نهایتا توسط WebApplication.Start، این وب سرور راه اندازی می‌شود. اکنون اگر برنامه را اجرا کرده و به مسیر http://localhost:1073/signalr/hubs مراجعه کنید، فایل پروکسی تعاریف متادیتای مرتبط با سرور قابل مشاهده خواهد بود.
سمت کلاینت استفاده از آن هیچ تفاوتی نمی‌کند و با جزئیات آن پیشتر آشنا شده‌اید؛ برای مثال در کلاینت جی‌کوئری خاصیت connection.hub.url باید به مسیر جدید سرور هاب تنظیم گردد تا اتصالات به درستی برقرار شوند.


دریافت پروژه کامل مرتبط با این 4 قسمت (البته بدون فایل‌های باینری آن، جهت کاهش حجم 32 مگابایتی)
  SignalRSamples.zip
نظرات مطالب
شروع به کار با EF Core 1.0 - قسمت 3 - انتقال مهاجرت‌ها به یک اسمبلی دیگر
نکته تکمیلی‌تر جهت ایجاد sln در این حالت استفاده از دستور زیر برای ساخت یک solution جدید با نام پوشه والد است:
dotnet new sln
سپس برای هر یکی از فایل‌های پروژه یک دایرکتوری ایجاد کرده و پروژه مربوط به هر کدام را داخل آن ایجاد میکنیم.

 سپس از طریق دستور زیر آن‌ها را در sln ثبت می‌نماییم: 
>dotnet sln add mymvc/mymvc.csproj
Project `mymvc\mymvc.csproj` added to the solution.
>dotnet sln add models/models.csproj
Project `models\models.csproj` added to the solution.
نظرات مطالب
شروع به کار با EF Core 1.0 - قسمت 3 - انتقال مهاجرت‌ها به یک اسمبلی دیگر
اگر علاقمند بودید تا کار افزودن مهاجرت‌ها، به همراه تولید خودکار نام فایل، بر اساس تاریخ و ساعت روز باشد، می‌توان از دستورات ذیل در خط فرمان استفاده کرد (و یا درست کردن یک فایل bat. برای آن):
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c_%%a_%%b)
For /f "tokens=1-2 delims=/:" %%a in ("%TIME: =0%") do (set mytime=%%a%%b)
dotnet ef --configuration Release --startup-project ../ProjName/ migrations add V%mydate%_%mytime%
مطالب
دقت نوع داده‌ی decimal در SQL Server و EF Core
از نوع داده‌ا‌ی decimal در SQL Server، بیشتر برای انجام کارهای تجاری و ذخیره‌ی قیمت‌ها و مبالغ استفاده می‌شود؛ جائیکه اعداد و ارقام خیلی سریع بزرگ می‌شوند و گاهی از اوقات ممکن است به همراه اعشار هم باشد. اما ... کار با آن‌ها در SQL Server نیازمند نکات ویژه‌ای است که اگر ندید گرفته شوند، محاسبات نادرستی را سبب خواهند شد!


مفهوم تعریف نوع decimal پیش‌فرض در SQL Server

فرض کنید از EF پیش از EF Core استفاده می‌کنید که به صورت پیش‌فرض، نوع System.Decimal را در مدل‌های شما به همان decimal در SQL Server نگاشت می‌کند. فکر می‌کنید در این حالت خروجی کوئری‌های زیر چه چیزی خواهد بود؟
select '0.4400' as Expected , cast(0.4400 as decimal) as Actual
select '1.3200' as Expected, cast(1.3200 as decimal) as Actual
select '1.7600' as Expected, cast(1.7600 as decimal) as Actual
select '65.0000' as Expected, cast(65.0000 as decimal) as Actual
select '99.50' as Expected, cast(99.50 as decimal) as Actual

این خروجی را در تصویر ذیل مشاهده می‌کنید. در اینجا خصوصا به مورد صفر دقت کنید:


 علت اینجا است که از دیدگاه SQL Server، نوع decimal پیش‌فرض، دقیقا به معنای decimal(18,0) است که به آرگومان اول آن، precision و به آرگومان دوم آن، scale می‌گویند. یعنی حداکثر چه تعداد رقم دسیمال، پیش از ممیز و چه تعداد عدد دسیمال، پس از ممیز قرار است در این نوع داده ذخیره شوند.
بنابراین باتوجه به اینکه در حالت پیش‌فرض، مقدار scale و یا همان تعداد ارقام مجاز پس از ممیز، صفر است، عدد ارائه شده، به نزدیک‌ترین عدد صحیح ممکن، گرد خواهد شد.

به همین جهت برای رفع این مشکل، باید دقیقا مشخص کرد که scale نوع داده‌ای decimal مدنظر چیست. برای مثال می‌توان از decimal(10,4) استفاده کرد که در اینجا، نتایج صحیحی را ارائه می‌دهد:


همچنین به عنوان تمرین، مثال زیر را حل کنید!
 select iif(cast(0.1 + 0.2 as decimal) = 0, 'true', 'false')

بنابراین باید به‌خاطر داشت، اگر از EF 6x (پیش از EF Core) استفاده می‌شود، حتما نیاز است مقادیر precision و scale را دقیقا مشخص کنیم؛ وگرنه حالت پیش‌فرض آن decimal(18,0) است:
modelBuilder.Properties<decimal>().Configure(x => x.HasPrecision(18, 6));


رفتار EF Core با نوع داده‌ای decimal

رفتار EF Core با نوع داده‌ای decimal بهبود یافته و حالت پیش‌فرض آن، بدون هیچگونه تنظیمی، نگاشت به decimal(18,2) است. به علاوه اگر این پیش‌فرض را هم تغییر ندهیم، در حین اعمال Migration، پیام اخطاری را نمایش می‌دهد:
No store type was specified for the decimal property 'Price' on entity type 'Product'.
This will cause values to be silently truncated if they do not fit in the default precision and scale.
Explicitly specify the SQL server column type that can accommodate all the values in 'OnModelCreating'
using 'HasColumnType', specify precision and scale using 'HasPrecision',
or configure a value converter using 'HasConversion'.
اگر می‌خواهید دیگر این اخطار نمایش داده نشود، می‌توان از EF Core 6x به بعد، به صورت زیر و سراسری، تنظیم زیر را اعمال کرد:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Properties<decimal>().HavePrecision(18, 6);
}
و یا روش دیگر تنظیم آن، استفاده از ویژگی جدید [Precision(18, 2)] است که می‌توان آن‌ها را بر روی خواص decimal قرار داد. اگر از نگارش‌های پیش‌از EF Core 6x استفاده می‌کنید، می‌توان از ویژگی [Column(TypeName = "decimal(5, 2)")] نیز استفاده کرد.




دو مطلب مرتبط
- از نوع‌های داده‌ا‌ی float و یا double در مدل‌های EF خود استفاده نکنید.
- همیشه مراقب بزرگ شدن اعداد و مبالغ و جمع نهایی آن‌ها باشید!