آموزش Entity Framework

آموزش Entity Framework

بسم الله الرحمن الرحیم

 

آموزش Entity Framework

بهینه سازی Entity Framework

 

قبل از مطالعه این دوره آموزشی بهتر است دوره های زیر را نیز مطالعه کنید.

آموزش Code first

آموزش migration و Entity Framework در Code First

 

بخش اول 

بخش دوم

بخش سوم

 

در ادامه سری مقالات مربوط به بهینه سازی SQL و بهینه سازی کوئری در این دوره قصد داریم در خصوص افزایش کارایی در Entity Framework صحبت کنیم. برای مطالعه مقالات بهینه سازی می توانید از طریق لینک های زیر اقدام فرمایید.

بهینه سازی کوئری

بهینه سازی SQL

 

در تمامی برنامه ها اکثر برنامه نویسان برای واکشی و بروزرسانی اطلاعات درون پایگاه داده خود از دستوراتی استفاده می کنند که مستقیما بر روی پایگاه داده اجرا می شود (مانند FirstOrDefault و یا ToList()) این روش، روش اشتباهی نیست اما طبیعتا هزینه ای برای ارسال اطلاعات به سمت سرور و دریافت نتیجه اجرای این دستور به برنامه شما تحمیل خواهد شد.
یکی از روش هایی که می توانید این مشکل را بر طرف نمایید استفاده از دستور Local می باشد. این دستور به جای فعالیت بر روی پایگاه داده بر روی Context شما کار خواهد کرد و هیچگاه دستوری را برای SQL Server ارسال نخواهد کرد و همین امر باعث افزایش سرعت اجرای دستورات شما خواهد شد.
برای آموزش نحوه کار کردن با این دستور، یک مثال را انجام خواهیم داد.

یک پروژه MVC ایجاد کنید و Model ایی با نام Ably به آن اضافه کنید. این مدل می بایست به صورت زیر باشد:

 

public class Ably
    {
       public int Id { get; set; }
       public string PostName { get; set; }
    }

 

سپس Controller خود را ایجاد می کنیم و در آن کد زیر را برای load اطلاعات می نویسیم.

 

 

 

 

 

 

 

 

بسم الله الرحمن الرحیم

 

آموزش Entity Framework

بهینه سازی Entity Framework

 

قبل از مطالعه این دوره آموزشی بهتر است دوره های زیر را نیز مطالعه کنید.

آموزش Code first

آموزش migration و Entity Framework در Code First

 

بخش اول 

بخش دوم

بخش سوم

 

در ادامه سری مقالات مربوط به بهینه سازی SQL و بهینه سازی کوئری در این دوره قصد داریم در خصوص افزایش کارایی در Entity Framework صحبت کنیم. برای مطالعه مقالات بهینه سازی می توانید از طریق لینک های زیر اقدام فرمایید.

بهینه سازی کوئری

بهینه سازی SQL

 

در تمامی برنامه ها اکثر برنامه نویسان برای واکشی و بروزرسانی اطلاعات درون پایگاه داده خود از دستوراتی استفاده می کنند که مستقیما بر روی پایگاه داده اجرا می شود (مانند FirstOrDefault و یا ToList()) این روش، روش اشتباهی نیست اما طبیعتا هزینه ای برای ارسال اطلاعات به سمت سرور و دریافت نتیجه اجرای این دستور به برنامه شما تحمیل خواهد شد.
یکی از روش هایی که می توانید این مشکل را بر طرف نمایید استفاده از دستور Local می باشد. این دستور به جای فعالیت بر روی پایگاه داده بر روی Context شما کار خواهد کرد و هیچگاه دستوری را برای SQL Server ارسال نخواهد کرد و همین امر باعث افزایش سرعت اجرای دستورات شما خواهد شد.
برای آموزش نحوه کار کردن با این دستور، یک مثال را انجام خواهیم داد.

یک پروژه MVC ایجاد کنید و Model ایی با نام Ably به آن اضافه کنید. این مدل می بایست به صورت زیر باشد:

 

public class Ably
    {
       public int Id { get; set; }
       public string PostName { get; set; }
    }

 

سپس Controller خود را ایجاد می کنیم و در آن کد زیر را برای load اطلاعات می نویسیم.

 

#region Example Entity Framework Load

// Load all Ablies from the database into the context 
context.Ablies.Load();

// Add a new blog to the context 
context.Ablies.Add(new Ably { PostName = "The ASP.NET MVC" });

// Mark one of the existing Ablies as Deleted 
context.Ablies.Remove(context.Ablies.Find(1));

// Loop over the Ablies in the context. 
Response.Write("In Local: <br />");
foreach (var ably in context.Ablies.Local)
{
    Response.Write(string.Format(
        "Found {0}: {1} with state {2}< br/>",
        ably.Id,
        ably.PostName,
        context.Entry(ably).State));
}

// Perform a query against the database. 
Response.Write("\nIn DbSet query: ");
foreach (var ably in context.Ablies)
{
    Response.Write(string.Format(
        "Found {0}: {1} with state {2}< br/>",
        ably.Id,
        ably.PostName,
        context.Entry(ably).State));
}

#endregion
            

 

اگر دقت کنید کدهای بالا بسیار ساده هستند ما ابتدا تمامی رکورد های Model خود را Load کردیم. سپس یک رکورد جدید به Model خود اضافه کرده ایم و در خط بعد یک رکورد را جستجو و حذف کرده ایم و در نهایت با استفاده از دو حلقه foreach اطلاعات را چاپ کرده ایم.

حلقه اول رکوردهای مربوط به context را نمایش می دهد، این رکوردها رکورد هایی هستند که در ابتدای برنامه ما آنها را Load کردیم و سپس به این رکوردها یک رکورد اضافه کردیم و همچنین یک رکورد از این رکورد ها را حذف کرده ایم (این حلقه اطلاعات context را چاپ می کند و با پایگاه داده ما ارتباطی ندارد، هر چند context ما در ابتدای برنامه از روی پایگاه داده پر شده است).

حلقه دوم رکوردهای موجود در پایگاه داده را چاپ می کند.

اگر ما قبلا در Table خود دو رکورد به صورت " The Code First POST " با ID یک (1) و " The Entity Framework POST" با ID دو (2) داشته باشیم. خروجی برنامه ما به صورت زیر است.

 

In Local:
Found 0: The ASP.NET MVC POST with state Added
Found 2: The Entity Framework POST with state Unchanged

In DbSet query:
Found 1: The Code First POST with state Deleted
Found 2: The Entity Framework POST with state Unchanged

 

همانطور که مشاهده می کنید با استفاده از دستور context.Entry(ably).State ما وضعیت هر یک از رکورد ها را در اینجا نمایش داده ایم. این دستور در واقع مقدار رکورد را درون پایگاه داده بررسی می کند بر اساس وضعیت موجود یکی از 5 مقدار زیر را می تواند داشته باشد.
 

Added
 Deleted
 Detached
 Modified
 Unchanged

 

در خروجی مثال بالا همانطور که مشاهده می کنید رکورد جدید اضافه شده “The ASP.NET MVC POST” دارای وضعیت Added است و Id این رکورد برابر 0 است زیرا این رکورد هنوز در پایگاه داده اضافه نشده است و Id ایی نیز به انتساب داده نشده است.

رکورد " The Code First POST " نیز دارای وضعیت Deleted است و همانطور که می بینید در بخش نمایش اطلاعات Local این رکورد وجود ندارد زیرا این رکورد توسط ما حذف شده اما چون هنوز پایگاه داده ما بر روز نشده است در بخش نمایش اطلاعات DbSet این رکورد با وضعیت Deleted نمایش داده شده است.

در نهایت رکورد “The ASP.NET MVC POST” نیز به در بخش DbSet مشاهده نمی شود زیرا این رکورد نیز به پایگاه داده هنوز اضافه نشده است.
 

Entity Framework

چند نکته

برای استفاده از این دستور ترجیحا آخرین نسخه Entity Framework را نصب کنید
این دستور تا زمانی که Model شما به Context اضافه نشده است قابل دسترسی نیست، پس حتما باید برنامه Build شود. در صورتی که این دستور را مشاهده نکردید update-database را اجرا کنید.
 

 

دستور Local

با استفاده از این دستور شما می توانید به جای کار بر روی اطلاعات پایگاه داده، ابتدا اطلاعات مورد نظر خود را درون Context بارگذاری (load) کنید و سپس بر روی این اطلاعات دستورات خود را اجرا و در نهایت این تغییرات به پایگاه داده ارسال کنید.
این دستور به همراه دستور Load برای انجام عملیات ها و کاهش هزینه بر روی دیتابیس مورد استفاده قرار می گیرد.

در پروژه ایجاد شده دستورات زیرا را اضافه کنید تا با استفاده از این دستورات اطلاعات پایگاه داده را واکشی کنیم و پس از آن بر روی این اطلاعات عملیات های خود را انجام دهیم.

 

#region Example Entity Framework Local
// Load some posts from the database into the context 
context.Ablies.Where(p => p.PostName.Contains("Entity Framework")).Load();

// Get the local collection and make some changes to it 
var localAbly = context.Ablies.Local;
localAbly.Add(new Ably { PostName = "What's New in EF" });
localAbly.Remove(context.Ablies.Find(1));

// Loop over the posts in the context. 
Response.Write("In Local after entity-framework query:  < br/>");
foreach (var ably in context.Ablies.Local)
{
    Response.Write(string.Format(
        "Found {0}: {1} with state {2} < br/>",
        ably.Id,
        ably.PostName,
        context.Entry(ably).State));
}


var ably1 = context.Ablies.Find(1);
Response.Write(string.Format(
    "State of post 1: {0} is {1}",
    ably1.PostName,
    context.Entry(ably1).State));

// Query some more posts from the database 
context.Ablies.Where(p => p.PostName.Contains("MVC")).Load();

// Loop over the posts in the context again. 
Response.Write("\nIn Local after MVC query: < br/>");
foreach (var post in context.Ablies.Local)
{
    Response.Write(string.Format(
        "Found {0}: {1} with state {2}< br/>",
        post.Id,
        post.PostName,
        context.Entry(post).State));
}

 

پس از اجرای این دستورات خروجی ما به صورت زیر خواهد بود:
 

 

In Local after entity-framework query:
Found 3: MVC & Entity Framework4 with state Unchanged
Found 5: MVC & Entity Framework5 with state Unchanged
Found 0: What's New in EF with state Added
State of post 1: EF Beginners Guide is Deleted

In Local after asp.net query:
Found 3: MVC & Entity Framework4 with state Unchanged
Found 5: MVC & Entity Framework5 with state Unchanged
Found 0: What's New in EF with state Added
Found 4: ASP.NET MVC with state Unchanged

 

با اجرای دستور اول

 

context.Ablies.Where(p => p.PostName.Contains("Entity Framework")).Load();


تنها رکوردهایی بازیابی می شوند که کلمه Entity Framework در آنها وجود دارد سپس تمامی این رکورد ها توسط دستور Local درون localAbly ذخیره می شوند. در خط بعد یک رکورد جدید به رکوردهای Local اضافه می شود و همچنین در خط بعد از رکوردهای موجود Local، رکوردی با ID شماره یک را حذف می کنیم.

حال تمامی اطلاعات local خود را چاپ می کنیم. پس از چاپ این اطلاعات رکوردی با Id شماره یک را جستجو می کنیم و اطلاعات آن را در شی ably1 می ریزیم. در نهایت اطلاعات این شی را چاپ می کنیم، همانطور که مشاهده می کنید این شی در وضعیت Deleted قرار دارد.

 

در بخش بعد پس از اجرای دستور زیر تمامی رکوردهایی که PostName آنها شامل MVC است را از پایگاه داده واکشی می کنیم و آنها را چاپ می کنیم.

context.Ablies.Where(p => p.PostName.Contains("MVC")).Load();

در این بخش اتفاق خاصی نیافتاده فقط رکوردهایی که واکشی کرده ایم متفاوت شده اند و همچنین رکوردی که جدید اضافه کردیم ("What's New in EF") با همان وضعیت قبی خود یعنی Added نمایش داده شده است.

 

رکورد جدید اضافه شده " What's New in EF" ابتدا به Collection مربوط به Context اضافه می شود و پس از اجرای دستور SaveChanges این رکورد به پایگاه داده اضافه خواهد شد. همچنین رکورد " EF Beginners Guide" به عنوان رکوردی که می بایست حذف شود در Context علامت گذاری شده است و این رکورد نیز پس از اجرای دستور SaveChanges از پایگاه داده حذف خواهد شد.

 در اینجا ما دستور SaveChange را می توانیم اضافه کنیم و خروجی را مجددا بررسی کنیم. برای انجام این کار دستورات زیر را اجرا کنید.

 

#region Example Entity Framework Local & SaveChange

//Save change
context.SaveChanges();

// Get the local collection with "Entity Framework" Keyword
context.Ablies.Where(p => p.PostName.Contains("Entity Framework")).Load();


// Loop over the posts in the context. 
Response.Write("In Local after entity-framework query:  < br/>");
foreach (var ably in context.Ablies.Local)
{
    Response.Write(string.Format(
        "Found {0}: {1} with state {2} < br/>",
        ably.Id,
        ably.PostName,
        context.Entry(ably).State));
}




// Query some more posts from the database with "MVC" Keyword
context.Ablies.Where(p => p.PostName.Contains("MVC")).Load();

// Loop over the posts in the context again. 
Response.Write("\nIn Local after MVC query: < br/>");
foreach (var post in context.Ablies.Local)
{
    Response.Write(string.Format(
        "Found {0}: {1} with state {2}< br/>",
        post.Id,
        post.PostName,
        context.Entry(post).State));
}

 

همانطور که در کد بالا مشاهده می کنید ما در ابتدا تمامی تغییرات را بر روی پایگاه داده خود ذخیره کردیم و سپس با استفاده از دستور

context.Ablies.Where(p => p.PostName.Contains("Entity Framework")).Load();

تمام رکوردهایی که کلمه Entity Framework در آن قید شده است را Load کردیم و در نهایت توسط یک حلقه این رکورد ها را چاپ کردیم.

در بخش بعد نیز مجددا تمامی رکوردهایی که کلمه MVC در آن قید شده است را به صورت زیر Load کردیم.

context.Ablies.Where(p => p.PostName.Contains("MVC")).Load();

این رکوردها را نیز مانند بخش قبل با استفاده از یک حلقه foreach چاپ کردیم.

خروجی ما به صورت زیر خواهد بود.

In Local after entity-framework query:
Found 3: MVC & Entity Framework4 with state Unchanged
Found 5: MVC & Entity Framework5 with state Unchanged
Found 0: What's New in EF with state Unchanged

In Local after asp.net query:
Found 3: MVC & Entity Framework4 with state Unchanged
Found 5: MVC & Entity Framework5 with state Unchanged
Found 0: What's New in EF with state Unchanged
Found 4: ASP.NET MVC with state Unchanged

 

اگر خروجی این مثال را با مثال قبل مقایسه کنید مشاهده خواهید کرد که رکورد زیر دیگر نمایش داده نمی شود، زیرا این رکورد به دلیل علامت گذاری شدن برای حذف پس از دستور SaveChanges از پایگاه داده ما حذف شده است.

State of post 1: EF Beginners Guide is Deleted

 

همچنین State رکورد زیر نیز از Added به Unchanged تغییر داده شده است، زیرا این رکورد نیز به پایگاه داده اضافه شده است.

Found 0: What's New in EF with state Added

 


نکته:
اگر در برنامه خود از تعداد زیادی Entity استفاده می کنید این روش و استفاده از دستورات Local پیشنهاد نمی شود زیرا واکشی این همه اطلاعات عملا مخالف بهینه سازی برنامه است اما برعکس اگر قرار است تعداد زیادی رکورد را تغییر دهید و یا اطلاعات زیادی را در یک زمان درج کنید می توانید ابتدا تمامی عملیات های خود را اجرا کنید و در نهایت تنها یک بار این تغییرات را به SQL Server ارسال کنید.

 

در خصوص اینکه چگونه می توانیم وضعیت این رکوردها را تغییر دهیم و سایر مطالب مربوط به مدیریت Entry().State ها در بخش های بعدی صحبت خواهیم کرد.

نظرات یا سوالات خودرا با ما درمیان بگذارید

0912 097 5516 :شماره تماس
0713 625 1757 :شماره تماس