نظرات مطالب
Minimal API's در دات نت 6 - قسمت دوم - ایجاد مدل‌ها و Context برنامه
  1. با توجه به مزیت‌هایی که قبلاً در پیاده‌سازی سرویس محور برای IUnitOfWork در نظر گرفته می‌شد و به طور مفصل هم درباره آن بحث شد، در این نوع پیاده‌سازی آیا باید نگرش جدیدی به استفاده مستقیم از DbContext اصلی برنامه داشت؟
  2. برای استفاده از مطلب کار با چندین نوع بانک اطلاعاتی متفاوت در Entity Framework Core در حالت فوق و با توجه به حذف IUnitOfWork، آیا پیاده‌سازی زیر صحیح است:
namespace MinimalBlog.Dal.SqlServer

public class SqlServerDbContext : MinimalBlogDbContext
{
        //Sql Server Settings
}
namespace MinimalBlog.Dal.Sqlite

public class SqliteDbContext : MinimalBlogDbContext
{
        //Sqlite Settings
}
var connectionStringKey = Configuration.GetConnectionString("InUseKey");
var connectionString = Configuration.GetConnectionString(connectionStringKey);

switch (connectionStringKey)
{
    case "SqlServerConnection":
        services.AddScoped<MinimalBlogDbContext, SqlServerDbContext>();
        services.AddDbContext<SqlServerDbContext>(options => opt.UseSqlServer(connectionString));
        break;
    case "SqliteConnection":
        services.AddScoped<MinimalBlogDbContext, SqliteDbContext>();
        services.AddDbContext<SqliteDbContext>(options => options.UseSqlite(connectionString));
        break;
    default:
        throw new NotImplementedException($"`{connectionStringKey}` is not defined in `appsettings.json` file.");
}

نظرات مطالب
بازسازی کد: ارتباط یک طرفه و دو طرفه بین کلاس ها
بنده به هیچ کدام از این روش‌ها انتقادی نداشتم. تصمیم طراحی باید بر اساس شرایط پروژه اتخاد بشه. 
در مورد استفاده از navigation property 
در entity framework استفاده از Navigation property برعکس (در مثال شما کالکشن Orders در کلاس Customer) برای ایجاد یک رابطه یک به چند الزامی نیست. (برای ایجاد relation نیازی به حضوری این collection نیست و حضور خصوصیت Customer در کلاس Order کافی است) و در صورتی که شما از نظر کسب و کاری نیازی به چنین خصوصیتی نداشته باشید می‌توانید از ایجاد آن صرف نظر کنید. 
public class Order
{
    public int Id { get; set; }
    public Customer Customer { get; set; }
}
public class Customer
{
    public int Id { get; set; }
}
......

modelBuilder.Entity<Order>().HasRequired(ff => ff.Customer);


حضور خصوصیت Orders در کلاس Customer در مثال شما از نظر کسب و کاری به این معنی است که شما برای رسیدن به لیست سفارشات نیاز دارید که به شی مشتری دسترسی پیدا کنید. 
نکته اصلی این بازسازی کد اجتناب از استفاده بی مورد ارتباط دوطرفه است.
نظرات مطالب
صفحه بندی و مرتب سازی خودکار اطلاعات به کمک jqGrid در ASP.NET MVC
- یک سری micro orm مانند Dapper وجود دارند که اساس کار آن‌ها، کوئری نویسی و سپس دریافت اطلاعات از طریق لیست‌های جنریک (مانند روش نهایی کار در مثال جاری) است. بنابراین datatable را فراموش کنید و شروع کنید به استفاده از dapper یا peta poco (اگر نمی‌خواهید از Entity framework استفاده کنید).
- مهم این نیست که منبع داده‌ی شما به چه نحوی تهیه می‌شود. مهم این است که این گرید خاص و امثال آن (Kendo UI هم به همین صورت)، داده‌ها را با فرمت JSON دریافت می‌کنند. همچنین داده‌ها را با فرمت JSON به سمت سرور ارسال می‌کنند. بنابراین مطابق مثالی که زده شد، اطلاعات خودتان را تبدیل می‌کنید به فرمت new JqGridData و سپس آن‌را به صورت JSON بازگشت می‌دهید. همچنین در سمت کاربر، تمام تغییرات، با فرمت JSON به سمت سرور ارسال می‌شوند که این مورد و آنالیز آن در قسمت‌های بعدی این سری بررسی شده‌اند.
- در این سری مثال‌ها از امکانات توکار ASP.NET MVC برای بازگشت داده‌ها به صورت JSON استفاده شده‌است. اما jqGrid یا Kendo UI Grid و امثال آن‌ها اساسا هیچگونه وابستگی به فناوری‌های سمت سرور ندارند. بنابراین از یکی از روش‌های موجود بازگشت اطلاعات به فرمت JSON استفاده کنید. مهم هم نیست که برنامه‌ی شما ASP.NET MVC است یا وب فرم یا PHP یا هر چی. برای مثال از کتابخانه‌ی JSON.NET برای بازگشت اطلاعات به فرمت JSON استفاده کنید.
- علاوه بر این، روش‌های دیگری هم برای بازگشت اطلاعات به فرمت JSON وجود دارند. اطلاعات بیشتر
نظرات مطالب
استفاده از چندین بانک اطلاعاتی به صورت همزمان در EF Code First
امکان ساخت رشته‌ی اتصالی، به همراه ذکر صریح Provider مورد استفاده هم وجود دارد. چند مثال:
public static string CreateConnectionStringForSQLCe(string dbPath = @"|DataDirectory|\NerdDinners.sdf")
{
   SqlCeConnectionStringBuilder sqlConnection = new SqlCeConnectionStringBuilder();
   sqlConnection.Password = "9023fase93";
   sqlConnection.DataSource = dbPath;

   EntityConnectionStringBuilder connection = new EntityConnectionStringBuilder();
   connection.Metadata = @"res://*/NerdDinnersModel.csdl|res://*/NerdDinnersModel.ssdl|res://*/NerdDinnersModel.msl";
   connection.Provider = "System.Data.SqlServerCe.3.5";
   connection.ProviderConnectionString = sqlConnection.ToString();

   return connection.ToString();
}


public static string CreateConnectionStringForSQLServer()
{
   //Build an SQL connection string
   SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
   {
      DataSource = "MyPC", // Server name
      InitialCatalog = "db1",  //Database
      UserID = "user1",         //Username
      Password = "mypassword",  //Password
   };
 
   //Build an Entity Framework connection string
   EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder
   {
      Provider = "System.Data.SqlClient",
      Metadata =   "res://*/testModel.csdl|res://*/testModel.ssdl|res://*/testModel.msl",
      ProviderConnectionString = sqlString.ToString()
   };
   return entityString.ConnectionString;
}
این روش با EF code first هم کار می‌کند و در سازنده‌ی دوم کلاس Context که connectionString را می‌پذیرد، قابل استفاده‌است.
نظرات مطالب
EF Code First #2
لطف کنید سؤالی رو که مطرح می‌کنید در حیطه مطلب جاری عنوان شده باشد و خارج از آن نباشد.
سؤال شما هم بحث کلاینت سروری است و نه بحث کلاینت تنها که EF روی آن مشغول به کار است.
- می‌شود در متد Seed ایی که در بالا توضیح دادم در SQL Server تریگر درست کرد. (که مثلا اگر کاربر دیگری به شرط اینکه این کاربر جزو کاربران تعریف شده در خود SQL Server باشد نه در برنامه شما، اتفاق خاصی رخ دهد. برنامه شما هم بدیهی است باید سرور را مدام چک کند تا از این مساله مطلع شود)- SQL Server مبحثی دارد به نام Service Broker : (^). توسط آن می‌توان از طریق سرور به کلاینت اطلاع رسانی کرد. بازهم خارج است از بحث یک ORM. یا تمام ORMهای موجود. - EF مبحثی دارد به نام Concurrency check که اگر شخصی در شبکه بر روی رکوردی که همین الان شما مشغول به کار هستید، تغییری را ایجاد کرد، به شما اطلاع رسانی کند. (در قسمت‌های بعدی بحث خواهد شد). البته این هم خودکار نیست. لازم است یک رفت و برگشت به سرور انجام شود.- entity framework auditing هم میسر است. خودکار نیست. در همان کلاس Context فوق که از DbContext مشتق می‌شود می‌توان متد تحریف شده public override int SaveChanges را تعریف کرد. در اینجا می‌توان به تمام تغییراتی که قرار است اعمال شوند دسترسی داشت. مثلا آن‌ها را در یک جدول مجزا ثبت کرد. بدیهی است برنامه بعدا نیاز خواهد داشت از این جدول گزارشگیری کند.
نظرات مطالب
نحوه‌ی مشاهده‌ی خروجی SQL تولید شده توسط WCF RIA Services
سلام،
من یک زمانی از طرفداران نوشتن stored procedure بودم اما الان به دلایل ذیل نیستم:
- امنیت: تمام کوئری‌های تولیدی entity framework از نوع پارامتری هستند. این مورد یعنی عقیم سازی حملات تزریق اس کیوال . (بنابراین اگر کسی عنوان کند که با SP ما امنیت بیشتری داریم، باید عنوان کرد که اینجا هم به همین صورت است)
- سرعت: در نگارش‌های جدید اس کیوال سرور، با کوئری‌های پارامتری دقیقا مانند SP رفتار می‌شود. همان کش شدن execution plan و غیره. بنابراین اینجا هم از همان مزایای SP برخوردار هستیم و سرعت سیستم مطلوب است.
- مشکلات نگهداری SP :
شما می‌تونید ساختار جداول رو تغییر بدید بدون اینکه اس کیوال سرور به شما پیغام خطایی در مورد غیر معتبر شدن یک SP بدهد. شما می‌تونید حتی یک SP غیر معتبر را تا زمانیکه syntax مربوط به آن صحیح است تولید کنید. هر دو مورد در زمان اجرا، سبب از کار افتادن برنامه می‌شوند. اما با EF این مشکلات را ندارید. ساختار را که عوض کنید برنامه دیگر کامپایل نمی‌شود. این مورد در برنامه‌های بزرگ خیلی خیلی خوب است!
مورد دیگر: یک برنامه بزرگ با چند صد SP رو در نظر بگیرید. جدا نگهداری این‌ها پیدا کردن کدها در یک برنامه‌ی بزرگ عذاب است. طبقه بندی آن‌ها یک طرف، اعمال تغییرات از طرف دیگر.
- مورد دیگر که من دیدم در یک سری از سایت‌ها در مورد آن بحث می‌کنند این است که نباید business logic برنامه را داخل دیتابیس طراحی کرد. این مورد باید با کد نویسی داخل برنامه باشد. در اینجا هم باز EF یا موارد مشابه بهتر هستند.
- مورد دیگری که در SP ها مشکل ساز می‌شود به اشتراک گذاری آن در بین برنامه‌های مختلف است. هم خوب است. بالاخره کد نویسی کمتر می‌شود. هم بد است، از این لحاظ که شاید این SP نیاز به تغییر داشت و اینجا است که برنامه‌های دیگر مشکل پیدا می‌کنند.
مطالب
تغییر استراتژی ساخت مدل در EF5 و رفع مشکل WCF Ria
Entity framework 5 نسبت به نسخه‌های پیشین شاهد تغییرات بسیاری بوده است و مانند هر تغییر دیگری اینجا نیز ممکن است تغییرات ؛ باعث بروز مشکلاتی در روند توسعه نرم افزار شوند. EF در نسخه جدید خود در کدهای پشت صحنه Model به جای ObjectContext از DbContext که نسخه محدود شده ObjectContext می‌باشد استفاده می‌کند. همین امر به خودی خود باعث محدود شدن متدهای شئی Context شده است. متدها و خواصی که گاها برای انجام اعمال خاصی به آنها نیاز پیدا می‌کنیم ولی دیگر در دسترس نیستند. برای مثال برای یک برنامه خاص می‌خواستم مقدار CommandTimeout   را به صورت دستی برای شئی Context تنظیم کنم ؛ ولی کد زیر دیگر قابل استفاده نبود:
  context.CommandTimeout = 180;
همچنین این استفاده از DbContext در هنگام استفاده از WCF Ria در سیلورلایت باعث بروز مشکل شده و کلاس‌های مدل در هنگام تعریف Domain Service Class توسط WCF Ria قابل شناسایی نیستند.یعنی WCF RIA به صورت خودکار قادر به تشخیص کلاس‌های Model نمی‌باشد.
 

برای رفع این مشکل مراحل زیر را انجام دهید:

  1. دو فایل tt موجود در مدل را حذف نمایید.

 2. مدل را در حالت Designer باز کنید و در بخش خصوصیات مدل مقدار Code Generation Strategy را از None  به Default تغییر دهید.

3. پروژه را Rebuild نمایید. مشکل به همین سادگی رفع می‌شود.
حالا با خیال راحت می‌توانید کلاس‌های مدل را در پنجره Add New Domain Service Class مشاهده نمایید.
 

مطالب
Entity Framework و InnerException
در Entity Framework  بیشتر استثناها تودرتو هستند و ما باید تمام استثناها رو بررسی کنیم تا به پیغام اصلی خطا برسیم. با استفاده از تکه کد زیر به راحتی می‌تونیم استثناها رو پیمایش کنیم و متن خطا را مشخص کنیم.
                catch (Exception ex)
                {
                    StringBuilder errorMsg = new StringBuilder();
                    for (Exception current = ex; current != null; current = current.InnerException)
                    {
                        if (errorMsg.Length > 0)
                            errorMsg.Append("\n");

                        errorMsg.Append(current.Message.Replace("See the inner exception for details.", string.Empty));
                    }
                    // log
                    errorMsg.ToString();
                }
برای استفاده در قسمت‌های مختلف برنامه یک متد الحاقی مانند زیر تعریف می‌کنیم: 
        public static string ExceptionToString(this Exception ex)
        {
            StringBuilder errorMsg = new StringBuilder();
            for (Exception current = ex; current != null; current = current.InnerException)
            {
                if (errorMsg.Length > 0)
                    errorMsg.Append("\n");
                errorMsg.Append(current.Message.
                    Replace("See the inner exception for details.", string.Empty));
            }
            return errorMsg.ToString();
        }
catch (Exception ex)
                {
                    // log
                    ex.ExceptionToString();
                }
مطالب
ObservableCollection در Entity Framework
در مبحث استفاده از خاصیت Local در Entity Framework  ملاحظه نمودید که خاصیت Local به راحتی می‌تواند از رفت و آمدهای بی جهت به دیتابیس جلوگیری کند.
حال قصد معرفی یک collection  را به نام ObservableCollection دارم.   
همانطور که از نامش پیداست برای مشاهده و تحت نظر قرار دادن داده‌های اضافه شده یا پاک شده کاربرد دارد. به کد زیر دقت کنید.
    private static void ListenToLocalChanges()
    {
        using (var context = new BreakAwayContext())
        {
            context.Destinations.Local.CollectionChanged += (sender, args) =>
            {
                if (args.NewItems != null)
                {
                    foreach (Destination item in args.NewItems)
                    {
                        Console.WriteLine("Added: " + item.Name);
                    }
                }
                if (args.OldItems != null)
                {
                    foreach (Destination item in args.OldItems)
                    {
                        Console.WriteLine("Removed: " + item.Name);
                    }
                }
            };
            context.Destinations.Load();
        }
    }
در بالا به وسیله یک event handler جدید به collection محلی ما (Local) نظر می‌اندازد و در صورت اضافه شدن یا حذف موجودیتی، آن را به ما نشان می‌دهد. فقط توجه کنید که اگر نیاز دارید در صفحه‌ای این تغییرات را مشاهده کنید باید عمل Refresh کردن صفحه را چه به صورت دستی یا با نوشتن کد خودتان مدیریت کنید. البته با استفاده از WPF میتوان (استفاده  از کنترل‌های مانند ListBox ) این کار را به صورت خودکار انجام داد.
مطالب
راه‌های تامین Product backlog در تیم‌های مایکروسافت

شاید مهم‌ترین رخداد وبلاگ‌های مرتبط با برنامه نویسی ایرانی در نیمه دوم سال 89، انتشار کتابچه اسکرام و XP ساده شده به زبان فارسی باشد. یکی از فصول این کتابچه، به روش‌های تهیه Product backlog اختصاص دارد که جزو قسمت‌های اولیه پروسه اسکرام است و می‌شود به آن یک to-do list الویت بندی شده هم گفت. تیم‌های مایکروسافت هم به نظر کمابیش بر همین اساس مدیریت می‌شوند. در ادامه لیستی از سایت‌هایی را مشاهده خواهید کرد که این تیم‌های گوناگون درون مایکروسافت از آن‌ها جهت تامین product backlog خود استفاده می‌کنند؛ کاربران (که در اینجا همان برنامه نویس‌ها هستند) با مراجعه به این سایت‌ها نیازهای خود را عنوان کرده و همچنین با وجود امکانات رای دهی، امکان تهیه لیست‌هایی اولویت بندی شده هم وجود دارد:




و ...


تیم‌های خارج از مایکروسافت هم از این ایده استفاده می‌کنند؛ مانند: