مطالب
پلاگین DataTables کتابخانه jQuery - قسمت دوم
در قسمت قبلی شما را با DataTables آشنا کردم. به طور خلاصه نحوه اعمال کردن DataTables به یک جدول ساده html را گفتیم که با این کار به صورت پیش فرض، امکاناتی مثل فیلتر کردن داده ها، صفحه بندی و مرتب سازی آنها و نیز اعمال شدن استایل‌های css به همین جدول html خام اضافه می‌شود. نکته مهم در مثال قبلی این بود که داده‌های درون این جدول با کدنویسی خام html فراهم شدند، اما این را در نظر داشته باشید که اکثریت مواقع باید داده‌ها از یک بانک اطلاعاتی دریافت شوند و سپس درون جدول قرار بگیرند.

در این قسمت سعی خواهیم کرد تا منبع داده جدول را یک آرایه جاوا اسکریپتی و سپس کالکشنی از آبجکتهای جاوا اسکریپتی (json) در نظر بگیریم و نیز برخی ویژگی‌های پیش فرض پلاگین را غیر فعال نمائیم.

فرض کنید می‌خواهید لیستی از اطلاعات دانشجویان شامل نام (FirstName)، نام خانوادگی (LastName)، و سن (Age) را نمایش دهید. اطلاعات قرار است در جدول زیر قرار بگیرند:
<table id="std-grid">
      <thead>
           <th>نام</th>
           <th>نام خانوادگی</th>
           <th>سن</th>
     </thead>
     <tbody>
                
     </tbody>
</table>


مشاهده می‌کنید که این جدول فقط شامل قسمت header است و در بدنه آن هیچ سطری قرار نگرفته است. در این مثال اطلاعات از یک آرایه جاوا اسکریپتی باید خوانده شوند و تبدیل به html شده و در نهایت درون قسمت <tbody></tbody> آن تزریق شوند. خوشبختانه DataTables برای این کار امکانات آماده ای را در اختیار قرار می‌دهد. این کار بدین صورت قابل انجام است:
<script>        
        $(document).ready(function() {
            $('#std-grid').dataTable({
                "aaData": [
                        ["پژمان", "پارسائی", "24"],
                        ["سعید", "الیاسی", "25"],
                        ["محمد رضا", "گلزار", "20"],
                        ["آرش", "ایرانی", "19"],
                        ["مرتضی", "فرمانی", "22"],
                        ["سعید", "حمیدیان", "23"],
                        ["امین", "پارسانیا", "23"],
                        ["محمد امین", "فقیهی", "24"],
                        ["محمد", "خرمی", "25"],
                        ["سینا", "امیریان", "20"],
                        ["آرش", "ایرانی", "19"],
                        ["وحید", "فرزانه", "22"],
                        ["امیر علی", "فرمانی", "23"],
                        ["امین", "حسینی", "23"],
            });
        });
        
    </script>

شرح کد:
aaData : یک آرایه دو بعدی (که به آن ماتریس یا آرایه ای از آرایه‌ها هم گفته می‌شود) است که مقادیر سلول هایی را نشان می‌دهد که در جدول قرار خواهند گرفت. تعداد ستون‌ها در این آرایه دو بعدی باید با تعداد ستون‌های جدول html متناظر یکسان باشند.

در مثال بالا از یک ماتریس به عنوان منبع داده استفاده شد. منبع داده می‌تواند به فرمت json نیز باشد. البته در این صورت باید ستون‌های جدول html را هم به پلاگین معرفی کنید، بدین صورت:
$(document).ready(function() {            
            $('#std-grid').dataTable({
                "aaData": [
                    {"FirstName" : "پژمان", "LastName" : "پارسائی", "Age" : "24"},
                    { "FirstName": "سعید", "LastName": "الیاسی", "Age": "25" },
                    { "FirstName": "محمد رضا", "LastName": "گلزار", "Age": "24" },
                    { "FirstName": "آرش", "LastName": "ایرانی", "Age": "24" },
                    { "FirstName": "مرتضی", "LastName": "فرمانی", "Age": "24" },
                    { "FirstName": "سعید", "LastName": "حمیدیان", "Age": "24" },
                    { "FirstName": "امین", "LastName": "پارسانیا", "Age": "24" },
                    { "FirstName": "محمد امین", "LastName": "فقیهی", "Age": "24" },
                    { "FirstName": "محمد", "LastName": "خرمی", "Age": "24" },
                    { "FirstName": "سینا", "LastName": "امیریان", "Age": "24" },
                    { "FirstName": "آرش", "LastName": "ایرانی", "Age": "24" },
                    { "FirstName": "وحید", "LastName": "فرزانه", "Age": "24" },
                    { "FirstName": "امیر علی", "LastName": "فرمانی", "Age": "24" },
                    { "FirstName": "امین", "LastName": "حسینی", "Age": "24" },
                ],
                "aoColumns": [
                      { "mDataProp": "FirstName" },
                      { "mDataProp": "LastName" },
                      { "mDataProp": "Age" }
                ]
            });
        });

aaData : همان طور که گفته شد در این قسمت دیتاهای درون جدول آورده می‌شوند و در این مثال آنها به فرمت json نوشته شده اند.
aoColumns : در این قسمت باید اسم ستون‌های جدول ذکر شوند.


غیرفعال کردن بعضی از ویژگی‌های پیش فرض DataTables

همان طور که گفته شد پلاگین DataTables به صورت پیش فرض ویژگی‌های مرتب سازی (sorting)، صفحه بندی (paging)، فیلتر کردن داده‌ها (filtering)، و غیره را به جدول مورد نظرش اعمال می‌کند. و بدین صورت قابل تغییر است:
$('#std-grid').dataTable({
          "bPaginate": false,
          "bLengthChange": false,
          "bFilter": false,
          "bSort": false,
          "bInfo": true,
          "bAutoWidth": false
});

bPaginate : بیان می‌کند آیا صفحه بندی سطرهای جدول فعال باشد یا نه.
bLengthChange : در صورتی که قابلیت صفحه بندی فعال باشد ، بیان می‌کند که کاربر بتواند اندازه صفحه را تغییر دهد یا نه.
bFilter : بیان می‌کند آیا قابلیت فیلتر کردن داده‌ها فعال باشد یا نه.
bSort : بیان می‌کند قابلیت مرتب سازی داده‌های جدول فعال باشد یا نه.
bInfo : بیان می‌کند که قسمت info زیر گرید نشان داده شود یا نه (در این قسمت اطلاعاتی راجع به تعداد کل رکوردهای بایند شده به جدول و نیز رکوردهای درون صفحه جاری نشان داده می‌شود)
bAutoWidth : در صورتی که این گزینه فعال باشد اندازه عرض هر ستون به صوتر خودکار توسط DataTables مقدار دهی خواهد شد.

مقدارهای قابل قبول برای هر کدام از این خصوصیات : true یا false

کدهای مربوط به این مثال را می‌توانید از لینک زیر دریافت کنید:
DataTables-DoteNetTips-Tutorial-02.zip 
مطالب
Image Annotations
می‌خواهیم با تغییر jQuery Image Annotation  این پلاگین و برای asp.net استفاده کنیم

ایجاد دیتابیس
ابتدا یک دیتابیس به نام Coordinates  ایجاد کنید و سپس جدول زیر رو ایجاد کنید
USE [Coordinates]
GO
CREATE TABLE [dbo].[Coords2](
[top] [int] NULL,
[left] [int] NULL,
[width] [int] NULL,
[height] [int] NULL,
[text] [nvarchar](50) NULL,
[id] [uniqueidentifier] NULL,
[editable] [bit] NULL
) ON [PRIMARY]
GO

ایجاد کلاس Coords برای خواندن و ذخیره اطلاعات
public class Coords
{
    public string top;
    public string left;
    public string width;
    public string height;
    public string text;
    public string id;
    public string editable;

    public Coords(string top, string left, string width, string height, string text, string id, string editable)
    {
        this.top = top;
        this.left = left;
        this.width = width;
        this.height = height;
        this.text = text;
        this.id = id;
        this.editable = editable;


    }
}
فرم اصلی برنامه شامل 3 وب سرویس به شرح زیر می‌باشد

1-GetDynamicContext 
این متد در زمان لود اطلاعات از دیتابیس استفاده می‌شود (وقتی که postback صورت می‌گیرد)
[WebMethod]
    public static List<Coords> GetDynamicContext(string entryId, string entryName)
    {
        List<Coords> CoordsList = new List<Coords>();

        string connect = "Connection String";
        using (SqlConnection conn = new SqlConnection(connect))
        {
            string query = "SELECT [top], [left], width, height, text, id, editable FROM  Coords2";
            using (SqlCommand cmd = new SqlCommand(query, conn))
            {
                conn.Open();
                using (SqlDataReader reader=cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        CoordsList.Add(new Coords(reader["top"].ToString(), reader["left"].ToString(),
                                                  reader["width"].ToString(), reader["height"].ToString(),
                                                  reader["text"].ToString(), reader["id"].ToString(),
                                                  reader["editable"].ToString()));
                    }
                }
               
               conn.Close();
            }
        }

         return CoordsList;


    }

2,3 -SaveCoordsو DeleteCoords 
این دو متد هم واسه ذخیره و حذف می‌باشند که نکته خاصی ندارند و خودتون بهینه اش کنید(در فایل ضمیمه موجودند)

تغییر فایل jquery.annotate.js  جهت فراخوانی وب سرویس ها
فقط لازمه که سه قسمت زیر رو در فایل اصلی تغییر بدید
$.fn.annotateImage.ajaxLoad = function (image) {
        ///<summary>
        ///Loads the annotations from the "getUrl" property passed in on the
        ///     options object.
        ///</summary>
      
        $.ajax({
            type: "POST",
            contentType: "application/json; charset=utf-8",
            url: "Default.aspx/GetDynamicContext",
            data: "{'entryId': '" + 1 + "','entryName': '" + 2 + "'}",
            dataType: "json",
            success: function (msg) {
                image.notes = msg.d;
                $.fn.annotateImage.load(image);
            }
        });
};

 $.fn.SaveCoords = function (note) {
        $.ajax({
            type: "POST",
            contentType: "application/json; charset=utf-8",
            url: "Default.aspx/SaveCoords",
            data: "{'top': '" + note.top + "','left': '" + note.left + "','width': '" + note.width + "','height': '" + note.height + "','text': '" + note.text + "','id': '" + note.id + "','editable': '" + note.editable + "'}",
            dataType: "json",
            success: function (msg) {
                note.id = msg.d;
             }
        });
 };
$.fn.annotateView.prototype.edit = function () {
///<summary>
///Edits the annotation.
///</summary>
if (this.image.mode == 'view') {
this.image.mode = 'edit';
var annotation = this;
// Create/prepare the editable note elements
var editable = new $.fn.annotateEdit(this.image, this.note);
$.fn.annotateImage.createSaveButton(editable, this.image, annotation);
// Add the delete button
var del = $('<a>حذف</a>');
del.click(function () {
var form = $('#image-annotate-edit-form form');
$.fn.annotateImage.appendPosition(form, editable)
if (annotation.image.useAjax) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "Default.aspx/DeleteCoords",
// url: annotation.image.deleteUrl,
// data: form.serialize(),
data: "{'id': '" + editable.note.id + "'}",
dataType: "json",
success: function (msg) {
// image.notes = msg.d;
// $.fn.annotateImage.load(image);
},
error: function (e) { alert("An error occured deleting that note.") }
});
}
annotation.image.mode = 'view';
editable.destroy();
annotation.destroy();
});
editable.form.append(del);
$.fn.annotateImage.createCancelButton(editable, this.image);
}
};
این پروژه شامل یه سری فایل css هم هست که می‌تونید کل پروژه رو از  اینجا دانلود کنید
نظرات مطالب
EF Code First #7
با سلام
اگر ما این  چنین ساختار را داشته باشیم مانند مثال ذکر شده در این پست ، در مورد قسمت زیر
public CustomerConfig()
        {
            // many-to-many
            this.HasMany(p => p.Roles)
                .WithMany(t => t.Customers)
                .Map(mc =>
                   {
                       mc.ToTable("RolesJoinCustomers");
                       mc.MapLeftKey("RoleId");
                       mc.MapRightKey("CustomerId");
                   });
        }
}
با حذف یک Customer و یا Role ، رکورد‌های مربوط به آن در جدول RolesJoinCustomers به صورت خود کار حذف می‌شود؟ اگر نه ، راه حل چیست ؟ چون من برای حذف رکورد ، با error برخورد میکنم
مورد دوم : اگر یک customer به عنوان مثال با تعدادی customer دیگر در ارتباط باشد(با تعدادی customer نه با یک customer)  در این صورت چگونه باید پیاده سازی شود ؟ در صورت یک Customer ، رکورد‌های مربوط به آن به صورت خود کار حذف می‌شود؟ اگر نه ، راه حل چیست ؟ 
با تشکر فراوان
مطالب
روشی برای مقایسه‌ی مقادیر تمام خواص دو شیء در آزمون‌های واحد
در زمان نوشتن تست‌های مختلف (Unit - Integration - UI) گاهی اوقات پیش می‌آید که بخواهید تمامی خصوصیت‌های یک شیء را تایید کنید. معمولا نوشتن اعتبارسنجی برای همه خصوصیت‌ها و همین طور پیام‌های استثناء برای هر یک در زمان عدم تایید اعتبار، کار بسیار زمانبری است. در این مقاله به شما نشان خواهم داد که چگونه با نوشتن یک اعتبارسنج عمومی از اتلاف زمان زیادی جلوگیری کنید.

با استفاده از کلاس زیر می‌توان کار اعتبارسنجی را با استفاده از Reflection به راحتی انجام داد. در اینجا برای اعتبارسنجی DateTime از کلاس DateTimeAssert استفاده کرده‌ایم.
public class PropertiesValidator<TK, T> where T : new() where TK : new()
{
    static TK _instance;

    public static TK Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new TK();
            }
            return _instance;
        }
    }

    public void Validate(T expectedObject, T realObject, params string[] propertiesNotToCompare)
    {
        var properties = realObject.GetType().GetProperties();
        foreach (var currentRealProperty in properties)
        {
            if (!propertiesNotToCompare.Contains(currentRealProperty.Name))
            {
                var currentExpectedProperty = expectedObject.GetType().GetProperty(currentRealProperty.Name);
                var exceptionMessage = $"The property {currentRealProperty.Name} of class {currentRealProperty.DeclaringType?.Name} was not as expected.";

                if (currentRealProperty.PropertyType != typeof(DateTime) && currentRealProperty.PropertyType != typeof(DateTime?))
                {
                    Assert.AreEqual( currentExpectedProperty.GetValue( expectedObject,
                                                                        null ),
                                        currentRealProperty.GetValue( realObject,
                                                                    null ),
                                        exceptionMessage );
                }
                else
                {
                    DateTimeAssert.Validate( currentExpectedProperty.GetValue( expectedObject,
                                                                                null ) as DateTime?,
                                                currentRealProperty.GetValue( realObject,
                                                                            null ) as DateTime?,
                                                TimeSpan.FromMinutes( 5 ) );
                }
            }
        }
    }
}


طرز استفاده

فرض کنید مدلی داریم با این مشخصات:
public class ObjectToAssert
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime LastVisit { get; set; }
}
و دو نمونه از آن را ایجاد کرده ایم:
var expectedObject = new ObjectToAssert
                        {
                            FirstName = "Vahid",
                            LastName = "Mohammad Taheri",
                            LastVisit = new DateTime( 2016, 11, 14, 0, 10, 50 )
                        };
var actualObject = new ObjectToAssert
                        {
                            FirstName = "Vahid",
                            LastName = "Mohammad Taheri",
                            LastVisit = new DateTime( 2016, 11, 14, 0, 13, 50 )
                        };
کلاسی را با ارث بری از PropertiesValidator ایجاد می‌کنیم:
public class ObjectToAssertValidator : PropertiesValidator<ObjectToAssertValidator, ObjectToAssert>
{
    public void Validate(ObjectToAssert expected, ObjectToAssert actual)
    {
        this.Validate(expected, actual, "FirstName");
    }
}

نکته
: در صورتی که می‌خواهید خصوصیتی را استثناء کنید از اعتبارسنجی، می‌توانید آن‌را به عنوان پارامتر سوم به بعد به تابع Validate ارسال کنید. طبق کد بالا FirstName به صورت استثناء تعریف شده است.


اکنون دو نمونه ساخته شده از ObjectToAssert بالا را با فراخوانی دستور زیر اعتبارسنجی می‌کنیم:
ObjectToAssertValidator.Instance.Validate(expectedObject, actualObject);
اشتراک‌ها
سری آموزش T-SQL

آموزش T-SQL - جلسه هفتاد و شش - YouTube 

سری آموزش T-SQL
نظرات مطالب
مهارت‌های تزریق وابستگی‌ها در برنامه‌های NET Core. - قسمت ششم - دخالت در مراحل وهله سازی اشیاء توسط IoC Container
با استفاده از ویژگی open generics قابل پیاده سازی است:
services.AddTransient(typeof(Lazy<>), typeof(LazyFactory<>));

class LazyFactory<T> : Lazy<T> where T : class
{
    public LazyFactory(IServiceProvider provider)
        : base(() => provider.GetRequiredService<T>())
    {
    }
}
به این صورت هر نوعی، قابلیت وهله سازی و دریافت Lazy را هم پیدا می‌کند.
نظرات مطالب
EF Code First #12
یک ToList به آخر آن اضافه کنید:
public class MyContext : DbContext, IUnitOfWork
    {
        // ...
        public IList<T> GetRows<T>(string sql, params object[] parameters) where T: class
        {
            return this.Database.SqlQuery<T>(sql, parameters).ToList();
        }
    }