نظرات مطالب
مروری بر کدهای کلاس SqlHelper
یک سری ویدیوی آزموشی به روز و با کیفیت در این زمینه از سایت pluralsight موجود است. در گوگل جستجو کنید قابل دریافت هستند.
مطالب
شروع به کار با EF Core 1.0 - قسمت 3 - انتقال مهاجرت‌ها به یک اسمبلی دیگر
در قسمت قبل، تغییرات Migrations، در EF Core 1.0 بررسی و گردش کاری آن به همراه مثال‌هایی ارائه شدند. در این قسمت یک سری از نکات تکمیلی EF Core Migrations را بررسی خواهیم کرد.


انتقال Context و Migrations به یک اسمبلی دیگر

تا اینجا اگر مثال بررسی شده را دنبال کرده باشید، دو پوشه‌ی Entities و Migrations را به همراه فایل‌‌های موجودیت‌ها، Context برنامه و Migrations آن‌ها، در همان پروژه‌ی اصلی برنامه، خواهید داشت:


در ادامه قصد داریم بانک اطلاعاتی آزمایشی برنامه را drop کرده، پوشه‌ی Migrations را حذف و صرفا دو فایل ApplicationDbContextSeedData و DBInitialization آن‌را نگه داریم.
کلاس Person را به اسمبلی جدید Entities و کلاس ApplicationDbContext را به اسمبلی جدید DataLayer منتقل می‌کنیم:


اسمبلی جدید Core1RtmEmptyTest.Entities از نوع NET Core Class Library. است و صرفا حاوی کلاس‌های موجودیت‌های برنامه‌است.
اسمبلی جدید Core1RtmEmptyTest.DataLayer نیز از نوع NET Core Class Library. بوده و حاوی تعاریف Context برنامه، به همراه Migrations و تنظیمات آن خواهد بود.

تا اینجا با این نقل و انتقالات، نیاز است وابستگی‌های DataLayer را اصلاح کنیم. بنابراین فایل project.json آن‌را گشوده و به نحو ذیل تکمیل نمائید:
{
  "version": "1.0.0-*",

    "dependencies": {
        "Core1RtmEmptyTest.Entities": "1.0.0-*",
        "Microsoft.EntityFrameworkCore": "1.0.0",
        "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
        "Microsoft.Extensions.Configuration.Abstractions": "1.0.0",
        "NETStandard.Library": "1.6.0"
    },

  "frameworks": {
    "netstandard1.6": {
      "imports": "dnxcore50"
    }
  }
}
به این صورت ارجاعی به اسمبلی Core1RtmEmptyTest.Entities به پروژه اضافه شده‌است (تا کلاس Person در ApplicationDbContext شناسایی شود) به همراه وابستگی‌های EF و SQL Server که مورد نیاز Context برنامه هستند.
وابستگی Microsoft.Extensions.Configuration.Abstractions برای کار با IConfigurationRoot اضافه شده‌است (دسترسی به تنظیمات برنامه از طریق تزریق وابستگی‌ها).

به علاوه اکنون به پروژه‌ی وب اصلی مراجعه کرده و فایل project.json آن‌را جهت افزودن ارجاعاتی به این دو اسمبلی جدید، ویرایش کنید:
{
    "dependencies": {
        // same as before
        "Core1RtmEmptyTest.Entities": "1.0.0-*",
        "Core1RtmEmptyTest.DataLayer": "1.0.0-*"
    }
}
به این ترتیب Startup برنامه می‌تواند محل جدید کلاس ApplicationDbContext را شناسایی کند و برنامه کامپایل شود.


فعال سازی Migrations و قرار دادن فایل‌های آن در اسمبلی Core1RtmEmptyTest.DataLayer

در ادامه اگر مانند قسمت قبل بخواهیم مهاجرت‌ها را اضافه کنیم، به خطای ذیل خواهیم رسید:
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest>dotnet ef migrations add InitialDatabase
Your target project 'Core1RtmEmptyTest' doesn't match your migrations assembly 'Core1RtmEmptyTest.DataLayer'.
Either change your target project or change your migrations assembly.
برای حل این مشکل، بجای اینکه دستور فوق را از مسیر src\Core1RtmEmptyTest صادر کنیم که همان ریشه‌ی اصلی پروژه‌ی وب است، اینبار باید دستور را از ریشه‌ی پروژه DataLayer صادر کنیم. اما اگر چنین کاری را انجام دهیم، پیام یافتن نشدن فایل اجرایی ابزارهای خط فرمان EF را دریافت می‌کنیم:
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef migrations add InitialDatabase
No executable found matching command "dotnet-ef"
علت اینجا است که باید مجددا فایل Core1RtmEmptyTest.DataLayer\project.json را گشوده و این ابزارها را در آن فعال کنیم:
{
     // same as before

    "tools": {
        "Microsoft.EntityFrameworkCore.Tools": {
            "version": "1.0.0-preview2-final",
            "imports": [
                "portable-net45+win8"
            ]
        }
    },

     // same as before
}
پس از فعال سازی ابزارهای EF در پروژه‌ی DataLayer، اکنون باز هم موفق به اجرای دستور فوق نخواهیم شد:
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef migrations add InitialDatabase
Could not invoke this command on the startup project 'Core1RtmEmptyTest.DataLayer'.
This preview of Entity Framework tools does not support commands on class library projects in ASP.NET Core and .NET Core applications.
عنوان می‌کند که پروژه‌ی startup را نمی‌تواند پیدا کند، برای حل این مشکل، دستور را به نحو ذیل ویرایش کنید:
 D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef --startup-project ../Core1RtmEmptyTest/ migrations add InitialDatabase
Done. To undo this action, use 'dotnet ef migrations remove'
در اینجا با ذکر صریح startup-project، عملیات تولید فایل‌های Migrations با موفقیت انجام شدند:



اعمال کلاس‌های Migrations تولید شده به بانک اطلاعاتی

پس از تولید موفقیت آمیز فایل‌های مهاجرت، برای اعمال آن‌ها به بانک اطلاعاتی، اینبار نیز دستور را از همان پوشه‌ی DataLayer با پارامتر پروژه‌ی آغازین اجرا می‌کنیم:
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef --startup-project ../Core1RtmEmptyTest/ database update
Applying migration '13950527070105_InitialDatabase'.
Done.
در اینجا نیز ذکر پارامتر startup-project جهت اجرای موفقیت آمیز دستور الزامی است.


بنابراین به صورت خلاصه

- ابتدا قسمت tools تنظیمات پروژه‌ی data layer را برای فعال سازی دستورات خط فرمان EF ویرایش کنید.
- سپس از طریق خط فرمان به پوشه‌ی data layer وارد شوید. اینبار باید دستورات EF را از ریشه‌ی این پوشه، بجای پوشه‌ی اصلی برنامه صادر کرد.
- در اینجا دستورات افزودن مهاجرت‌ها و به روز رسانی بانک اطلاعاتی، همانند قبل هستند. فقط ذکر محل واقع شدن پوشه‌ی آغازین برنامه توسط پارامتر startup-project الزامی است.
مطالب
دات نت 4 و کلاس Lazy

یکی از الگوهای برنامه نویسی شیء گرا، Lazy Initialization Pattern نام دارد که دات نت 4 پیاده سازی آن‌را سهولت بخشیده است.
در دات نت 4 کلاس جدیدی به فضای نام System اضافه شده است به نام Lazy و هدف از آن lazy initialization است؛ من ترجمه‌اش می‌کنم وهله سازی با تاخیر یا به آن on demand construction هم گفته‌اند (زمانی که به آن نیاز هست ساخته خواهد شد).
فرض کنید در برنامه‌ی خود نیاز به شیءایی دارید و ساخت این شیء بسیار پرهزینه است. نیازی نیست تا بلافاصله پس از تعریف، این شیء ساخته شود و تنها زمانیکه به آن نیاز است باید در دسترس باشد. کلاس Lazy جهت مدیریت اینگونه موارد ایجاد شده است. تنها کاری که در اینجا باید صورت گیرد، محصور کردن آن شیء هزینه‌بر توسط کلاس Lazy است:

Lazy<ExpensiveResource> ownedResource = new Lazy<ExpensiveResource>();

در این حالت برای دسترسی به شیء ساخته شده از ExpensiveResource ، می‌توان از خاصیت Value استفاده نمود (ownedResource.Value). تنها در حین اولین دسترسی به ownedResource.Value ، شیء ExpensiveResource ساخته خواهد شد و نه پیش از آن و نه در اولین جایی که تعریف شده است. پس از آن این حاصل cache شده و دیگر وهله سازی نخواهد شد.
ownedResource دارای خاصیت IsValueCreated نیز می‌باشد و جهت بررسی ایجاد آن شیء می‌تواند مورد استفاده قرار گیرد. برای مثال قصد داریم اطلاعات ExpensiveResource را ذخیره کنیم اما تنها در حالتیکه یکبار مورد استفاده قرار گرفته باشد.
کلاس Lazy دارای دو متد سازنده‌ی دیگر نیز می‌باشد:
public Lazy(bool isThreadSafe);
public Lazy(Func<T> valueFactory, bool isThreadSafe);

و هدف از آن استفاده‌ی صحیح از این متد در محیط‌های چند ریسمانی است. بدیهی است در این نوع محیط‌ ها علاقه‌ای نداریم که در یک لحظه توسط چندین ترد مختلف، سبب ایجاد وهله‌های ناخواسته‌ا‌ی از ExpensiveResource شویم و تنها یک مورد از آن کافی است یا به قولی thread safe, lazy initialization of expensive objects
بدیهی است اگر برنامه‌ی شما چند ریسمانی نیست می‌توانید این مکانیزم را کنسل کرده و اندکی کارآیی برنامه را با حذف قفل‌های همزمانی این کلاس بالا ببرید.

مثال اول:

using System;
using System.Threading;

namespace LazyExample
{
class Program
{
static void Main()
{
Console.WriteLine("Before assignment");
var slow = new Lazy<Slow>();
Console.WriteLine("After assignment");

Thread.Sleep(1000);

Console.WriteLine(slow);
Console.WriteLine(slow.Value);

Console.WriteLine("Press a key...");
Console.Read();
}
}


class Slow
{
public Slow()
{
Console.WriteLine("Start creation");
Thread.Sleep(2000);
Console.WriteLine("End creation");
}
}
}
خروجی این برنامه به شرح زیر است:

Before assignment
After assignment
Value is not created.
Start creation
End creation
LazyExample.Slow
Press a key...

همانطور که ملاحظه می‌کنید تنها در حالت دسترسی به مقدار Value شیء slow ، عملا وهله‌ای از آن ساخته خواهد شد.

مثال دوم:
شاید نیاز به مقدار دهی خواص کلاس پرهزینه‌ وجود داشته باشد. برای مثال علاقمندیم خاصیت SomeProperty کلاس ExpensiveClass را مقدار دهی کنیم. برای این منظور می‌توان به شکل ذیل عمل کرد (یک Func<t>را می‌توان به سازنده‌ی آن ارسال نمود):

using System;

namespace LazySample
{
class Program
{
static void Main()
{
var expensiveClass =
new Lazy<ExpensiveClass>
(
() =>
{
var fobj = new ExpensiveClass
{
SomeProperty = 100
};
return fobj;
}
);

Console.WriteLine("expensiveClass has value yet {0}",
expensiveClass.IsValueCreated);

Console.WriteLine("expensiveClass.SomeProperty value {0}",
(expensiveClass.Value).SomeProperty);

Console.WriteLine("expensiveClass has value yet {0}",
expensiveClass.IsValueCreated);

Console.WriteLine("Press a key...");
Console.Read();
}
}

class ExpensiveClass
{
public int SomeProperty { get; set; }

public ExpensiveClass()
{
Console.WriteLine("ExpensiveClass constructed");
}
}
}

کاربردها:
- علاقمندیم تا ایجاد یک شیء هزینه‌بر تنها پس از انجام یک سری امور هزینه‌بر دیگر صورت گیرد. برای مثال آیا تابحال شده است که با یک سیستم ماتریسی کار کنید و نیاز به چند گیگ حافظه برای پردازش آن داشته باشید؟! زمانیکه از کلاس Lazy استفاده نمائید، تمام اشیاء مورد استفاده به یکباره تخصیص حافظه پیدا نکرده و تنها در زمان استفاده از آن‌ها کار تخصیص منابع صورت خواهد گرفت.
- ایجاد یک شیء بسیار پر هزینه بوده و ممکن است در بسیاری از موارد اصلا نیازی به ایجاد و یا حتی استفاده از آن نباشد. برای مثال یک شیء کارمند را درنظر بگیرید که یکی از خواص این شیء، لیستی از مکان‌هایی است که این شخص قبلا در آنجاها کار کرده است. این اطلاعات نیز به طور کامل از بانک اطلاعاتی دریافت می‌شود. اگر در متدی، استفاده کننده از شیء کارمند هیچگاه اطلاعات مکان‌های کاری قبلی او را مورد استفاده قرار ندهد، آیا واقعا نیاز است که این اطلاعات به ازای هر بار ساخت وهله‌ای از شیء کارمند از دیتابیس دریافت شده و همچنین در حافظه ذخیره شود؟

اشتراک‌ها
کتابخانه fancygrid

Include files from code.fancygrid.com

 <link href="http://code.fancygrid.com/fancygrid.min.css" rel="stylesheet">
<script src="http://code.fancygrid.com/fancygrid.min.js"></script>
 

FancyGrid AngularJS directive

 <script src="http://code.fancygrid.com/fancygrid-angular.js"></script>
   
کتابخانه fancygrid
اشتراک‌ها
کتابخانه ngtimeago

time ago angularjs plugin allow to show the time in human readable format....

for example like few time ago,hours ago,etc  Demo

کتابخانه ngtimeago